review: gate web Reddit enrichment behind EXCLUDE_SOURCES
PR #366 routes Reddit URLs found in web-search results through the public Reddit JSON API to recover thread body + top comments (the Claude Code WebFetch tool blocks reddit.com directly). That bypass is sound and the fixed problem is real - but the always-on shape ignores user intent on source gating. A user who sets EXCLUDE_SOURCES=reddit to suppress Reddit results would still get Reddit content smuggled back in via web-search URLs that happen to point at reddit.com threads. This contradicts the suppression contract that EXCLUDE_SOURCES is supposed to provide (see lib/pipeline.available_sources where the same env var gates the top-level Reddit source). Add a _reddit_excluded(config) check in web_search() that mirrors the parsing pattern from lib/pipeline (comma-separated, case-insensitive, whitespace-tolerant). When reddit is in EXCLUDE_SOURCES, skip the enrichment pass entirely - the web results themselves still flow through, but they're not augmented with Reddit body/comments. Four new tests in test_grounding_v3.py cover: - EXCLUDE_SOURCES=reddit skips enrichment - case-insensitive parsing matches REDDIT/Reddit/whitespace-padded/csv - Other sources in EXCLUDE_SOURCES don't trigger the gate - Enrichment runs normally when reddit isn't excluded 19/19 grounding tests pass.
This commit is contained in:
@@ -190,5 +190,42 @@ class WebSearchDispatchTests(unittest.TestCase):
|
||||
grounding.web_search("test", ("2026-02-25", "2026-03-27"), {}, backend="google")
|
||||
|
||||
|
||||
class RedditEnrichmentGateTests(unittest.TestCase):
|
||||
"""EXCLUDE_SOURCES=reddit must suppress the web-search Reddit enrichment.
|
||||
|
||||
Otherwise a user who explicitly excluded Reddit would still get Reddit
|
||||
content smuggled back in via web-search URLs that happen to point at
|
||||
reddit.com threads.
|
||||
"""
|
||||
|
||||
def test_reddit_excluded_via_exclude_sources_skips_enrichment(self):
|
||||
config = {"BRAVE_API_KEY": "k", "EXCLUDE_SOURCES": "reddit"}
|
||||
items = [{"url": "https://www.reddit.com/r/python/comments/abc/title/", "snippet": "original"}]
|
||||
with patch("lib.grounding.brave_search", return_value=(items, {})), \
|
||||
patch("lib.grounding._enrich_reddit_items") as enrich_mock:
|
||||
grounding.web_search("test", ("2026-02-25", "2026-03-27"), config, backend="auto")
|
||||
enrich_mock.assert_not_called()
|
||||
|
||||
def test_reddit_excluded_case_insensitive(self):
|
||||
for value in ("REDDIT", "Reddit", " reddit ", "x,reddit,y"):
|
||||
config = {"BRAVE_API_KEY": "k", "EXCLUDE_SOURCES": value}
|
||||
self.assertTrue(
|
||||
grounding._reddit_excluded(config),
|
||||
msg=f"_reddit_excluded should be True for EXCLUDE_SOURCES={value!r}",
|
||||
)
|
||||
|
||||
def test_reddit_not_excluded_when_other_sources_listed(self):
|
||||
config = {"EXCLUDE_SOURCES": "tiktok,instagram"}
|
||||
self.assertFalse(grounding._reddit_excluded(config))
|
||||
|
||||
def test_enrichment_runs_when_reddit_not_excluded(self):
|
||||
config = {"BRAVE_API_KEY": "k"}
|
||||
items = [{"url": "https://www.reddit.com/r/python/comments/abc/title/", "snippet": "original"}]
|
||||
with patch("lib.grounding.brave_search", return_value=(items, {})), \
|
||||
patch("lib.grounding._enrich_reddit_items", return_value=items) as enrich_mock:
|
||||
grounding.web_search("test", ("2026-02-25", "2026-03-27"), config, backend="auto")
|
||||
enrich_mock.assert_called_once()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user