From 223954979994df4f323210699412a65684fbab99 Mon Sep 17 00:00:00 2001 From: jay Date: Fri, 19 Jun 2026 20:29:31 -0400 Subject: [PATCH] Closer to Home: gate "Near you" on high/medium confidence (both modes) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex polish before deploy: anything elevated as Near you / Close to home must have geo_confidence in (high, medium) — the feature's promise is relevance. Country-only mode now gates "near" too; since it has no "country" tier, the "world" scope is widened to absorb low-confidence home-country stories so they surface there instead of vanishing between tiers (the same edge-case class, fixed). State mode unchanged. 364 tests green. Co-Authored-By: Claude Opus 4.8 --- goodnews/queries.py | 20 +++++++++++++++++--- tests/test_geo_feed.py | 13 +++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/goodnews/queries.py b/goodnews/queries.py index 7e61d8b..a0a39ce 100644 --- a/goodnews/queries.py +++ b/goodnews/queries.py @@ -171,13 +171,17 @@ def feed( # shaky location). Untagged articles have no places, so they land in 'world' — never # lost while the backfill is still running. if geo_scope == "near": + # Anything elevated as "Near you" / "Close to home" requires high/medium geo + # confidence — the feature's promise is relevance, so don't surface shaky locals. if home_state and home_country: clauses.append( "g.confidence IN ('high','medium') AND EXISTS (SELECT 1 FROM article_places p " "WHERE p.article_id = a.id AND p.country_code = ? AND p.state_code = ?)") params.extend([home_country, home_state]) elif home_country: - clauses.append("EXISTS (SELECT 1 FROM article_places p WHERE p.article_id = a.id AND p.country_code = ?)") + clauses.append( + "g.confidence IN ('high','medium') AND EXISTS (SELECT 1 FROM article_places p " + "WHERE p.article_id = a.id AND p.country_code = ?)") params.append(home_country) elif geo_scope == "country" and home_country: clauses.append("EXISTS (SELECT 1 FROM article_places p WHERE p.article_id = a.id AND p.country_code = ?)") @@ -191,8 +195,18 @@ def feed( "WHERE p2.article_id = a.id AND p2.country_code = ? AND p2.state_code = ?))") params.extend([home_country, home_state]) elif geo_scope == "world" and home_country: - clauses.append("NOT EXISTS (SELECT 1 FROM article_places p WHERE p.article_id = a.id AND p.country_code = ?)") - params.append(home_country) + if home_state: + # State mode: the "country" tier catches all home-country stories (incl. + # low-confidence ones), so world is simply everything outside your country. + clauses.append("NOT EXISTS (SELECT 1 FROM article_places p WHERE p.article_id = a.id AND p.country_code = ?)") + params.append(home_country) + else: + # Country-only mode has no "country" tier, so a LOW-confidence home-country + # story isn't "near" and must land here rather than vanish between tiers. + clauses.append( + "NOT (g.confidence IN ('high','medium') AND EXISTS (SELECT 1 FROM article_places p " + "WHERE p.article_id = a.id AND p.country_code = ?))") + params.append(home_country) where = "WHERE " + " AND ".join(clauses) params.extend([limit, offset]) diff --git a/tests/test_geo_feed.py b/tests/test_geo_feed.py index 67d095e..5e0ee20 100644 --- a/tests/test_geo_feed.py +++ b/tests/test_geo_feed.py @@ -67,13 +67,18 @@ def test_sparse_near_folds_into_country(app_db): assert "country" in _sections(r["items"]) # US stories still surface as your country -def test_country_only_home_has_no_country_tier(app_db): +def test_country_only_home_gates_near_on_confidence(app_db): r = TestClient(app_db).get("/api/feed?home=US&limit=50").json() - secs = set(_sections(r["items"])) + items = r["items"] + secs = set(_sections(items)) assert "country" not in secs # no state -> near IS the whole country assert secs <= {"near", "world"} - near_ids = {it["id"] for it in r["items"] if it["section"] == "near"} - assert near_ids == {1, 2, 3, 4, 5, 6, 7, 8} # all US (incl. the low-conf one, country match) + near_ids = {it["id"] for it in items if it["section"] == "near"} + # "Near you" requires high/medium confidence: high-conf US stories only, NOT the + # low-confidence US story (#5), which must still appear, in "world". + assert near_ids == {1, 2, 3, 4, 6, 7, 8} + a5 = next(it for it in items if it["id"] == 5) + assert a5["section"] == "world" # low-conf home-country -> world, not vanished def test_no_home_is_unchanged_and_unsectioned(app_db):