How the topic feedback loop works
The problem: without feedback, a content platform keeps writing what it always wrote — saturating winners into cannibalization and feeding dead topics forever. The loop closes this: what earned attention gets more; what proved dead gets parked; and a protected share always goes to the unknown.
Layer 1 — from search signal to topic verdicts
Section titled “Layer 1 — from search signal to topic verdicts”Search-console data (already collected — the loop adds no new harvesting) is aggregated weekly into topic performance: articles per topic, impressions, clicks, and the headline metric — impressions per article. A nightly pass rebuilds topic state before Collect runs:
Verdicts respect signal inertia — three separate constants, often confused: articles younger than the maturity window don’t vote at all; the freshest few days of search data are excluded (reporting lag); and policy changes themselves are rate-limited by a governance interval.
Layer 2 — the selection policy
Section titled “Layer 2 — the selection policy”The policy is precisely not a hard split: exploit takes topics with above-median yield; explore is a protected minimum share — new and under-sampled topics get it even when exploit could fill the whole batch. Saturation is capped (a topic already heavily covered in the recent window stops accepting more candidates), dead topics are parked wholesale through the same defer mechanism the dedup gate uses, and unclassifiable candidates pass through unjudged — deliberately excluded from the median so dictionary gaps don’t masquerade as yield signals. A watchdog alarms if too much of a week’s output lands in dead topics.
Everything is tunable without deploys: per-contract policy overrides cascade over fleet defaults over code defaults, edited through an owner-gated tool; topic dictionaries are versioned and append-only.
Layer 3 — the seam
Section titled “Layer 3 — the seam”The loop’s write surface into production is intentionally tiny: one step inside Collect, placed right after topic dedup and right before the export gate — the same choke-point every candidate already passes. The quota mechanism cannot increase a contract’s nightly budget; it only redistributes within it.
Layer 4 — the twin: never pay twice
Section titled “Layer 4 — the twin: never pay twice”A sibling mechanism guards the opposite failure — regenerating what was already generated. Measured before the fix, nearly half of generation submissions were repeats, and the overwhelming majority of those repeats failed the same gates again. Now a historical guard at run creation refuses a generate-run for a source that already succeeded (with an explicit override for deliberate regeneration), and gate-failed articles sit in quarantine rather than a retry loop. The two mechanisms are philosophical twins on different seams: the loop decides what to write, the guard ensures what was written isn’t paid for twice.
The trade-offs, honestly
Section titled “The trade-offs, honestly”The loop is only as sharp as the topic dictionary — a deterministic slug-to-topic mapper with zero LLM calls, which means new topic families need dictionary entries before the loop can see them. And the quota features ship behind calibration flags whose production state moves as tuning proceeds — scoring and telemetry always run; enforcement is switched deliberately, consistent with the platform’s deployed-means-enabled rule.
See it in two minutes
Section titled “See it in two minutes”The nightly report’s topics section shows every bucket decision of the
last run; topic performance and states are queryable per contract through
the analytics domain.
Specs: SPEC-125 (the loop), SPEC-126 (regeneration suppression + quarantine), SPEC-118 (the shared defer mechanism), SPEC-096 (the signal source).