F2 final-verification code-quality review: news-triage Scope: crates/*/src/**/*.rs, Cargo.toml workspace lint table, Dockerfile, .gitea/workflows/ci.yml, deploy/*. REJECT Blocking finding: - crates/news-server/src/scheduler/cycle.rs computes relevance_percentile and importance_percentile from the current poll batch only (lines 141-146), using a local percentile_rank helper (lines 207-215). The implementation plan and draft spec require these percentiles to come from the trailing-7-day PercentileTracker distribution (crates/news-store/src/percentile.rs PercentileTracker::percentile). This is a core-algorithm deviation that changes notification gating decisions, so the F2 verdict is REJECT. Non-blocking findings (correct but noted): - percentile_rank helper is duplicated in crates/news-server/src/api/stories.rs:268, crates/news-server/src/scheduler/cycle.rs:207, and crates/news-cli/src/replay.rs:232. - Deterministic source UUID generation uses Uuid::from_u128(hash) in crates/news-server/src/bin_support.rs:162 and crates/news-cli/src/replay.rs:202. Functionally round-trips; non-standard but acceptable for stable fixtures/default sources. - Stub sweep passed: no todo!/unimplemented! in production code; panic! and unwrap/expect are only in tests. - Workspace lints inherited by all six crates via [lints] workspace = true. - cargo clippy --workspace --all-targets -- -D warnings passes. - Math formulas match the draft spec: importance = 1/(1+prominence_rank) + source_trust_weight + (1 - 1/(1+corroboration_count)); relevance = bm25 + bayes_score (Bayes term omitted until ≥20 samples). - Deployment units (deploy/news-update, deploy/news-update.service, deploy/news-update.timer, deploy/ntfy-access-snippet.md) are present and consistent with CI/Dockerfile paths. Required fix: - In scheduler/cycle.rs, call PercentileTracker::percentile(MetricKind::Relevance, ...) and PercentileTracker::percentile(MetricKind::Importance, ...) for each cluster, then map the returned Option or StoreError::InsufficientData to the appropriate percentile value, instead of computing batch-local percentiles. Next step: - After the fix is merged, re-run this F2 review to verify the scheduler uses the trailing-7-day distribution and update this evidence file to APPROVE.