Skip to content

Editorial

The editorial module is where the platform’s thesis becomes code. Five editorial constraints — topical diversity, recency / freshness, sentiment balance, editorial promotion, and sensitive-topic guard — applied to a candidate set through the ranker.

The ranker is the platform’s headline deep module: a pure function from (candidate_set, constraint_configuration) to a ranked list of articles. That’s the entire interface. Everything else in the module is in service of making that function trustworthy, testable, and editorially defensible.

The ranker lives at tutorial/serving/src/serving/ranker.py. It is dependency-free — no database connection, no HTTP framework, no filesystem. That isolation is deliberate (ADR-0010 explains why) and is what makes the test suite fast and exhaustive: every config, every constraint, every edge case covered with seeded inputs.

The sensitive-topic detector is its own deep module:

The editorial configuration is a table, not code: constraint_configurations.sql. That table is what the editor interface reads and writes, and it is part of the analytical contract analysts can query directly.

The mixed-enforcement model (ADR-0010) refuses the temptation to make every editorial concern a numeric preference.

Soft constraints (weighted into a score):

  • Topical diversity — anti-overlap with already-ranked articles in the list
  • Recency / freshness — exponential decay against article age, half-life tunable
  • Sentiment balance — Wasserstein-style penalty against a target sentiment distribution; degrades gracefully when sentiment scores are absent

Hard rules (applied after sorting):

  • Editorial promotion — articles in the always-include list are inserted at their target positions, period
  • Sensitive-topic guard — a hard cap on the share of sensitive articles per list, dropping from the bottom until the cap holds

A promoted investigation cannot vanish into a low weight. A sensitive-topic cap cannot be overridden by a high relevance score. That asymmetry is the editorial promise this module makes.

ADR-0015 spells out the exact formulas: the score combination, each soft-term shape, the configuration schema, and the defaults. Anyone reading the ranker code can compare line-for-line against the ADR.

The ranker is consumed by serving through /recommendations/ and /preview endpoints. The editor module gives editors sliders + toggles + an always-include list management UI that all read and write the constraint_configurations table the ranker references. The evaluation module sweeps configurations and produces the Pareto chart that makes the editorial-cost-of-clicks argument visible.