docs: TechCrunch RSS integration PRD (#55)
Adds PRD for cross-referencing TechCrunch news with GitHub trends. Addresses review feedback: correlation rates, filtering, temporal alignment, and success criteria. Closes #55 revision cycle Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Juan Manuel Servera committed
May 19, 2026 at 14:54 UTC
38e6a74a2eba914e375fde646e0a8512eec58ef8
1 file changed
+443
docs/PRD-techcrunch-integration.md
new
+443
@@ -0,0 +1,443 @@
1
+# PRD: TechCrunch RSS Integration for Cross-Signal Enrichment
2
+
3
+**Author:** Farnsworth (Analyst), revised by Bender (Crawler)
4
+**Date:** 2026-05-19
5
+**Status:** Draft
6
+**Type:** Feature PRD (Enrichment Signal)
7
+**Depends on:** .squad/decisions.md (Decision #7 — Crawler Plugin Architecture), docs/PRD-topic-channels.md
8
+
9
+---
10
+
11
+## Executive Summary
12
+
13
+SquadScope tracks GitHub repository trends weekly. This PRD proposes adding TechCrunch RSS as a **supplementary enrichment signal** — not a primary data source — to detect the *delta* between press hype and actual GitHub traction. When TechCrunch covers a technology or project that also shows unusual GitHub star activity, that correlation is newsworthy. When press coverage does NOT correlate with GitHub activity, that absence is equally informative.
14
+
15
+**Key constraint acknowledged upfront:** The correlation hit rate between TechCrunch articles and specific GitHub repositories is estimated at only **5–15%**. This feature is designed as a low-cost enrichment layer that adds value when correlations exist, and degrades gracefully (adds zero noise) when they don't.
16
+
17
+---
18
+
19
+## Problem Statement
20
+
21
+### The Gap: Press Hype vs. Real Adoption
22
+
23
+1. **GitHub stars measure developer interest.** A repo gaining 500 stars in a week signals genuine traction from people who build things.
24
+
25
+2. **TechCrunch coverage measures press/VC interest.** An article about a startup or technology signals attention from the funding and media ecosystem.
26
+
27
+3. **The delta between these signals is the insight.** Three scenarios produce editorial value:
28
+ - **Hype confirmed:** TechCrunch covers X, and X's GitHub repos are surging → "Real momentum, developers agree"
29
+ - **Hype without substance:** TechCrunch covers Y, but Y has zero or declining GitHub activity → "Marketing over engineering"
30
+ - **Quiet breakout:** No press coverage, but a repo is exploding on GitHub → "Under the radar"
31
+
32
+4. **Currently, SquadScope only sees scenario 3.** Adding press signal enables detecting scenarios 1 and 2, making the weekly digest more insightful.
33
+
34
+### Why TechCrunch Specifically
35
+
36
+- TechCrunch has a well-maintained RSS feed (`http://techcrunch.com/feed`) with full article metadata
37
+- It covers the startup/tech ecosystem most likely to overlap with open-source GitHub activity
38
+- RSS is free, requires no API key, and is stable
39
+- Other sources (HN, Reddit) can follow the same plugin pattern later
40
+
41
+---
42
+
43
+## Value Proposition: The Delta Model
44
+
45
+The value of this integration is **NOT** in summarizing TechCrunch articles (readers can read TechCrunch themselves). The value is in the **cross-reference delta**:
46
+
47
+```
48
+Value = f(TechCrunch_coverage, GitHub_activity) where:
49
+ - Both high → "Confirmed trend" (correlation)
50
+ - TC high, GH low → "Hype alert" (anti-correlation)
51
+ - TC low, GH high → "Sleeper hit" (absence signal)
52
+ - Both low → No signal (filtered out)
53
+```
54
+
55
+This positions SquadScope as providing analysis that neither TechCrunch nor GitHub alone can offer.
56
+
57
+---
58
+
59
+## Honest Assessment: Correlation Rates
60
+
61
+### Expected Hit Rates
62
+
63
+| Correlation Type | Estimated Rate | Reasoning |
64
+|-----------------|---------------|-----------|
65
+| Direct match (TC mentions a specific repo) | 2–5% | Few TC articles name exact repos |
66
+| Indirect match (TC covers technology X, repo uses topic X) | 10–15% | Broader topic matching catches more |
67
+| No correlation found | 80–93% | Most TC articles have no GitHub signal |
68
+
69
+### Why Low Rates Are Acceptable
70
+
71
+1. **Low false-positive cost:** Uncorrelated articles are simply ignored — they add zero noise to the output.
72
+2. **High value per hit:** When a correlation IS found, it's genuinely interesting editorial content.
73
+3. **Asymmetric payoff:** Even 2–3 notable correlations per week would meaningfully enrich a weekly digest.
74
+4. **Trend over time:** Cross-referencing accumulated over weeks reveals patterns invisible in any single week.
75
+
76
+### What This Feature Is NOT
77
+
78
+- NOT a TechCrunch summarizer
79
+- NOT a primary data source for SquadScope
80
+- NOT expected to produce signal every week
81
+- NOT a replacement for GitHub-native trend detection
82
+
83
+---
84
+
85
+## Filtering Strategy
86
+
87
+### The Problem: Volume
88
+
89
+TechCrunch publishes **30–50 articles per day** (210–350 per week). Without aggressive filtering, this overwhelms the pipeline with noise. The crawler must reduce this to a manageable set before any correlation attempt.
90
+
91
+### Three-Stage Filtering Pipeline
92
+
93
+```
94
+Stage 1: Category Filter (RSS metadata)
95
+ Input: ~250 articles/week (full RSS feed)
96
+ Filter: Keep only categories relevant to developer tools/open-source
97
+ Output: ~60-80 articles/week (70% reduction)
98
+ Method: Allowlist of RSS <category> tags
99
+
100
+Stage 2: Keyword Filter (title + description)
101
+ Input: ~60-80 articles/week
102
+ Filter: Must contain technology/developer keywords
103
+ Output: ~20-30 articles/week (60% reduction)
104
+ Method: Keyword scoring (open-source, GitHub, developer, API, SDK, framework, etc.)
105
+
106
+Stage 3: Entity Extraction (lightweight)
107
+ Input: ~20-30 articles/week
108
+ Filter: Extract mentioned technologies, companies, project names
109
+ Output: ~20-30 enriched article records with entity tags
110
+ Method: Regex patterns + known project name dictionary
111
+```
112
+
113
+### Category Allowlist (Initial)
114
+
115
+```yaml
116
+allowed_categories:
117
+ - Apps
118
+ - Artificial Intelligence
119
+ - Cloud
120
+ - Developer
121
+ - Enterprise
122
+ - Hardware
123
+ - Open Source
124
+ - Robotics
125
+ - Security
126
+ - Startups
127
+
128
+blocked_categories:
129
+ - Media & Entertainment
130
+ - Transportation
131
+ - Government & Policy
132
+ - Crypto # Too noisy, low GitHub correlation
133
+```
134
+
135
+### Keyword Scoring
136
+
137
+Each article gets a relevance score (0–10) based on title + description:
138
+
139
+| Keyword Group | Weight | Examples |
140
+|--------------|--------|----------|
141
+| Direct GitHub mentions | +5 | "GitHub", "open source", "repository" |
142
+| Developer tools | +3 | "API", "SDK", "framework", "library", "CLI" |
143
+| Technology names | +2 | "Python", "Rust", "Kubernetes", "LLM" |
144
+| Funding/startup | +1 | "raises", "Series A", "launch" |
145
+
146
+**Threshold:** Articles scoring ≥ 3 proceed to entity extraction. Expected pass rate: ~40% of category-filtered articles.
147
+
148
+---
149
+
150
+## Temporal Alignment
151
+
152
+### The Problem: RSS is Real-Time, SquadScope is Weekly
153
+
154
+TechCrunch publishes continuously. SquadScope runs weekly (Monday 08:00 UTC). This creates a timing mismatch:
155
+
156
+- An article published Tuesday about Project X won't be seen until the following Monday
157
+- By then, the GitHub star surge may have already peaked and fallen
158
+
159
+### Solution: Weekly Batch with 7-Day Window
160
+
161
+```
162
+┌─────────────────────────────────────────────────────┐
163
+│ Monday 08:00 UTC: Crawl job runs │
164
+│ │
165
+│ 1. Fetch all RSS items from past 7 days │
166
+│ 2. Filter (3-stage pipeline above) │
167
+│ 3. Extract entities from filtered articles │
168
+│ 4. Cross-reference entities against weekly │
169
+│ GitHub trending repos (already collected) │
170
+│ 5. Output correlation data for Farnsworth │
171
+└─────────────────────────────────────────────────────┘
172
+```
173
+
174
+### Why Weekly Batch Is Sufficient
175
+
176
+1. **SquadScope is a weekly digest.** Real-time alerting is out of scope.
177
+2. **7-day accumulation helps.** A trend covered across multiple articles in a week is stronger signal.
178
+3. **GitHub stars data is also weekly.** Both signals align on the same time window.
179
+4. **Simplicity:** No state management, no incremental polling, no deduplication across runs.
180
+
181
+### Freshness Guarantee
182
+
183
+- RSS feed items older than 7 days are discarded
184
+- If the RSS feed doesn't contain 7 days of history (TechCrunch's feed typically holds 20–30 items), supplement with the feed's full available content
185
+- Each item's `<pubDate>` is checked against the collection window
186
+
187
+---
188
+
189
+## Correlation Approach
190
+
191
+### Entity-to-Repository Matching
192
+
193
+```
194
+TechCrunch Entity → GitHub Signal
195
+─────────────────────────────────────────────────
196
+"Anthropic" (company) → repos with topic:anthropic or org:anthropic
197
+"LangChain" (project) → repo langchain-ai/langchain stars_gained
198
+"Rust 2024 edition" (tech) → repos with topic:rust AND stars_gained > threshold
199
+"Series B: Acme Corp" → repos owned by acme-corp org
200
+```
201
+
202
+### Matching Strategies (in priority order)
203
+
204
+1. **Exact name match:** Article mentions "LangChain" → search for repos named `langchain*`
205
+2. **Organization match:** Article mentions company → search GitHub org
206
+3. **Topic match:** Article discusses technology → match against repo topics
207
+4. **Description match:** Fuzzy match article entities against repo descriptions
208
+
209
+### Scoring Correlation Strength
210
+
211
+| Match Type | Confidence | Example |
212
+|-----------|-----------|---------|
213
+| Exact repo name in article | 0.9 | "...announced on their GitHub repo langchain-ai/langchain..." |
214
+| Organization name + topic overlap | 0.7 | Article about Anthropic + repo topics include "claude" |
215
+| Technology keyword + trending | 0.5 | Article about "Rust" + Rust repo trending |
216
+| Company name only (no GitHub signal) | 0.3 | Article about startup with no public repos |
217
+
218
+### Output Format
219
+
220
+```json
221
+{
222
+ "week": "2026-W21",
223
+ "correlations": [
224
+ {
225
+ "article_title": "LangChain raises $25M Series A",
226
+ "article_url": "https://techcrunch.com/...",
227
+ "article_date": "2026-05-15",
228
+ "matched_repos": ["langchain-ai/langchain"],
229
+ "match_type": "exact_name",
230
+ "confidence": 0.9,
231
+ "github_signal": {
232
+ "stars_gained": 847,
233
+ "percentile": 98
234
+ },
235
+ "delta_type": "confirmed_trend"
236
+ }
237
+ ],
238
+ "unmatched_articles": 24,
239
+ "total_filtered_articles": 27
240
+}
241
+```
242
+
243
+---
244
+
245
+## Technical Implementation
246
+
247
+### Architecture: Plugin Pattern (Decision #7)
248
+
249
+This integration implements the `DataSource` protocol defined in Decision #7:
250
+
251
+```python
252
+class TechCrunchSource:
253
+ """TechCrunch RSS crawler plugin for SquadScope."""
254
+
255
+ def get_name(self) -> str:
256
+ return "techcrunch"
257
+
258
+ def get_rate_limits(self) -> RateLimits:
259
+ return RateLimits(
260
+ requests_per_minute=10, # Polite RSS polling
261
+ retry_after_seconds=60
262
+ )
263
+
264
+ def crawl(self, window_start: datetime, window_end: datetime) -> CrawlResult:
265
+ """Fetch, filter, and extract entities from TechCrunch RSS."""
266
+ raw_items = self._fetch_rss(window_start, window_end)
267
+ filtered = self._apply_filters(raw_items)
268
+ enriched = self._extract_entities(filtered)
269
+ return CrawlResult(source="techcrunch", items=enriched)
270
+```
271
+
272
+### File Layout
273
+
274
+```
275
+scripts/
276
+ sources/
277
+ __init__.py
278
+ base.py # DataSource protocol
279
+ techcrunch.py # TechCrunch RSS plugin
280
+ config/
281
+ techcrunch.yml # Category allowlist, keywords, thresholds
282
+data/
283
+ enrichment/
284
+ techcrunch/
285
+ 2026-W21.json # Weekly filtered articles + entities
286
+ correlations/
287
+ 2026-W21.json # Cross-reference results (output for Farnsworth)
288
+```
289
+
290
+### Dependencies
291
+
292
+| Dependency | Purpose | Size Impact |
293
+|-----------|---------|-------------|
294
+| `feedparser` | RSS parsing | ~200 KB, pure Python |
295
+| `re` (stdlib) | Entity extraction patterns | None |
296
+| `datetime` (stdlib) | Window filtering | None |
297
+
298
+No additional API keys or authentication required. RSS is public.
299
+
300
+### Integration with Existing Crawl Workflow
301
+
302
+```yaml
303
+# In crawl-and-publish.yml (additions only)
304
+- name: Crawl TechCrunch RSS
305
+ run: |
306
+ python3 scripts/sources/techcrunch.py \
307
+ --window-days 7 \
308
+ --output data/enrichment/techcrunch/$WEEK.json
309
+ env:
310
+ WEEK: ${{ env.WEEK }}
311
+
312
+- name: Cross-reference correlations
313
+ run: |
314
+ python3 scripts/correlate.py \
315
+ --github-data data/raw/$WEEK.json \
316
+ --techcrunch-data data/enrichment/techcrunch/$WEEK.json \
317
+ --output data/correlations/$WEEK.json
318
+```
319
+
320
+### Error Handling
321
+
322
+| Failure Mode | Response | Impact |
323
+|-------------|----------|--------|
324
+| RSS feed unreachable | Retry 3×, then skip TechCrunch for this week | None — enrichment is optional |
325
+| RSS feed format changed | Log warning, skip parsing, open issue | None — graceful degradation |
326
+| Zero correlations found | Normal — output empty correlations file | Expected most weeks |
327
+| Malformed XML in feed | Skip malformed items, process rest | Partial data is fine |
328
+
329
+---
330
+
331
+## Cost Estimate
332
+
333
+### Compute Cost
334
+
335
+| Resource | Usage | Cost |
336
+|---------|-------|------|
337
+| RSS fetch | 1 HTTP request/week | $0.00 |
338
+| Python processing | ~5 seconds CPU | $0.00 (free Actions minutes) |
339
+| Correlation script | ~2 seconds CPU | $0.00 |
340
+| **Total infrastructure cost** | | **$0.00/week** |
341
+
342
+### Token Cost (if Farnsworth uses correlations in analysis)
343
+
344
+| Component | Size | Tokens | Cost Impact |
345
+|-----------|------|--------|-------------|
346
+| Correlations JSON (typical week, 2–5 hits) | ~2 KB | ~570 | +$0.002/week |
347
+| Correlations JSON (zero hits) | ~0.2 KB | ~57 | +$0.0002/week |
348
+| Correlations JSON (exceptional week, 10+ hits) | ~5 KB | ~1,400 | +$0.004/week |
349
+
350
+**Annual token cost impact: $0.10–$0.21/year** (negligible relative to $16/year baseline).
351
+
352
+### Development Cost
353
+
354
+| Task | Effort | Priority |
355
+|------|--------|----------|
356
+| `techcrunch.py` plugin | 2–3 hours | Medium |
357
+| `correlate.py` script | 2–3 hours | Medium |
358
+| Configuration + tests | 1–2 hours | Medium |
359
+| Workflow integration | 1 hour | Low |
360
+| **Total** | **6–9 hours** | |
361
+
362
+---
363
+
364
+## Success Criteria
365
+
366
+### Quantitative Metrics (measured after 8 weeks of operation)
367
+
368
+| Metric | Target | Measurement |
369
+|--------|--------|-------------|
370
+| RSS fetch success rate | ≥ 95% | Weeks with successful fetch / total weeks |
371
+| Filter reduction ratio | 85–95% reduction | (Raw articles - filtered) / raw articles |
372
+| Correlation hit rate | ≥ 5% of filtered articles | Articles with ≥1 GitHub match / filtered articles |
373
+| False positive rate | ≤ 2% | Matches marked incorrect in manual review / total matches |
374
+| Zero-noise weeks | 100% | Weeks where zero-correlation produces zero output noise |
375
+| Enrichment value (subjective) | ≥ 3/5 quality rating | Monthly review: "Did correlations improve the digest?" |
376
+
377
+### Qualitative Success Indicators
378
+
379
+- At least 1 "hype vs reality" insight per month that wouldn't exist without this signal
380
+- Zero instances where TechCrunch noise degrades the digest quality
381
+- The feature is invisible when it has nothing useful to contribute
382
+
383
+### Failure Criteria (triggers feature removal)
384
+
385
+- Hit rate below 2% after 8 weeks → feature adds complexity without value
386
+- False positives above 10% → feature introduces noise
387
+- RSS feed breaks and stays broken for 4+ consecutive weeks → dependency unreliable
388
+- Farnsworth (analyst) consistently ignores correlation data in analysis → no downstream value
389
+
390
+---
391
+
392
+## Phased Rollout
393
+
394
+### Phase 1: RSS Collection Only (Week 1–2)
395
+
396
+- Implement `techcrunch.py` with 3-stage filtering
397
+- Output `data/enrichment/techcrunch/{week}.json`
398
+- No integration with analysis — just collect and validate filter quality
399
+- **Exit criteria:** Filter reduces volume by ≥ 80%, entity extraction produces meaningful tags
400
+
401
+### Phase 2: Correlation Script (Week 3–4)
402
+
403
+- Implement `correlate.py` cross-reference logic
404
+- Output `data/correlations/{week}.json`
405
+- Manual review of correlation quality for 2 weeks
406
+- **Exit criteria:** Hit rate ≥ 3%, false positive rate ≤ 5%
407
+
408
+### Phase 3: Analysis Integration (Week 5–6)
409
+
410
+- Farnsworth consumes `data/correlations/{week}.json` in analysis prompt
411
+- Correlation data appears in weekly digest when relevant
412
+- **Exit criteria:** At least 1 correlation adds editorial value in 2 of 4 weeks
413
+
414
+### Phase 4: Steady State (Week 7+)
415
+
416
+- Monitor success metrics
417
+- Tune keyword lists and category filters based on actual hit rates
418
+- Consider adding second source (HN) if TechCrunch proves the plugin model
419
+
420
+---
421
+
422
+## Open Questions
423
+
424
+| # | Question | Impact | Proposed Resolution |
425
+|---|----------|--------|---------------------|
426
+| OQ1 | Does TechCrunch's RSS feed include full article text or just excerpts? | Medium — affects entity extraction quality | Spike: inspect actual feed content. If excerpts only, extraction limited to title + summary. |
427
+| OQ2 | How stable is TechCrunch's RSS feed over time? | Low — RSS is a mature standard | Monitor for 4 weeks before hard dependency. Breakage triggers graceful skip. |
428
+| OQ3 | Should entity extraction use AI (LLM) or stay rule-based? | Medium — cost vs quality trade-off | Start rule-based (zero cost). Upgrade to LLM extraction in Phase 4 if hit rates are too low. |
429
+| OQ4 | What's the right confidence threshold for surfacing correlations? | Medium — affects noise level | Start conservative (confidence ≥ 0.7). Lower if too few results after 4 weeks. |
430
+| OQ5 | Should correlations appear as a separate section in the digest or inline? | Low — editorial decision | Defer to Farnsworth. Provide data; let analyst decide presentation. |
431
+| OQ6 | Can we use GitHub's topic taxonomy to improve matching? | Medium — could boost hit rate | Investigate `GET /repos/{owner}/{repo}/topics` coverage during Phase 2. |
432
+
433
+---
434
+
435
+## Relationship to Other PRDs
436
+
437
+- **PRD-topic-channels.md:** Topic channels define per-domain crawling. TechCrunch integration is orthogonal — it enriches ANY topic channel with press signal. A `rust` channel could correlate TechCrunch Rust articles with Rust repo trends.
438
+- **PRD-cost-estimation.md:** TechCrunch adds negligible cost ($0.10–$0.21/year in tokens). No budget concern.
439
+- **Decision #7 (Plugin Architecture):** TechCrunch is the first non-GitHub `DataSource` plugin, validating the extensible crawler design.
440
+
441
+---
442
+
443
+*This PRD will be updated with actual hit rates and filter performance after Phase 1 completes (target: 2 weeks post-implementation).*