Advisory source health: review flags, never auto-deactivate

- Add source health columns (last_success_at, last_error_at, last_error,
  consecutive_failures, review_flag, review_reason) via SCHEMA + migration.
- poll_source maintains them: success resets the failure streak and records the
  success time; failure increments it and stores the latest error.
- review_sources() flags active sources that are stale, repeatedly failing,
  low-acceptance, duplicate-heavy, or doom-skewed (high cortisol/ragebait) over
  a recent window. It is purely advisory: it sets review_flag/review_reason and
  never changes the active column (human stays in the loop), clearing the flag
  when a source recovers.
- CLI review-sources; cycle runs it as a final step (--no-review to skip);
  source-report shows a review line for flagged feeds.
- Tests: healthy/failing/stale/low-acceptance/recovery and never-deactivates.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-05-30 20:28:18 +00:00
parent aa4125ddec
commit 1e190c5e88
6 changed files with 243 additions and 4 deletions
+7 -4
View File
@@ -22,6 +22,7 @@ python3 -m goodnews suggest-source https://example.com/feed/ --name "Example" --
python3 -m goodnews list-candidates
python3 -m goodnews promote-candidate 1 # copies into sources (inactive by default)
python3 -m goodnews reject-candidate 1
python3 -m goodnews review-sources # advisory health flags (never deactivates)
python3 -m goodnews build-brief --date 2026-05-27 --replace
python3 -m goodnews show-brief
python3 -m goodnews list-recent --limit 10
@@ -161,7 +162,7 @@ often as you like — it only polls sources that are *due* (per each source's
rebuilds the current day's brief:
```bash
python3 -m goodnews cycle # poll due -> classify new -> dedup -> rebuild today's brief
python3 -m goodnews cycle # poll due -> classify -> dedup -> brief -> review flags
python3 -m goodnews cycle --force # poll every active source regardless of interval
python3 -m goodnews cycle --no-classify # skip the LLM step (e.g. model box offline)
```
@@ -195,9 +196,11 @@ Still ahead:
previews a feed and stages it in the `source_candidates` table (status
suggested/quarantined/rejected/promoted); `promote-candidate` copies it into
`sources` (inactive by default — active on approval); promotion is never
automatic. Still ahead: advisory auto-degrade of stale/rejecting feeds (flag
for review, never auto-block), and an authenticated POST surface so the website
can accept public suggestions once accounts exist.
automatic. Advisory health is done too: `review-sources` (also run at the end
of `cycle`) flags stale, failing, low-acceptance, duplicate-heavy, or
doom-skewed feeds for human review — it never deactivates anything. Still
ahead: an authenticated POST surface so the website can accept public
suggestions once accounts exist.
2. **Learned "Less like this" weighting** — replace the interim flavor-pause with
real preference down-ranking.
3. **Corpus rebalancing** — add calm/feelgood sources (currently science-heavy).