Personal-content re-surface decision math
What this skill does
Given (a) a corpus of saved personal content, (b) a static user profile, and (c) the user's recent activity, decide which N items to re-surface today and why. Output is a ranked list with one-line reasons. Does NOT define the UX (push notif vs daily digest vs dashboard widget) — that lives in product code.
Inputs
| Signal |
Shape |
Source |
| Corpus item |
{id, source, captured_at, text/embedding, tags, last_surfaced_at, surface_count, useful_score} |
Obsidian vault, Pinecone, or Supabase — whatever the store is |
| Static user profile |
{interests[], role, current_projects[], stated_priorities[]} |
User-authored, lives in Obsidian or app DB |
| Dynamic recent activity |
{queries_this_week[], content_consumed_this_week[], current_focus_topic} |
Activity log of last 7 days |
Output
[
{ "item_id": "yt_abc123", "score": 0.87, "reason": "topic match with current focus + 14d since last surface" },
{ "item_id": "wa_xyz", "score": 0.81, "reason": "high useful_score + 60d dormant" }
]
Rank descending. Cap at N (default 5). Each item carries a one-line reason for transparency.
Three algorithms — pick at build time
1. SM-2 (classic Anki) — day-1, no personalization needed
Decay-only. Each item has interval and ease_factor. When marked useful, interval grows. Re-surface when now > last_surfaced_at + interval. Zero LLM in the loop. Cheapest compute.
Use when: MVP day-1, corpus <100 items, no feedback signal yet.
2. FSRS (Free Spaced Repetition Scheduler) — modern, accurate
Three latent variables per item: difficulty, stability, retrievability. Updates via maximum-likelihood estimation. Outperforms SM-2 in benchmarks.
Use when: corpus >500 items AND ≥30 useful/not-useful events accumulated to train the model.
3. Custom context-aware hybrid — the Connecting-Dots moat
score = 0.5 × time_decay + 0.3 × relevance_to_recent_activity + 0.2 × static_profile_match
time_decay: forgetting curve, sigmoid over days-since-surface
relevance_to_recent_activity: cosine sim between item embedding and embedding of last 7d activity
static_profile_match: cosine sim between item embedding and embedding of user profile
Use when: corpus >100 items AND user has authored a meaningful profile. The recommended path for Connecting Dots specifically — pure spaced-rep misses the "this is suddenly relevant" signal that recent activity unlocks.
See references/algorithms.md for exact formulas, half-life tuning, and edge cases.
Decision matrix
| Stage |
Corpus |
Feedback events |
Algorithm |
| MVP day 1 |
<100 |
0 |
SM-2 |
| MVP weeks 2–4 |
100–500 |
<30 |
Custom hybrid (no FSRS training data yet) |
| Mature |
500+ |
30+ |
FSRS + hybrid signal — ensemble |
Common pitfalls
- Cold start: day-1 has no feedback. Default to SM-2 with
ease=2.5, interval=1. Don't attempt FSRS.
- Recency bias: if only dynamic activity drives the score, old gold gets buried. The
time_decay term fights this.
- Echo chamber: if
relevance_to_recent_activity weights too high, the user only sees more-of-the-same. Cap that term at 0.5; force diversity sampling for top-N.
- Surface fatigue: enforce
min_days_between_surface = 7 regardless of score — same item every day is annoying.
- Feedback bootstrap: cold-start the
useful_score to 0.5 (neutral), update on user signal. Never let it drop below 0.1 — that's bandit-style starvation.
What this skill does NOT do
- Pull content from source platforms — that's
baoyu-youtube-transcript, integrate-whatsapp, superpowers-chrome:browsing, etc.
- Store content — that's
obsidian-vault, memory-router, or supabase.
- Extract entities/topics from content — that's
ner-content-pipeline.
- Render the surface UX — that's product code (Obsidian dashboard, web app, push notif daemon).
- Build the RAG pipeline that answers queries — that's
rag-patterns.
It only answers: "Given everything you have, what should I look at today?"
1---2name: personal-content-resurface3description: Decide which saved personal content (saved YouTube videos, Instagram reels, WhatsApp self-messaged links/files, LinkedIn saved posts) should re-surface today, based on time-since-last-surface plus relevance to the user's current context. Returns a ranked list with reasons. Teaches three algorithms (SM-2, FSRS, custom context-aware hybrid) — the implementer picks at build time. Decision math only, not surfacing UX. Use when the user asks "what should I re-look at today", "resurface saved content", "spaced repetition for my saved stuff", "Connecting Dots prioritization", "second brain re-surfacing", "what saved content matters right now", "personalized content scheduling", or any variant of "I save things and never re-look at them — what should I look at now?"4---56# Personal-content re-surface decision math78## What this skill does910Given (a) a corpus of saved personal content, (b) a static user profile, and (c) the user's recent activity, decide **which N items to re-surface today** and **why**. Output is a ranked list with one-line reasons. Does NOT define the UX (push notif vs daily digest vs dashboard widget) — that lives in product code.1112## Inputs1314| Signal | Shape | Source |15|---|---|---|16| **Corpus item** | `{id, source, captured_at, text/embedding, tags, last_surfaced_at, surface_count, useful_score}` | Obsidian vault, Pinecone, or Supabase — whatever the store is |17| **Static user profile** | `{interests[], role, current_projects[], stated_priorities[]}` | User-authored, lives in Obsidian or app DB |18| **Dynamic recent activity** | `{queries_this_week[], content_consumed_this_week[], current_focus_topic}` | Activity log of last 7 days |1920## Output2122```json23[24 { "item_id": "yt_abc123", "score": 0.87, "reason": "topic match with current focus + 14d since last surface" },25 { "item_id": "wa_xyz", "score": 0.81, "reason": "high useful_score + 60d dormant" }26]27```2829Rank descending. Cap at N (default 5). Each item carries a one-line `reason` for transparency.3031## Three algorithms — pick at build time3233### 1. SM-2 (classic Anki) — day-1, no personalization needed3435Decay-only. Each item has `interval` and `ease_factor`. When marked useful, `interval` grows. Re-surface when `now > last_surfaced_at + interval`. Zero LLM in the loop. Cheapest compute.3637**Use when:** MVP day-1, corpus <100 items, no feedback signal yet.3839### 2. FSRS (Free Spaced Repetition Scheduler) — modern, accurate4041Three latent variables per item: difficulty, stability, retrievability. Updates via maximum-likelihood estimation. Outperforms SM-2 in benchmarks.4243**Use when:** corpus >500 items AND ≥30 useful/not-useful events accumulated to train the model.4445### 3. Custom context-aware hybrid — the Connecting-Dots moat4647```48score = 0.5 × time_decay + 0.3 × relevance_to_recent_activity + 0.2 × static_profile_match49```5051- `time_decay`: forgetting curve, sigmoid over days-since-surface52- `relevance_to_recent_activity`: cosine sim between item embedding and embedding of last 7d activity53- `static_profile_match`: cosine sim between item embedding and embedding of user profile5455**Use when:** corpus >100 items AND user has authored a meaningful profile. **The recommended path for Connecting Dots specifically** — pure spaced-rep misses the "this is suddenly relevant" signal that recent activity unlocks.5657See [references/algorithms.md](references/algorithms.md) for exact formulas, half-life tuning, and edge cases.5859## Decision matrix6061| Stage | Corpus | Feedback events | Algorithm |62|---|---|---|---|63| MVP day 1 | <100 | 0 | SM-2 |64| MVP weeks 2–4 | 100–500 | <30 | Custom hybrid (no FSRS training data yet) |65| Mature | 500+ | 30+ | FSRS + hybrid signal — ensemble |6667## Common pitfalls6869- **Cold start**: day-1 has no feedback. Default to SM-2 with `ease=2.5, interval=1`. Don't attempt FSRS.70- **Recency bias**: if only dynamic activity drives the score, old gold gets buried. The `time_decay` term fights this.71- **Echo chamber**: if `relevance_to_recent_activity` weights too high, the user only sees more-of-the-same. Cap that term at 0.5; force diversity sampling for top-N.72- **Surface fatigue**: enforce `min_days_between_surface = 7` regardless of score — same item every day is annoying.73- **Feedback bootstrap**: cold-start the `useful_score` to 0.5 (neutral), update on user signal. Never let it drop below 0.1 — that's bandit-style starvation.7475## What this skill does NOT do7677- Pull content from source platforms — that's `baoyu-youtube-transcript`, `integrate-whatsapp`, `superpowers-chrome:browsing`, etc.78- Store content — that's `obsidian-vault`, `memory-router`, or `supabase`.79- Extract entities/topics from content — that's `ner-content-pipeline`.80- Render the surface UX — that's product code (Obsidian dashboard, web app, push notif daemon).81- Build the RAG pipeline that answers queries — that's `rag-patterns`.8283It only answers: "Given everything you have, what should I look at today?"