From 306d8c2d73330aa2af307e196a1fb606a678e6a2 Mon Sep 17 00:00:00 2001 From: Trevin Chow Date: Sat, 16 May 2026 19:30:27 -0700 Subject: [PATCH] fix(env): wire EXCLUDE_SOURCES through get_config + SKILL.md integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original PR added EXCLUDE_SOURCES filtering to pipeline.available_sources() and to the check-config.sh banner, but env.py::get_config() builds its config dict from a hardcoded keys list that didn't include EXCLUDE_SOURCES. The result: setting EXCLUDE_SOURCES in the environment silently no-op'd through the Python pipeline. Only the bash hook (which reads shell env directly) worked. The PR's unit tests didn't catch this because they construct config dicts directly, bypassing get_config(). Changes: - Add ('EXCLUDE_SOURCES', '') to env.py's keys list so the env var actually propagates into config. - Add an end-to-end regression test that goes through get_config() rather than constructing config dicts directly. - Document EXCLUDE_SOURCES in SKILL.md's source-list checklist so the model invoking the skill knows to subtract excluded sources before displaying the active-sources line. (Per AGENTS.md: engine flags without SKILL.md prose are incomplete — the agent invoking the skill won't know the flag exists.) --- skills/last30days/SKILL.md | 1 + skills/last30days/scripts/lib/env.py | 1 + tests/test_pipeline_v3.py | 24 ++++++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/skills/last30days/SKILL.md b/skills/last30days/SKILL.md index a7db05f..2b47dc0 100644 --- a/skills/last30days/SKILL.md +++ b/skills/last30days/SKILL.md @@ -327,6 +327,7 @@ Common patterns: - If SCRAPECREATORS_API_KEY is set and INCLUDE_SOURCES contains pinterest: add Pinterest - If BSKY_HANDLE and BSKY_APP_PASSWORD are set: add Bluesky - If OPENROUTER_API_KEY is set: add Perplexity +- If EXCLUDE_SOURCES is set (comma-separated, case-insensitive): drop any matching source from the list above before displaying Then display (use "and more" if 5+ sources, otherwise list all with Oxford comma): diff --git a/skills/last30days/scripts/lib/env.py b/skills/last30days/scripts/lib/env.py index e78f012..81f5641 100644 --- a/skills/last30days/scripts/lib/env.py +++ b/skills/last30days/scripts/lib/env.py @@ -265,6 +265,7 @@ def get_config() -> dict[str, Any]: ('FROM_BROWSER', None), ('SETUP_COMPLETE', None), ('INCLUDE_SOURCES', ''), + ('EXCLUDE_SOURCES', ''), ] for key, default in keys: diff --git a/tests/test_pipeline_v3.py b/tests/test_pipeline_v3.py index 54dcc18..5ccddd1 100644 --- a/tests/test_pipeline_v3.py +++ b/tests/test_pipeline_v3.py @@ -956,5 +956,29 @@ class TestExcludeSources(unittest.TestCase): self.assertIn("reddit", sources) +class TestExcludeSourcesEndToEnd(unittest.TestCase): + """Wiring regression: EXCLUDE_SOURCES from the process environment must + reach available_sources() via env.get_config(). The unit tests above + construct config dicts directly; this one exercises the env-to-config + path so a missing entry in env.py's keys list is caught immediately.""" + + def test_exclude_sources_from_env_propagates_through_get_config(self): + import os + from unittest.mock import patch as _patch + from lib import env as env_mod + from importlib import reload + with _patch.dict(os.environ, { + "LAST30DAYS_CONFIG_DIR": "", + "EXCLUDE_SOURCES": "tiktok,instagram", + "SCRAPECREATORS_API_KEY": "fake", + }, clear=False): + reload(env_mod) + cfg = env_mod.get_config() + self.assertEqual(cfg.get("EXCLUDE_SOURCES"), "tiktok,instagram") + sources = pipeline.available_sources(cfg) + self.assertNotIn("tiktok", sources) + self.assertNotIn("instagram", sources) + + if __name__ == "__main__": unittest.main()