Attention strip: richer source-health items (stale/reject/dup/thin/rate-limit)
Per Codex — make the Overview strip diagnostic without making the operator hunt through tables. Aggregated (one calm line per condition with a count), volume- gated, conservative thresholds: * Stale: active+visible source, last success > 10 days ago (warn). * High rejection: >=20 ingested, acceptance < 25% (info). * High duplicate: >=10 accepted, accepted-dup > 50% (info). * Thin images: >=10 served, per-source image coverage < 25% (info). * Long rate-limit: retry_after_at more than 12h out (info). source_health gains a per-source images count + image_coverage. _attention takes an optional now (for tests). Existing site-wide items (global image coverage, thin brief, unread feedback) unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -74,3 +74,43 @@ def test_attention_clear_when_healthy():
|
||||
content = {"served": 100, "with_image": 95, "latest_brief_size": 7}
|
||||
sources = [{"failures": 0, "review_flag": 0}]
|
||||
assert queries._attention(content, sources, feedback_unread=0) == []
|
||||
|
||||
|
||||
def test_attention_richer_items_fire_and_are_quiet_below_threshold():
|
||||
from datetime import UTC, datetime
|
||||
from goodnews import queries
|
||||
now = datetime(2026, 6, 9, 12, 0, 0, tzinfo=UTC)
|
||||
content = {"served": 100, "with_image": 95, "latest_brief_size": 7} # no site-wide items
|
||||
sources = [
|
||||
# stale: active, visible, last success 20 days ago
|
||||
{"status": "active", "content_visible": 1, "last_success_at": "2026-05-20 00:00:00"},
|
||||
# high rejection: 40 ingested, 10% acceptance
|
||||
{"status": "active", "content_visible": 1, "total_articles": 40, "acceptance_rate": 10},
|
||||
# high duplicate: 30 accepted, 70% accepted-dup
|
||||
{"status": "active", "content_visible": 1, "accepted_total": 30, "accepted_dup_rate": 70},
|
||||
# thin images: 40 served, 5% coverage
|
||||
{"status": "active", "content_visible": 1, "served": 40, "image_coverage": 5},
|
||||
# long rate-limit rest: 2 days out
|
||||
{"status": "active", "content_visible": 1, "retry_after_at": "2026-06-11 12:00:00"},
|
||||
]
|
||||
texts = " | ".join(i["text"] for i in queries._attention(content, sources, 0, now=now))
|
||||
assert "haven't updated in over 10 days" in texts
|
||||
assert "accepting under 25%" in texts
|
||||
assert "mostly duplicating" in texts
|
||||
assert "thin image coverage" in texts
|
||||
assert "rate-limited for 12h+" in texts
|
||||
|
||||
|
||||
def test_attention_quiet_below_thresholds():
|
||||
from datetime import UTC, datetime
|
||||
from goodnews import queries
|
||||
now = datetime(2026, 6, 9, 12, 0, 0, tzinfo=UTC)
|
||||
content = {"served": 100, "with_image": 95, "latest_brief_size": 7}
|
||||
sources = [
|
||||
{"status": "active", "content_visible": 1, "last_success_at": "2026-06-08 00:00:00"}, # 1 day — fresh
|
||||
{"status": "active", "content_visible": 1, "total_articles": 5, "acceptance_rate": 10}, # too little volume
|
||||
{"status": "active", "content_visible": 1, "accepted_total": 3, "accepted_dup_rate": 90}, # too little volume
|
||||
{"status": "active", "content_visible": 1, "served": 5, "image_coverage": 0}, # too little volume
|
||||
{"status": "paused", "content_visible": 1, "last_success_at": "2020-01-01 00:00:00"}, # paused → ignored
|
||||
]
|
||||
assert queries._attention(content, sources, 0, now=now) == []
|
||||
|
||||
Reference in New Issue
Block a user