Skip to content
Back to skills

News Collection

ASecurity

Collect, filter, and freshness-qualify news items.

  • 425 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 5, 2026
ai-agentsrustgo

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned September 21, 2026

npx -y skills add notque/vexjoy-agent --skill news-collection --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of News Collection?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for News Collection
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/notque-news-collection/badge)](https://www.skillsdirectory.com/skills/notque-news-collection)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: news-collection
promoted_to: content
description: "Collect, filter, and freshness-qualify news items."
user-invocable: false
routing:
  triggers:
    - "news collection"
    - "collect news"
    - "qualify news items"
    - "news triage"
    - "filter news feed"
    - "check news freshness"
  not_for: "general research reports — that is research-pipeline. Pick this when the input is a stream of news items to qualify for a content pipeline."
  pairs_with:
    - research
  complexity: Medium
  category: research
---

# News Collection

Gather news items on a topic, filter junk cheaply, verify freshness, and emit
qualified items under an evidence contract. Pipeline-shaped: four phases, a
gate between each. Content pipelines consume the JSON artifact; pair with
fact-check to verify what this skill qualifies.

## Instructions

### Phase 1: COLLECT

**Goal**: gather candidate items from available sources (feeds, search
results, provided fixtures). Every item carries the five-fact evidence
contract: **title, url, outlet, author, published_at**.

Rule (verbatim from the design): publish times are extracted (article
metadata), never guessed; missing timestamp → recorded as unknown, confidence
lowered and disclosed. A guessed timestamp poisons every downstream freshness
verdict; an honest `"published_at": null` keeps the item usable with known
uncertainty.

Record each item as one JSON object per the item schema below. Fill
`evidence_notes` with where each fact came from (meta tag, byline, JSON-LD,
sitemap).

Distinguish outcomes: zero items because sources were unreachable is a
collection failure (report it, stop); zero items from reachable sources is a
valid empty feed (deliver an empty artifact with counts of zero).

Gate: every collected item has all five fields present — value or explicit
`null` with a `confidence` downgrade and a disclosure note. Items with silent
gaps stay in COLLECT until the gap is recorded.

### Phase 2: COARSE FILTER

**Goal**: cheap, high-recall pass over collected items. Three verdicts:
`keep` / `monitor_only` / `reject`, each with a reason code (see
Coarse Filter below).

Rule (verbatim from the design): high-magnitude stories are downgraded to
monitor_only at most, never rejected — a false keep is cheap, a silent drop is
expensive. A keep costs one extra freshness check; a wrongly dropped major
story costs the whole pipeline its value.

This phase runs on a cheap model when dispatched -- it needs recall, not
judgment depth. Give the dispatched model: topic, verdict/code tables,
asymmetry rule, and items' five facts plus a text excerpt.

Gate: every item has exactly one verdict and one reason code. `reject`
verdicts on items that look high-magnitude get re-checked once before the
phase closes.

### Phase 3: FRESHNESS CHECK

**Goal**: for each `keep` and `monitor_only` item, establish when the story
first became public and whether this page is the original coverage.

- First-public time vs page date -- a page can carry today's date on old news.
- Syndication and aggregator reposts detected; select the canonical coverage.
- Same-story vs new-development rubric -- consolidate duplicates, keep genuine
  developments. See Freshness Forensics below.

Rule (verbatim from the design): two independent sources or verdict "unclear".
Conservative default: unclear over guessed. An "unclear" verdict is
recoverable downstream; a confidently wrong "fresh" verdict ships stale news.

Gate: every surviving item carries `freshness: fresh | stale | unclear`, a
`first_public_estimate` (or `null`), and the count of sources backing the
verdict. Duplicate clusters are consolidated to one canonical item with
`duplicates_of` links.

### Phase 4: DELIVER

**Goal**: emit qualified items as a structured JSON artifact (see Artifact
Schema below) plus a summary table. Every verdict state
appears in the artifact — `monitor_only`, `unclear`, and `reject` items ship
with their verdicts rather than vanishing, so consumers see the full triage.

Gate (deterministic phase checkpoint — emit this table before delivering the
artifact; delivery without it is incomplete):

| Verdict | Count |
|---------|-------|
| keep | n |
| monitor_only | n |
| reject | n |
| unclear (freshness) | n |
| duplicates consolidated | n |

The counts make silent drops visible: collected total must equal
keep + monitor_only + reject. If it does not, return to the phase that lost
items.

## Error Handling

**No items collected**
- Cause: sources unreachable, or feed genuinely empty.
- Solution: unreachable sources → report collection failure and stop;
  reachable but empty → deliver an empty artifact with zero counts. The two
  outcomes stay distinct so an outage is not read as a quiet news day.

**No timestamp found anywhere for an item**
- Cause: page has no metadata, byline date, or sitemap entry.
- Solution: set `published_at: null`, `confidence: low`, disclose in
  `evidence_notes`; freshness verdict for that item is `unclear`.

**Two sources disagree on first-public time**
- Cause: syndication chain or republished update.
- Solution: apply canonical-coverage selection
  (`references/freshness-forensics.md`); if still split, verdict `unclear`.

**Item count mismatch at DELIVER**
- Cause: an item was dropped without a verdict.
- Solution: diff item ids against the COLLECT record; assign the missing item
  a verdict with reason code.

---

## Evidence Contract

Every collected item carries five facts:

| Fact | Type | Missing value handling |
|------|------|------------------------|
| `title` | string | Empty string only if page truly has none; note in `evidence_notes` |
| `url` | string | Required -- no URL means unverifiable; exclude from artifact |
| `outlet` | string | Derive from domain when no masthead found; note derivation |
| `author` | string or null | `null` when no byline; note where you looked |
| `published_at` | ISO 8601 or null | Extracted from metadata, never guessed. `null` when absent; lower `confidence`, disclose |

Confidence: `high` (all five extracted), `medium` (one derived or weak), `low` (`published_at` null or 2+ derived).

### Item Schema

```json
{
  "id": "string", "title": "string", "url": "string",
  "outlet": "string", "author": "string|null",
  "published_at": "ISO 8601|null", "confidence": "high|medium|low",
  "evidence_notes": "string", "verdict": "keep|monitor_only|reject",
  "reason_code": "string", "freshness": "fresh|stale|unclear|null",
  "first_public_estimate": "ISO 8601|null",
  "freshness_sources": "integer", "duplicates_of": "string id|null"
}
```

### Artifact Schema

```json
{
  "schema_version": "1.0", "topic": "string",
  "collected_at": "ISO 8601",
  "counts": {"collected":0,"keep":0,"monitor_only":0,"reject":0,"unclear_freshness":0,"duplicates_consolidated":0},
  "items": []
}
```

Conservation rule: `collected == keep + monitor_only + reject`.

---

## Coarse Filter

| Verdict | Meaning | Goes to freshness check |
|---------|---------|-------------------------|
| `keep` | On-topic, substantive, plausibly fresh | Yes |
| `monitor_only` | Worth watching: off-topic but high-magnitude, thin, or uncertain | Yes |
| `reject` | Junk: spam, ads, dead pages, clearly irrelevant | No |

Asymmetry rule: high-magnitude stories downgrade to `monitor_only` at most, never `reject`. A false keep is cheap; a silent drop is expensive.

### Reason Codes

| Code | Pairs with | Meaning |
|------|-----------|---------|
| `RC-ONTOPIC` | keep | Directly on topic |
| `RC-DEV` | keep | New development of known story |
| `RC-OFFTOPIC-BIG` | monitor_only | Off-topic but high-magnitude |
| `RC-THIN` | monitor_only | On-topic but little substance |
| `RC-UNCERTAIN` | monitor_only | Relevance unclear |
| `RC-SPAM` | reject | Promotional, SEO bait |
| `RC-IRRELEVANT` | reject | Outside topic, low magnitude |
| `RC-NOCONTENT` | reject | Dead link, paywall stub, empty page |

---

## Freshness Forensics

### First-public time vs page date

A syndicated repost or refreshed CMS page can carry today's date on old news. Establish first-public time from (in trust order):

1. Article metadata (`article:published_time`, JSON-LD `datePublished`) on the originating outlet's page.
2. Earliest `published_at` across collected items covering the same story.
3. In-text anchors ("announced Tuesday") tied to a known date.

Two independent sources or verdict `unclear`. Independent means separately reported -- two copies of the same wire story count as one.

| Verdict | Condition |
|---------|-----------|
| `fresh` | Two sources put first-public time inside the freshness window |
| `stale` | Two sources put it outside, or page repackages older coverage |
| `unclear` | <2 sources, conflicting evidence, or no usable timestamp |

### Syndication detection

Signals of a repost: wire credit in byline, `rel=canonical` pointing elsewhere, body near-identical to an earlier item, aggregator framing ("read more at"), outlet with no original bylines across beats. A repost inherits the original's first-public time.

### Canonical-coverage selection

When several items cover one story, deliver one canonical item, link the rest via `duplicates_of`. Pick canonical by: originating outlet > earliest `published_at` > most complete five-fact record.

### Same-story vs new-development

| Question | Same story (consolidate) | New development (keep separate) |
|----------|--------------------------|---------------------------------|
| New named facts? | No | Yes |
| New primary source? | No | Yes |
| Event advanced? | No | Yes |
| Only framing/outlet changed? | Yes | -- |

Two+ "new development" answers = separate item.

Files in this skill

  • SKILL.md5.8 KB
  • evals/fixture-feed.json12.3 KB
  • evals/ground-truth.json5.3 KB
  • evals/rubric.md2.2 KB
  • references/coarse-filter.md2.2 KB
  • references/evidence-contract.md2.6 KB
  • references/freshness-forensics.md2.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.