Cut weak interest matches and add the rating-driven affinity signal (step 2)

An interest matches an article only when it is in the top three by z and
z >= 1.0, so the Matches line, the stored rows and the weights agree. The
new bounded affinity signal blends each matched interest's rating-derived
weight, gated on attributable ratings like feed affinity.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9PrjtUS16PAQve8D4bHgc
This commit is contained in:
2026-09-13 05:20:05 +00:00
co-authored by Claude Fable 5.1
parent f0c0927ab8
commit 2d857e3e10
8 changed files with 384 additions and 33 deletions
+2 -1
View File
@@ -58,10 +58,11 @@ pub fn router() -> Router<AppState> {
// ---------------------------------------------------------------------------
/// Signal names in the order of curation plan §7.5.
pub const SIGNAL_NAMES: [&str; 8] = [
pub const SIGNAL_NAMES: [&str; 9] = [
"interest",
"knn",
"feed",
"affinity",
"social",
"heuristic",
"triage",
+4
View File
@@ -351,6 +351,8 @@ pub const SETTINGS_HELP: &[(&str, &str)] = &[
("curation.ranking.knn_full", "Rated articles at which the knn signal reaches full weight. Must be > knn_floor."),
("curation.ranking.feed_floor", "Attributable ratings before the feed-affinity signal starts to count."),
("curation.ranking.feed_full", "Attributable ratings at which feed affinity reaches full weight. Must be > feed_floor."),
("curation.ranking.affinity_floor", "Interest-attributable ratings before the affinity signal starts to count."),
("curation.ranking.affinity_full", "Interest-attributable ratings at which affinity reaches full weight. Must be > affinity_floor."),
("curation.ranking.semantic_min_words", "Bodies shorter than this are not embedded."),
("curation.ranking.exploration_slots", "Shortlist slots reserved for exploration picks."),
("curation.ranking.embedding_retention_days", "features prune: unrated, unpublished vectors older than this are deleted."),
@@ -360,12 +362,14 @@ pub const SETTINGS_HELP: &[(&str, &str)] = &[
("curation.ranking.quotas.knn", "Deep-set slots filled by rated-neighbour preference."),
("curation.ranking.weights.preliminary.interest", "Interest similarity in the preliminary blend."),
("curation.ranking.weights.preliminary.knn", "Rated-neighbour preference in the preliminary blend."),
("curation.ranking.weights.preliminary.affinity", "Rating-derived interest affinity in the preliminary blend."),
("curation.ranking.weights.preliminary.heuristic", "Heuristic score in the preliminary blend."),
("curation.ranking.weights.preliminary.feed", "Feed affinity in the preliminary blend."),
("curation.ranking.weights.preliminary.social", "Social signal in the preliminary blend."),
("curation.ranking.weights.utility.quality", "Deep-assessment quality in the utility score."),
("curation.ranking.weights.utility.fit", "Deep-assessment fit in the utility score."),
("curation.ranking.weights.utility.knn", "Rated-neighbour preference in the utility score."),
("curation.ranking.weights.utility.affinity", "Rating-derived interest affinity in the utility score."),
("curation.ranking.weights.utility.interest", "Interest similarity in the utility score."),
("curation.ranking.weights.utility.feed", "Feed affinity in the utility score."),
("curation.ranking.weights.utility.triage", "Triage score in the utility score."),