topic-momentum
$
npx mdskill add aaronjmars/aeon/topic-momentum> **${var}** — Optional domain filter (e.g. "crypto", "AI", "prediction-markets"). If empty, scans every domain declared in `memory/topics/content-domains.md`.
SKILL.md
.github/skills/topic-momentumView on GitHub ↗
---
name: topic-momentum
description: Weekly content-gap scanner — cross-references rising narrative signals (narrative-tracker, tweet-roundup, paper-pick, etc.) against recent article history and surfaces the top 3 uncovered angles to write next.
var: ""
tags: [content, meta]
---
> **${var}** — Optional domain filter (e.g. "crypto", "AI", "prediction-markets"). If empty, scans every domain declared in `memory/topics/content-domains.md`.
Today is ${today}. Read `memory/MEMORY.md` before starting.
## Voice
If `soul/SOUL.md` and `soul/STYLE.md` are populated, read both and match the operator's voice when drafting the suggested hook line (step 4) and the notification body. If they are empty templates or absent, use a clear, direct, neutral tone — short, declarative, position-first.
## Why this skill exists
The article skill picks one trending topic per run. Skills like `narrative-tracker`, `tweet-roundup`, and `paper-pick` surface discrete signals. Nothing cross-references **what's been covered** against **what keeps surfacing** — so timely angles get missed or covered weeks late. This skill closes that gap: a weekly pattern detector that finds the signal the operator keeps receiving but hasn't written about yet.
## Config
Domain filters and signal-source aliases live in `memory/topics/content-domains.md`. If the file doesn't exist, create the seed below and continue with the default (no filter):
```markdown
# Content Domains
## Domains
- crypto
- AI
- prediction-markets
- macro
- protocols
## Signal Sources
(Skill log section names that produce candidate signals. Add more as you wire up trackers.)
- narrative-tracker # rising/peaking narratives
- tweet-roundup # topic-grouped tweet picks
- paper-pick # research papers
- repo-actions # GitHub-ecosystem ideas
## Topic Memory Files
(Files in memory/topics/ that hold cross-run context the gap scanner should also read.)
- market-context.md
- papers.md
```
If `${var}` is set, restrict the gap-scan to themes that match the named domain (substring/keyword match against the theme name).
## Steps
### 1. Load recent article coverage
Use Glob to list `.md` files in `articles/` modified in the last 30 days (filename pattern `YYYY-MM-DD.md` makes this easy).
For each file:
- Read the H1 and first 2 sentences — extract the core topic and angle
- Note the date from the filename
Build a **covered-topics list**: `[{ date, topic, angle }]`.
- Articles ≤ 7 days old: "very recent" → suppress re-suggestion (-5 in scoring)
- Articles 8–14 days old: "recent" → penalize (+1 only)
- Articles 15–30 days old: still penalized lightly (+3)
- Articles > 30 days old or never written: full credit (+5)
### 2. Load narrative signals from recent logs
Read `memory/logs/` for the last 7 days (Glob `memory/logs/*.md`, sort by name, take last 7).
From each daily log, extract entries under each `Signal Source` declared in `content-domains.md`. For each entry, extract:
- The theme / narrative name
- Whether it was labeled "rising", "peaking", or otherwise high-signal
- How many sources / days surfaced it
Also read each `Topic Memory File` from `content-domains.md` (default: `memory/topics/market-context.md`, `memory/topics/papers.md`) for current macro themes and hot narratives.
Build a **signal-map**: `{ theme: { frequency_score, source_list, first_seen, last_seen } }`.
If `${var}` is set, filter signal-map to themes matching that domain.
### 3. Score the gaps
For each theme in signal-map:
| Criterion | Points |
|---|---|
| Surfaced 5+ days/sources in last 7d | +5 |
| Surfaced 3–4 days/sources | +3 |
| Surfaced 1–2 days/sources | +1 |
| Never written about | +5 |
| Last covered 15+ days ago | +3 |
| Last covered 8–14 days ago | +1 |
| Last covered in past 7 days | −5 (suppress) |
| Domain-fit: matches a declared domain in content-domains.md | +1 |
**Max score: ~14.** Drop themes with net score < 2.
Rank descending. Pick top 3.
### 4. Develop the angles
For each top-3 gap:
- Define a **specific angle** — not "write about X" but "X from the angle of Y; the thing everyone's missing is Z"
- Draft a **hook line** (voice per the Voice section above)
- Note **what triggered it** (sources from step 2)
- Note **last coverage** date or "never"
### 5. Update memory
Write `memory/topics/content-gaps.md` (overwrite):
```markdown
# Content Gaps — Last Updated: ${today}
## Top 3 Angles (Ranked by Signal Score)
### 1. <Theme Name> — Score: N/14
**Angle:** <specific take — not generic>
**Hook:** <suggested opener>
**Sources:** <what surfaced this, e.g. "narrative-tracker 4d, tweet-roundup 3d">
**Last coverage:** <date or "never">
### 2. <Theme Name> — Score: N/14
...
### 3. <Theme Name> — Score: N/14
...
---
*Generated by topic-momentum on ${today}. Consumed by: article skill, remix-tweets.*
```
### 6. Notify
Use Write to create `.pending-notify-temp/topic-momentum-${today}.md`:
```
topic momentum — ${today}
3 angles with high signal, no recent article:
1. <theme name> — <angle in one line>
2. <theme name> — <angle in one line>
3. <theme name> — <angle in one line>
full breakdown: memory/topics/content-gaps.md
```
Then run:
```bash
./notify -f .pending-notify-temp/topic-momentum-${today}.md
```
Keep total under 800 chars. Do NOT use `./notify "$(cat ...)"` — write the file first, pass the path.
### 7. Log
Append to `memory/logs/${today}.md`:
```markdown
## Topic Momentum
- **Themes scanned:** N
- **Gaps scored:** N
- **Top 3:** <theme1>, <theme2>, <theme3>
- **Lowest gap score included:** N/14
- **Updated:** memory/topics/content-gaps.md
- **Notification:** sent
- TOPIC_MOMENTUM_OK
```
If fewer than 3 scoreable gaps were found: log `TOPIC_MOMENTUM_SKIP: insufficient signal (<3 themes above threshold)` and stop without notifying.
## Required Env Vars
None. All reads from local `memory/` and `articles/` dirs. No external API calls, no curl, no prefetch script needed.
## Sandbox Note
No network calls required — all data comes from local memory files written by other skills. If `memory/logs/` is sparse (e.g. first run), fall back to reading the `Topic Memory Files` declared in `content-domains.md` directly as the signal source. **WebSearch** is available as a last resort for current narrative heat if local data is too thin, but should rarely be needed.
More from aaronjmars/aeon
- [REPLACE: SKILL_NAME]Daily price and volume tracker for [REPLACE: TOKEN_SYMBOL] with anomaly alerts above [REPLACE: ALERT_THRESHOLD_PCT]% movement
- Action Converter5 concrete real-life actions for today, leverage-scored against open loops with specificity and anti-fluff gates
- Agent BuzzCurated AI-agent tweets, clustered into narratives with insight summaries
- agent-displacementWeekly tracker of AI agent substitution signals — which roles, companies, and industries show real headcount displacement. Named roles + real deployments only.
- AI Framework WatchWeekly competitive-intelligence digest on the AI agent framework space — momentum, releases, breaking changes across a curated watchlist
- AIXBT PulseCross-domain market pulse from AIXBT's free grounding endpoint — crypto, macro, tradfi, geopolitics. Refreshes taxonomy references (clusters, chains) as a bonus.
- api-health-probeDaily pre-batch API provider health check — detects credit exhaustion or auth failure for every configured provider key before the morning batch runs, giving the operator a window to act before skills degrade
- Approval AuditList a wallet's live ERC-20 token approvals on Base and flag unlimited / risky spender grants. Keyless via Base RPC (eth_getLogs + eth_call) — no explorer key needed.
- article-queueWeekly article idea synthesizer — ranks signals from topic-momentum, beat-tracker, and narrative-tracker into a prioritized queue the article skill reads on next run
- atrium-catalog-watcherWeekly diff of the Atrium marketplace catalog at https://atriumhermes.tech/.well-known/skills/index.json against the prior snapshot — surfaces newly-published skills, removed skills, and updated descriptions. Supply-side complement to sparkleware-catalog (curated skill-packs.json registry) and skill-update-check (version drift of installed skills).