---
title: How the topic feedback loop works
description: Search results steer what gets written next — topic yield scoring, an explore floor that protects discovery, dead-topic parking, and the twin mechanism that stops paying twice for the same article.
locale: en
version: 0.2.0
canonical: https://enterium-developer-docs.pages.dev/developers/how-it-works/topic-feedback-loop/
---

> Documentation index: https://enterium-developer-docs.pages.dev/developers/llms.txt — every page of this portal has a Markdown twin at <route>.md; the frozen API contract is at https://enterium-developer-docs.pages.dev/developers/api/openapi.json.

**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

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:

```mermaid
stateDiagram-v2
    [*] --> no_data
    no_data --> star: earns impressions + clicks
    no_data --> not_indexed: never crawled
    star --> star_far: impressions, position too deep for clicks
    star --> dead: yield collapses
    dead --> star: signal returns
    note right of not_indexed: "not indexed" ≠ "dead" —\ndifferent problem, different fix
```

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

```mermaid
pie showData
    title Selection shares (concept)
    "Exploit — above-median yield" : 75
    "Explore — protected floor" : 25
```

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

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

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*.

## Trade-offs

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

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.
