Daily news report (Markdown)
Quick start
- Resolve the target date.
- Accept
YYYY-MM-DD from the user.
- Default to local today.
- Read
sources.json and cache.json with explicit paths.
- Always call the read tool with a
path field (not file_path).
- Resolve paths relative to this skill's directory (the folder containing this SKILL.md):
read(path="<skill_dir>/sources.json")
read(path="<skill_dir>/cache.json")
- Where
<skill_dir> is the absolute path to skills/sophnet-dailynews/ in the current workspace.
- Collect items in waves (Tier 1 → Tier 2 → Tier 3/browser) until the report has enough high-quality items.
- Write
NewsReport/YYYY-MM-DD-news-report.md.
- Update
cache.json (dedupe + historical stats).
Files in this skill
sources.json: tiers, batches, URLs, fetch method (webfetch/browser), extraction hint, enable/disable flags, and quality thresholds.
cache.json: last run metadata, per-source stats, URL/content dedupe caches, and per-day article history.
Common failure: web_fetch → fetch failed
This usually means the fetch tool hit one of these:
- a redirect it doesn’t follow (302)
- a method mismatch (some sites don’t like
HEAD)
- bot protection / CDN quirks
- response too large / slow for the tool limits
This skill is tuned to avoid common failures:
- Prefer HN RSS over HTML (
https://news.ycombinator.com/rss).
- Pin HuggingFace Papers to a concrete date URL to avoid redirects:
https://huggingface.co/papers/date/{{date}}
- Replace
{{date}} with the target date (YYYY-MM-DD) before fetching.
Output contract
Produce exactly one Markdown file:
- Path:
NewsReport/YYYY-MM-DD-news-report.md
- Target:
quality_thresholds.target_items items (default 20)
- Include only items with
quality_score >= quality_thresholds.min_score_to_include (default 3)
Each item must include:
title
summary (2–4 sentences, concrete and non-hypey)
key_points (max 3)
url (canonical if possible)
source_id
keywords (2–6)
quality_score (1–5, integer)
Collection workflow
1) Initialize
- Load
sources.json → treat it as the source of truth.
- Load
cache.json → use it for dedupe and stats.
- Create
NewsReport/ if missing.
- If
NewsReport/YYYY-MM-DD-news-report.md already exists, either:
- regenerate from scratch (preferred), or
- append only if explicitly requested.
2) Fetch in waves (early stop)
Follow the tier order in sources.json:
- Wave A (Tier 1 / batch_a + batch_b): high hit-rate sources first.
- If you still have fewer than ~15 included items after filtering, continue.
- Wave B (Tier 2 / batch_a + batch_b): supplemental sources.
- If you still have fewer than
target_items, continue.
- Wave C (Tier 3 / browser sources): JS-rendered / blocked sources.
Stop fetching when you have:
- at least
target_items included items, and
- at least
quality_thresholds.early_stop_threshold total candidates evaluated (default 25), or you have exhausted all enabled sources.
3) Extract and normalize
For each enabled source entry:
- Fetch the page content using the configured
fetch_method:
webfetch: normal HTTP fetch.
browser: render with a headless browser when available; otherwise skip with a recorded error.
- Apply the
extract hint from the source entry (examples: top_10, latest_5, latest_issue, today_top_5).
- For each candidate item, normalize:
- clean title (no site suffix noise)
- canonical URL (strip tracking params when safe)
- short summary + key points
RSS-first rule (important):
- For RSS sources, do not
web_fetch the item URLs.
- Use the RSS item's title + description/summary as the source of truth.
- If the RSS description is too thin to summarize, either:
- drop the item, or
- keep it with a one-sentence, non-speculative summary based only on the RSS description.
- Only fetch item URLs if the source entry explicitly says
extract: fetch_items (none do by default).
If a webfetch attempt fails:
- retry once (respect
fetch_config.webfetch.timeout_ms)
- then mark the source as failed and continue (do not abort the whole report)
4) Filter, score, and dedupe
Apply these rules in order:
- Reject obvious low-signal items (marketing fluff, generic science, job posts, thin announcements).
- Score each remaining item (
quality_score 1–5) with a consistent rubric:
- 5: deeply useful + specific + actionable/insightful
- 4: strong signal, worth reading
- 3: decent, include only if you need more items
- 1–2: exclude
- Deduplicate:
- exact URL match (including
cache.json:url_cache)
- near-duplicate title (treat ~80% similarity as duplicate; keep the higher-scored one)
- optional content hash match (when you have the full text)
5) Select and sort
- Keep only items with
quality_score >= min_score_to_include.
- Sort by
quality_score descending.
- Break ties by source credibility (Tier 1 > Tier 2 > Tier 3) and recency.
- Take the top
target_items.
Markdown template
Use this structure:
# Daily News Report (YYYY-MM-DD)
> Sources used: N | Candidates evaluated: M | Included: K
> Generated at: <local timestamp> | Skill: sophnet-dailynews
---
## 1. <Title>
- **Summary**: ...
- **Key Points**:
1. ...
2. ...
3. ...
- **Source**: <source_id> — <url>
- **Keywords**: `k1` `k2` `k3`
- **Score**: 4/5
Cache update rules (cache.json)
Update these fields every run:
last_run: date, duration, items_collected, items_published, sources_used
source_stats[source_id]: total_fetches, success_count, avg_items_per_fetch, avg_quality_score, last_fetch, last_success
url_cache.entries: add included URLs (store timestamps; respect _ttl_hours)
content_hashes.entries: add hashes when available (respect _ttl_hours)
article_history[YYYY-MM-DD]: record the final included item list (at minimum: title + url + source_id + score)
Editing sources (sources.json)
- Disable a flaky/low-quality source by setting
enabled: false or moving it to disabled.
- Prefer fixing extraction hints before adding new sources.
- Keep Tier 1 small and high-signal; use Tier 2 for “fill”.
Failure handling
- If a source 403s on
webfetch, try browser (if available) or skip and record the error.
- If all enabled sources fail, still write a report header and an explicit “no items” section; do not silently succeed.
1---2name: sophnet-dailynews3description: Generate a daily, high-signal Markdown news report by scraping a preset source list, filtering and deduplicating items, and writing `NewsReport/YYYY-MM-DD-news-report.md`. Use when the user asks for “daily news”, “tech/news digest”, “today’s links”, “what should I read”, "what happens today", or requests an automated curated report driven by `sources.json` + `cache.json`.4---56# Daily news report (Markdown)78## Quick start9101. Resolve the target date.11 - Accept `YYYY-MM-DD` from the user.12 - Default to local today.132. Read `sources.json` and `cache.json` **with explicit paths**.14 - Always call the read tool with a `path` field (not `file_path`).15 - Resolve paths relative to this skill's directory (the folder containing this SKILL.md):16 - `read(path="<skill_dir>/sources.json")`17 - `read(path="<skill_dir>/cache.json")`18 - Where `<skill_dir>` is the absolute path to `skills/sophnet-dailynews/` in the current workspace.193. Collect items in waves (Tier 1 → Tier 2 → Tier 3/browser) until the report has enough **high-quality** items.204. Write `NewsReport/YYYY-MM-DD-news-report.md`.215. Update `cache.json` (dedupe + historical stats).2223## Files in this skill2425- `sources.json`: tiers, batches, URLs, fetch method (`webfetch`/`browser`), extraction hint, enable/disable flags, and quality thresholds.26- `cache.json`: last run metadata, per-source stats, URL/content dedupe caches, and per-day article history.2728## Common failure: `web_fetch` → `fetch failed`2930This usually means the fetch tool hit one of these:3132- a redirect it doesn’t follow (302)33- a method mismatch (some sites don’t like `HEAD`)34- bot protection / CDN quirks35- response too large / slow for the tool limits3637This skill is tuned to avoid common failures:3839- Prefer **HN RSS** over HTML (`https://news.ycombinator.com/rss`).40- Pin **HuggingFace Papers** to a concrete date URL to avoid redirects:41 - `https://huggingface.co/papers/date/{{date}}`42 - Replace `{{date}}` with the target date (`YYYY-MM-DD`) before fetching.4344## Output contract4546Produce exactly one Markdown file:4748- Path: `NewsReport/YYYY-MM-DD-news-report.md`49- Target: `quality_thresholds.target_items` items (default 20)50- Include only items with `quality_score >= quality_thresholds.min_score_to_include` (default 3)5152Each item must include:5354- `title`55- `summary` (2–4 sentences, concrete and non-hypey)56- `key_points` (max 3)57- `url` (canonical if possible)58- `source_id`59- `keywords` (2–6)60- `quality_score` (1–5, integer)6162## Collection workflow6364### 1) Initialize6566- Load `sources.json` → treat it as the source of truth.67- Load `cache.json` → use it for dedupe and stats.68- Create `NewsReport/` if missing.69- If `NewsReport/YYYY-MM-DD-news-report.md` already exists, either:70 - regenerate from scratch (preferred), or71 - append only if explicitly requested.7273### 2) Fetch in waves (early stop)7475Follow the tier order in `sources.json`:7677- **Wave A (Tier 1 / batch_a + batch_b)**: high hit-rate sources first.78- If you still have fewer than ~15 included items after filtering, continue.79- **Wave B (Tier 2 / batch_a + batch_b)**: supplemental sources.80- If you still have fewer than `target_items`, continue.81- **Wave C (Tier 3 / browser sources)**: JS-rendered / blocked sources.8283Stop fetching when you have:8485- at least `target_items` included items, and86- at least `quality_thresholds.early_stop_threshold` total candidates evaluated (default 25), or you have exhausted all enabled sources.8788### 3) Extract and normalize8990For each enabled source entry:9192- Fetch the page content using the configured `fetch_method`:93 - `webfetch`: normal HTTP fetch.94 - `browser`: render with a headless browser when available; otherwise skip with a recorded error.95- Apply the `extract` hint from the source entry (examples: `top_10`, `latest_5`, `latest_issue`, `today_top_5`).96- For each candidate item, normalize:97 - clean title (no site suffix noise)98 - canonical URL (strip tracking params when safe)99 - short summary + key points100101**RSS-first rule (important):**102103- For RSS sources, **do not** `web_fetch` the item URLs.104- Use the RSS item's title + description/summary as the source of truth.105- If the RSS description is too thin to summarize, either:106 - drop the item, or107 - keep it with a one-sentence, non-speculative summary based only on the RSS description.108- Only fetch item URLs if the source entry explicitly says `extract: fetch_items` (none do by default).109110If a `webfetch` attempt fails:111112- retry once (respect `fetch_config.webfetch.timeout_ms`)113- then mark the source as failed and continue (do not abort the whole report)114115### 4) Filter, score, and dedupe116117Apply these rules in order:1181191. Reject obvious low-signal items (marketing fluff, generic science, job posts, thin announcements).1202. Score each remaining item (`quality_score` 1–5) with a consistent rubric:121 - 5: deeply useful + specific + actionable/insightful122 - 4: strong signal, worth reading123 - 3: decent, include only if you need more items124 - 1–2: exclude1253. Deduplicate:126 - exact URL match (including `cache.json:url_cache`)127 - near-duplicate title (treat ~80% similarity as duplicate; keep the higher-scored one)128 - optional content hash match (when you have the full text)129130### 5) Select and sort131132- Keep only items with `quality_score >= min_score_to_include`.133- Sort by `quality_score` descending.134- Break ties by source credibility (Tier 1 > Tier 2 > Tier 3) and recency.135- Take the top `target_items`.136137## Markdown template138139Use this structure:140141```markdown142# Daily News Report (YYYY-MM-DD)143144> Sources used: N | Candidates evaluated: M | Included: K145> Generated at: <local timestamp> | Skill: sophnet-dailynews146147---148149## 1. <Title>150151- **Summary**: ...152- **Key Points**:153 1. ...154 2. ...155 3. ...156- **Source**: <source_id> — <url>157- **Keywords**: `k1` `k2` `k3`158- **Score**: 4/5159```160161## Cache update rules (`cache.json`)162163Update these fields every run:164165- `last_run`: date, duration, items_collected, items_published, sources_used166- `source_stats[source_id]`: total_fetches, success_count, avg_items_per_fetch, avg_quality_score, last_fetch, last_success167- `url_cache.entries`: add included URLs (store timestamps; respect `_ttl_hours`)168- `content_hashes.entries`: add hashes when available (respect `_ttl_hours`)169- `article_history[YYYY-MM-DD]`: record the final included item list (at minimum: title + url + source_id + score)170171## Editing sources (`sources.json`)172173- Disable a flaky/low-quality source by setting `enabled: false` or moving it to `disabled`.174- Prefer fixing extraction hints before adding new sources.175- Keep Tier 1 small and high-signal; use Tier 2 for “fill”.176177## Failure handling178179- If a source 403s on `webfetch`, try `browser` (if available) or skip and record the error.180- If all enabled sources fail, still write a report header and an explicit “no items” section; do not silently succeed.