Batch link-liveness checks against old.reddit.com from a single datacenter IP can mark every Reddit link dead in one run: the Reddit-specific checker treated ANY HTTP status >= 400 (including 429 rate-limit and 403 WAF blocks) as 'post deleted', while the generic editorial-site path deliberately failed open on 403. One rate-limited batch scrubbed all Reddit source links from a generated daily brief, leaving the LLM writer with unlinkable story text (it then cited the subreddit without a link). Post-hoc diagnosis was impossible because the liveness trace recorded only live:true/false per URL with no reason.
Two changes. (1) Fail open on transient blocks for the Reddit path, mirroring the editorial-path rationale: status 403/429 -> treat as live ('fail_open_403'/'fail_open_429') BEFORE the generic >=400 -> dead branch. A rate limit is a property of the checker's IP, not the content; the deletion signals (og:description, selftext div, score floor) can't be evaluated on a challenge/block page anyway, so failing closed only creates false positives. (2) Make every verdict auditable: return (live, reason) tuples from the checker — 'http_404', 'og_empty', 'og_deleted', 'selftext_deleted', 'score_below_floor_3', 'fail_open_429', 'ok' — and persist the reason in the pipeline's per-URL trace. Without reasons, a legitimate engagement-floor drop (score < 5) is indistinguishable from a 429 burst hours later, because scores drift and the block is gone. Keep a bool wrapper (is_link_live = check_link(url)[0]) for callers that don't need reasons.