Scope dial v2: Nearby / Region / Country / World radius on the homepage
Codex-approved evolution: the reader controls the "emotional radius" of the landing. - Census-region "Regional" grain (geo.region_of / region_states). Scope-aware tiering (queries.home_tiers): closest->widest lead, confidence-gated on state + region, never a hard filter — blends outward so the set is always full. 'world' = the global brief. - queries.home_brief takes a scope; /api/brief gains a scope param (nearby|region| country|world). Country-only / non-US homes collapse to country. - Homepage dial replaces the 2-button toggle: adaptive stops (4 with a US state, else Country/World), persisted scope, "Good news closest first" framing. Concrete, soft section labels (Around New Jersey / Across the Northeast / Across the US / Around the world) so the reader sees the dial worked. Backend 366 + frontend tests green. (Latest feed still on v1 local-first; aligning it to the dial is the immediate follow-up.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+16
-8
@@ -82,20 +82,28 @@ def test_country_only_home_gates_near_on_confidence(app_db):
|
||||
|
||||
|
||||
def test_home_brief_leads_with_local(app_db):
|
||||
# The landing's /api/brief?home=US-NY leads with high-confidence NY good news,
|
||||
# tags items by section, and titles it "Close to home". The low-conf NY story (#5)
|
||||
# is not elevated as local.
|
||||
# /api/brief?home=US-NY defaults to the 'nearby' scope: leads with the 'state' tier
|
||||
# (high-confidence NY), titles it "Close to home", and never elevates the low-conf
|
||||
# NY story (#5). CA stories (a different census region) fall to 'country'.
|
||||
r = TestClient(app_db).get("/api/brief?home=US-NY&limit=10").json()
|
||||
assert r["title"] == "Close to home"
|
||||
near_ids = {it["id"] for it in r["items"] if it["section"] == "near"}
|
||||
assert near_ids == {1, 2, 3, 4} # the high-conf NY stories
|
||||
# near items all appear before any world item (local leads)
|
||||
state_ids = {it["id"] for it in r["items"] if it["section"] == "state"}
|
||||
assert state_ids == {1, 2, 3, 4} # high-conf NY only
|
||||
a5 = next(it for it in r["items"] if it["id"] == 5)
|
||||
assert a5["section"] == "country" # low-conf NY -> not 'state'
|
||||
secs = [it["section"] for it in r["items"]]
|
||||
if "near" in secs and "world" in secs:
|
||||
assert max(i for i, s in enumerate(secs) if s == "near") < \
|
||||
if "state" in secs and "world" in secs: # local leads, world trails
|
||||
assert max(i for i, s in enumerate(secs) if s == "state") < \
|
||||
min(i for i, s in enumerate(secs) if s == "world")
|
||||
|
||||
|
||||
def test_home_brief_scope_country_has_no_state_tier(app_db):
|
||||
# The 'country' scope drops the local lead: all US stories sit in 'country', none 'state'.
|
||||
r = TestClient(app_db).get("/api/brief?home=US-NY&scope=country&limit=10").json()
|
||||
secs = {it["section"] for it in r["items"]}
|
||||
assert "state" not in secs and "country" in secs
|
||||
|
||||
|
||||
def test_no_home_is_unchanged_and_unsectioned(app_db):
|
||||
r = TestClient(app_db).get("/api/feed?limit=50").json()
|
||||
assert all(it["section"] is None for it in r["items"])
|
||||
|
||||
Reference in New Issue
Block a user