Files
news/.omo/evidence/task-19a-news-triage.txt
T
connor 20a6c26f7c
Check / check (push) Failing after 1m27s
Check / guardrails (push) Failing after 39s
Check / bundle (push) Successful in 1m4s
Initial commit -- did OMO do a good job?
2026-09-01 18:29:46 -04:00

58 lines
2.2 KiB
Plaintext

Task: todo 19a — notification-gate peek + read-only HTTP API
Date: 2026-09-01
Files created/modified:
- crates/news-server/src/gate.rs (refactored: shared decide(), new peek(), tests)
- crates/news-server/src/api/mod.rs (register config + stories modules)
- crates/news-server/src/api/config.rs (new GET /api/config endpoint + tests)
- crates/news-server/src/api/stories.rs (new GET /api/stories endpoint)
- crates/news-server/src/api/stories/tests.rs (new tests)
- crates/news-server/src/main.rs (wire /api/config and /api/stories routers)
Verification commands
---------------------
1. Formatting
$ cargo fmt --all --check
Result: clean
2. Clippy
$ cargo clippy --workspace --all-targets -- -D warnings
Result: clean
3. Workspace tests
$ cargo test --workspace
Result: passed (83 tests total)
- news-cli: 2 passed
- news-core: 18 passed
- news-ingest: 4 passed
- news-server: 41 passed (up from 33 in task 18)
- news-store: 22 passed
4. Build
$ cargo build --workspace --bins
Result: finished successfully
Implementation notes
--------------------
- NotificationGate::peek is side-effect-free: clones the token bucket, refills
in memory only, calls the shared decide() logic, and never writes
notification_log or decrements budget.tokens.
- Shared decision logic lives in a private decide() method used by both
evaluate_with_mode and peek, guaranteeing identical Notify/Digest/Suppress
outcomes.
- GET /api/stories queries story_clusters joined to raw_items for the canonical
item, recomputes relevance (RelevanceScorer) and importance
(ImportanceScorer) per request, derives percentile ranks from
percentile_stats over a 7-day window, calls gate.peek, and returns a JSON
array of story rows with decision/reason/last_notification_lane.
- GET /api/config returns the current in-memory NewsConfig as JSON.
- Both endpoints are read-only: no notification_log rows are written and the
gate token budget is unchanged after a request.
Known divergences from plan wording
-----------------------------------
- Percentile ranks are computed with a direct SQL query on percentile_stats
rather than through PercentileTracker, because PercentileTracker exposes no
rank API and news-store is frozen for this task.