feat(quality): YouTube relevance scoring and cross-source linking

YouTube videos now get real relevance scores based on token overlap
between the search query and video title (was hardcoded at 0.7).
Uses ratio overlap with stopword removal, floored at 0.1.

Cross-source linking annotates items that discuss the same story
across different platforms (e.g., Reddit + HN + X). Items get
bidirectional cross_refs displayed as [xref: R3, HN5] in compact
output so Claude can triangulate multi-platform coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt Van Horn
2026-02-25 10:46:58 -08:00
parent f60a4359a0
commit 0591f55f0e
8 changed files with 642 additions and 14 deletions
+166
View File
@@ -0,0 +1,166 @@
"""Tests for cross-source linking."""
import sys
import unittest
from pathlib import Path
# Add lib to path
sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
from lib import dedupe, schema
class TestCrossSourceLink(unittest.TestCase):
def _make_reddit(self, id, title, score=50):
item = schema.RedditItem(id=id, title=title, url="", subreddit="test")
item.score = score
return item
def _make_hn(self, id, title, score=50):
item = schema.HackerNewsItem(id=id, title=title, url="", hn_url="", author="user")
item.score = score
return item
def _make_x(self, id, text, score=50):
item = schema.XItem(id=id, text=text, url="", author_handle="user")
item.score = score
return item
def _make_yt(self, id, title, score=50):
item = schema.YouTubeItem(id=id, title=title, url="", channel_name="ch")
item.score = score
return item
def _make_web(self, id, title, score=50):
item = schema.WebSearchItem(id=id, title=title, url="", source_domain="example.com", snippet="")
item.score = score
return item
def test_no_crossrefs_for_unrelated(self):
reddit = [self._make_reddit("R1", "Best Claude Code Tips")]
hn = [self._make_hn("HN1", "Python Django Release Notes")]
dedupe.cross_source_link(reddit, hn)
self.assertEqual(reddit[0].cross_refs, [])
self.assertEqual(hn[0].cross_refs, [])
def test_bidirectional_link(self):
reddit = [self._make_reddit("R1", "OpenAI launches GPT-5 with new features")]
hn = [self._make_hn("HN1", "OpenAI launches GPT-5 with new features")]
dedupe.cross_source_link(reddit, hn)
self.assertIn("HN1", reddit[0].cross_refs)
self.assertIn("R1", hn[0].cross_refs)
def test_multi_source_link(self):
reddit = [self._make_reddit("R1", "Claude Code gets new skill system")]
hn = [self._make_hn("HN1", "Claude Code gets new skill system")]
yt = [self._make_yt("YT1", "Claude Code gets new skill system")]
dedupe.cross_source_link(reddit, hn, yt)
# All three should reference each other
self.assertEqual(len(reddit[0].cross_refs), 2)
self.assertEqual(len(hn[0].cross_refs), 2)
self.assertEqual(len(yt[0].cross_refs), 2)
def test_same_source_not_linked(self):
reddit = [
self._make_reddit("R1", "OpenAI GPT-5 launch details"),
self._make_reddit("R2", "OpenAI GPT-5 launch details"),
]
dedupe.cross_source_link(reddit)
self.assertEqual(reddit[0].cross_refs, [])
self.assertEqual(reddit[1].cross_refs, [])
def test_x_text_truncation_helps(self):
# Truncation increases similarity vs full tweet.
# A near-identical short tweet should match a Reddit title.
reddit = [self._make_reddit("R1", "Anthropic releases Claude 4 model")]
x_short = [self._make_x("X1", "Anthropic releases Claude 4 model today!")]
dedupe.cross_source_link(reddit, x_short)
self.assertIn("X1", reddit[0].cross_refs)
self.assertIn("R1", x_short[0].cross_refs)
def test_long_x_text_may_not_match(self):
# When a tweet diverges significantly after the shared prefix,
# Jaccard drops below 0.5 even with truncation. This is expected.
reddit = [self._make_reddit("R1", "Anthropic releases Claude 4 model")]
x_long = [self._make_x("X1",
"Anthropic releases Claude 4 model and it's incredible. "
"The reasoning capabilities are next level. Just tested it "
"on my entire codebase and it understood everything."
)]
dedupe.cross_source_link(reddit, x_long)
# May or may not match depending on trigram overlap - just verify no crash
self.assertIsInstance(reddit[0].cross_refs, list)
def test_empty_lists(self):
# Should not crash
dedupe.cross_source_link([], [], [])
def test_single_item(self):
reddit = [self._make_reddit("R1", "Test item")]
dedupe.cross_source_link(reddit)
self.assertEqual(reddit[0].cross_refs, [])
def test_no_duplicate_refs(self):
reddit = [self._make_reddit("R1", "Same exact title repeated")]
hn = [self._make_hn("HN1", "Same exact title repeated")]
# Call twice - should not duplicate refs
dedupe.cross_source_link(reddit, hn)
dedupe.cross_source_link(reddit, hn)
self.assertEqual(reddit[0].cross_refs.count("HN1"), 1)
self.assertEqual(hn[0].cross_refs.count("R1"), 1)
def test_web_items_linked(self):
web = [self._make_web("W1", "Claude Code skill system overview")]
hn = [self._make_hn("HN1", "Claude Code skill system overview")]
dedupe.cross_source_link(web, hn)
self.assertIn("HN1", web[0].cross_refs)
self.assertIn("W1", hn[0].cross_refs)
class TestCrossRefsSchemaRoundTrip(unittest.TestCase):
def test_reddit_roundtrip(self):
item = schema.RedditItem(id="R1", title="Test", url="", subreddit="test",
cross_refs=["HN1", "X2"])
d = item.to_dict()
self.assertEqual(d['cross_refs'], ["HN1", "X2"])
def test_reddit_empty_crossrefs_omitted(self):
item = schema.RedditItem(id="R1", title="Test", url="", subreddit="test")
d = item.to_dict()
self.assertNotIn('cross_refs', d)
def test_report_roundtrip(self):
report = schema.Report(
topic="test", range_from="2026-01-01", range_to="2026-02-01",
generated_at="2026-02-01T00:00:00Z", mode="both",
reddit=[schema.RedditItem(id="R1", title="T", url="", subreddit="s",
cross_refs=["HN1"])],
hackernews=[schema.HackerNewsItem(id="HN1", title="T", url="", hn_url="",
author="u", cross_refs=["R1"])],
)
d = report.to_dict()
restored = schema.Report.from_dict(d)
self.assertEqual(restored.reddit[0].cross_refs, ["HN1"])
self.assertEqual(restored.hackernews[0].cross_refs, ["R1"])
class TestGetCrossSourceText(unittest.TestCase):
def test_x_truncated(self):
item = schema.XItem(id="X1", text="A" * 200, url="", author_handle="u")
result = dedupe._get_cross_source_text(item)
self.assertEqual(len(result), 100)
def test_reddit_uses_title(self):
item = schema.RedditItem(id="R1", title="My Title", url="", subreddit="s")
result = dedupe._get_cross_source_text(item)
self.assertEqual(result, "My Title")
def test_web_uses_title(self):
item = schema.WebSearchItem(id="W1", title="Web Title", url="",
source_domain="example.com", snippet="snip")
result = dedupe._get_cross_source_text(item)
self.assertEqual(result, "Web Title")
if __name__ == "__main__":
unittest.main()
+110
View File
@@ -0,0 +1,110 @@
"""Tests for YouTube relevance scoring."""
import sys
import unittest
from pathlib import Path
# Add lib to path
sys.path.insert(0, str(Path(__file__).parent.parent / "scripts"))
from lib.youtube_yt import _compute_relevance, _tokenize
class TestTokenize(unittest.TestCase):
def test_basic(self):
tokens = _tokenize("Claude Code Tutorial")
self.assertIn("claude", tokens)
self.assertIn("code", tokens)
self.assertIn("tutorial", tokens)
def test_removes_stopwords(self):
tokens = _tokenize("how to use Claude Code for beginners")
self.assertNotIn("how", tokens)
self.assertNotIn("to", tokens)
self.assertNotIn("for", tokens)
self.assertIn("claude", tokens)
self.assertIn("code", tokens)
self.assertIn("beginners", tokens)
def test_strips_punctuation(self):
tokens = _tokenize("What's new in Claude?")
self.assertIn("claude", tokens)
self.assertNotIn("what's", tokens)
def test_drops_single_char(self):
tokens = _tokenize("a b c Claude")
self.assertNotIn("a", tokens)
self.assertNotIn("b", tokens)
self.assertIn("claude", tokens)
def test_empty(self):
tokens = _tokenize("")
self.assertEqual(tokens, set())
def test_all_stopwords(self):
tokens = _tokenize("the a an to for how")
self.assertEqual(tokens, set())
class TestComputeRelevance(unittest.TestCase):
def test_exact_match(self):
result = _compute_relevance("Claude Code", "Claude Code")
self.assertEqual(result, 1.0)
def test_full_match_in_longer_title(self):
result = _compute_relevance("Claude Code", "Claude Code Tutorial")
self.assertEqual(result, 1.0)
def test_partial_match(self):
result = _compute_relevance("Claude Code Tips", "Claude Tips for Beginners")
self.assertGreater(result, 0.5)
self.assertLess(result, 1.0)
def test_no_match(self):
result = _compute_relevance("Claude Code", "Python Web Scraping")
self.assertEqual(result, 0.1) # Floor
def test_empty_query_returns_neutral(self):
result = _compute_relevance("", "Some Video Title")
self.assertEqual(result, 0.5)
def test_stopword_only_query(self):
result = _compute_relevance("how to the", "Some Video Title")
self.assertEqual(result, 0.5)
def test_empty_title(self):
result = _compute_relevance("Claude Code", "")
self.assertEqual(result, 0.1) # Floor
def test_case_insensitive(self):
result = _compute_relevance("claude code", "CLAUDE CODE Tutorial")
self.assertEqual(result, 1.0)
def test_stopwords_in_title_dont_inflate(self):
# "Claude Code" query against a title with lots of stopwords
# Should still match well since Claude and Code are present
result = _compute_relevance(
"Claude Code",
"How To Use Claude Code For Complete Beginners"
)
self.assertEqual(result, 1.0)
def test_floor_at_0_1(self):
result = _compute_relevance("quantum computing", "cat videos compilation")
self.assertEqual(result, 0.1)
def test_cap_at_1_0(self):
result = _compute_relevance("AI", "AI AI AI AI AI")
self.assertLessEqual(result, 1.0)
def test_single_word_query(self):
result = _compute_relevance("Seedance", "Seedance AI Video Generator Review")
self.assertEqual(result, 1.0)
def test_single_word_no_match(self):
result = _compute_relevance("Seedance", "Random cooking video")
self.assertEqual(result, 0.1)
if __name__ == "__main__":
unittest.main()