Fix status/active mirror drift in upsert_sources (pre Promote-candidate)
Per Codex: upsert_sources() wrote `active` but not `status`, so a candidate promoted inactive (the pipeline default) became active=0 + status='active' — the exact mirror drift Phase 1 set out to avoid (scheduler won't poll, admin UI shows "active"). Now derive status from an explicit value or from active, mirror active off status, and write both columns together (insert + conflict update). Test: promote_candidate(active=False) → status='paused', active=0. Also fix stale source_health docstring (now includes retired). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -282,7 +282,7 @@ def content_stats(conn: sqlite3.Connection) -> dict:
|
||||
|
||||
|
||||
def source_health(conn: sqlite3.Connection) -> list[dict]:
|
||||
"""Per source (active AND paused), the data an operator needs to manage feeds:
|
||||
"""Per source (active, paused, AND retired), the data an operator needs to manage feeds:
|
||||
failure streak, last error/success/attempt, computed next poll, and the
|
||||
backing metrics (served/accepted/total counts + acceptance & duplicate rates)
|
||||
so Pause/Flag decisions aren't vibes-based.
|
||||
|
||||
+11
-3
@@ -21,14 +21,20 @@ def load_sources(path: Path | str) -> list[dict]:
|
||||
def upsert_sources(conn: sqlite3.Connection, source_defs: list[dict]) -> int:
|
||||
count = 0
|
||||
for source in source_defs:
|
||||
# Keep status and the legacy `active` mirror in lockstep (Phase 1 rule):
|
||||
# derive status from an explicit value or from active, then mirror active.
|
||||
status = source.get("status") or ("active" if source.get("active", True) else "paused")
|
||||
if status not in ("active", "paused", "retired"):
|
||||
status = "active"
|
||||
active = 1 if status == "active" else 0
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO sources (
|
||||
name, homepage_url, feed_url, source_type, default_category,
|
||||
trust_score, pr_risk_score, active, poll_interval_minutes, notes,
|
||||
trust_score, pr_risk_score, active, status, poll_interval_minutes, notes,
|
||||
updated_at
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT(feed_url) DO UPDATE SET
|
||||
name = excluded.name,
|
||||
homepage_url = excluded.homepage_url,
|
||||
@@ -37,6 +43,7 @@ def upsert_sources(conn: sqlite3.Connection, source_defs: list[dict]) -> int:
|
||||
trust_score = excluded.trust_score,
|
||||
pr_risk_score = excluded.pr_risk_score,
|
||||
active = excluded.active,
|
||||
status = excluded.status,
|
||||
poll_interval_minutes = excluded.poll_interval_minutes,
|
||||
notes = excluded.notes,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
@@ -49,7 +56,8 @@ def upsert_sources(conn: sqlite3.Connection, source_defs: list[dict]) -> int:
|
||||
source.get("default_category"),
|
||||
int(source.get("trust_score", 5)),
|
||||
int(source.get("pr_risk_score", 3)),
|
||||
1 if source.get("active", True) else 0,
|
||||
active,
|
||||
status,
|
||||
int(source.get("poll_interval_minutes", 60)),
|
||||
source.get("notes"),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user