Skip to content

sentiment-mapper

Maps polarizing topics to identify opposing positions, trigger points, engagement signals, and belief clusters. Use when analyzing a topic’s controversy landscape for strategic content positioning.

ModelSource
sonnetpack: content-pumper
Full Reference

┏━ πŸ” sentiment-mapper ━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Maps polarization landscape for a topic β€” ┃ ┃ sides, triggers, and strategic positioning ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Reads a topic from topic-memory, researches its controversy landscape, and writes a structured sentiment object back. Output drives polarizationHeat scoring and informs content angle selection.


  1. Read topic β€” pull topic entry from topic-memory by topicId; note current trendVelocity and socialBuzz
  2. Research β€” invoke web-research skill; search for "<topic> controversy", "<topic> debate", "<topic> criticism", "<topic> supporters"
  3. Identify positions β€” extract 2–4 distinct, named positions from search results; collapse fringe positions with <5% estimated share
  4. Estimate audience size β€” assign estimatedSize (0–1 float, all sides must sum to ≀1.0); use engagement proxy from comment counts and share volume
  5. Extract trigger phrases β€” scan top 10 comment threads or discussion threads per topic; extract recurring emotionally-charged phrases; cluster by which side uses them
  6. Assess engagement β€” rate each side low | medium | high based on reply depth, reshare rate, and comment volume observed in research
  7. Write back β€” call topic-memory update-sentiment with the completed sentiment object

Matches content-topics.json sentiment block exactly:

{
"polarized": true,
"sides": [
{
"label": "<short label, e.g. 'Pro-regulation'>",
"position": "<1–2 sentence summary of what this side believes>",
"estimatedSize": 0.45,
"triggers": ["phrase A", "phrase B", "phrase C"],
"engagement": "high"
}
]
}

Rules:

  • polarized: false when all positions are low-engagement or topic has no meaningful opposition
  • Minimum 2 sides when polarized: true; max 4 sides
  • estimatedSize values across all sides must sum to ≀ 1.0
  • triggers β€” minimum 3 phrases per side, maximum 8

Sources to scan (in priority order):

SourceWhere to look
RedditTop 10 posts by upvotes in relevant subreddits
YouTubeTop comments on 3 high-view topic videos
Twitter/XTop reply threads on viral topic tweets
News commentsDisqus or native comments on top 3 news stories

Detection method:

  1. Collect raw comment text from each source
  2. Identify phrases that appear β‰₯3 times across unrelated threads
  3. Tag each phrase to a position by co-occurrence with known position signals
  4. Discard neutral phrases (appear equally across sides)
  5. Output top phrases ranked by emotional intensity (caps, exclamation, upvotes)

For each identified side, produce a positioning note:

Side: <label>
Safe angles: <2–3 content angles that resonate without alienating>
Risky angles: <1–2 framings that will draw backlash from this side>
Bridge topics: <1–2 topics that appeal to both this side and its opposition>

Store positioning notes in a local scratch block β€” do not write to content-topics.json. Surface them as context when content-pumper-pimp requests a content angle.


Re-run sentiment mapping when any of the following conditions are met:

TriggerCondition
Velocity shifttrendVelocity changes state (e.g., stable β†’ rising)
Buzz spikesocialBuzz increases or decreases > 20% since last mapping
Time elapsed> 14 days since last lastScored timestamp
Manual overrideUser or orchestrator explicitly requests re-map

Check these conditions before starting research β€” if none are met and a recent sentiment object exists, return existing data without re-mapping.


SkillPurpose
web-researchGathers source material β€” discussions, news, threads
audience-analysisOverlays demographic data onto estimated side sizes
topic-memoryReads topic entry; writes update-sentiment on completion

Invoke audience-analysis after sides are identified but before writing back β€” use its demographic breakdown to refine estimatedSize values.


CallerReadsWrites
topic-scorersentiment.polarized, sides[].engagementβ€”
content-pumper-pimpsides[], positioning notesβ€”
sentiment-mappertopics[topicId]update-sentiment