Skip to content

topic-scorer

Algorithmic topic scoring engine — computes composite scores from freshness, search volume, social buzz, polarization heat, brand fit, and competition gap. Use when ranking topics for content priority or recalibrating scoring weights.

ModelSource
sonnetpack: content-pumper
Full Reference

┏━ 🎯 topic-scorer ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Algorithmic engine for topic priority ranking ┃ ┃ — scores, thresholds, and weight recalibration ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Computes composite scores for topics in content-topics.json. Reads raw signals, normalizes them to 0-100, applies weights, and writes scores back via topic-memory. Triggers status transitions when scores cross config.autoThreshold.


composite = Σ(normalized_signal × weight)

Weights come from content-topics.jsonconfig.scoringWeights. Default weights:

SignalDefault Weight
freshness0.20
searchVolume0.20
socialBuzz0.15
polarizationHeat0.10
brandFit0.20
competitionGap0.15

Total weight must sum to 1.0. Validate before scoring — abort with error if sum != 1.0.


Every signal normalizes to 0-100 before weighting.

100 = discovered today
decay = 5 pts/day since firstSeen
normalized = max(0, 100 - (daysSinceDiscovered × 5))

Source: history.firstSeen in topic record.

normalized = min(100, log10(volume) × 20)

Volume < 10 → normalized = 0. Volume 100k+ → normalized capped at 100. Source: content-research skill or Google Trends via WebSearch.

normalized = socialBuzz × 100

Raw value already 0-1. Source: trend-scanner signal output.

normalized = polarizationHeat × 100

Raw value already 0-1. Source: sentiment-mapper signal output.

normalized = LLM assessment 0-100

Assess topic against brand.json fields: voice, values, verticals. High fit = topic aligns with brand verticals AND voice. Low fit = off-brand subject matter or tone mismatch.

normalized = max(0, 100 - (competitors × 10))

competitors = number of ranking articles found via "topic" site:competitor.com WebSearch. 10+ competitors → normalized = 0.


SignalSource
freshnesshistory.firstSeen in content-topics.json
searchVolumecontent-research skill → WebSearch Google Trends
socialBuzztrend-scanner output → topic signals
polarizationHeatsentiment-mapper output → topic signals
brandFitLLM assessment vs brand.json
competitionGapWebSearch competitor count

  1. Read content-topics.json
  2. Filter: topics where status != "archived"
  3. For each topic:
    • Read raw signals from topic.signals
    • Normalize each signal (rules above)
    • Compute composite = Σ(normalized × weight)
    • Round to 2 decimal places
    • Call topic-memory update-score with result
  4. After all scores updated, check threshold (see below)
  5. Output leaderboard: top 10 topics sorted by score descending

After batch scoring, for each topic where status === "discovered":

if composite >= config.autoThreshold AND queued_count < config.maxQueueSize:
→ set status = "queued"
→ log: "topic queued — score {composite} crossed threshold {autoThreshold}"

queued_count = current count of topics with status === "queued". Never exceed maxQueueSize.


Weekly process — correlates historical topic scores with article performance.

  • Topics with status in ["published", "monitoring"]
  • history.performance[] entries from GA4 or GSC
performance_score = normalize(sessions × 0.4 + impressions × 0.3 + clicks × 0.3)

Normalize across all published topics to 0-100.

For each signal, compute Pearson correlation between:

  • normalized_signal_at_queue_time (from score history)
  • performance_score (from actual results)
new_weight = current_weight × (1 + (correlation - avg_correlation) × 0.1)

Clamp each new weight to [0.05, 0.40]. Normalize all weights to sum to 1.0 after adjustment.

Write updated config.scoringWeights to content-topics.json. Log before/after weights for audit.

Recalibration requires minimum 10 published topics with performance data. Skip if insufficient data — log reason.


SkillRelationship
topic-memoryWrites scores and status via update-score operation
trend-scannerProvides socialBuzz signal
sentiment-mapperProvides polarizationHeat signal
content-researchProvides searchVolume data
content-pumper-pimpTriggers batch scoring on schedule

topic-scorer batch complete — 2026-03-01T14:00:00Z
Scored ✓ 42 topics
Queued ✓ 3 new (total: 7)
Skipped ○ 2 archived
Top 5:
88.4 AI regulation debate queued
82.1 Medicare negotiation impact queued
79.3 EV tax credit changes discovered
71.0 Student loan forgiveness monitoring
65.5 Housing affordability index discovered