Previously Reddit was returning ~60% old content (some from 2022).
This commit adds multiple layers of date enforcement:
- Reddit prompt: Explicit from_date/to_date with "fewer results > older results"
- Hard filter: filter_by_date_range() in normalize.py excludes old content
- WebSearch Date Detective: Extracts dates from URLs (/2026/01/24/) and
snippets ("January 24, 2026", "3 days ago")
- WebSearch scoring: +10 bonus for verified dates, -20 penalty for unknown
The skill now guarantees only content from the last 30 days.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
11 KiB
fix: Enforce Strict 30-Day Date Filtering
Overview
The /last30days skill is returning content older than 30 days, violating its core promise. Analysis shows:
- Reddit: Only 40% of results within 30 days (9/15 were older, some from 2022!)
- X: 100% within 30 days (working correctly)
- WebSearch: 90% had unknown dates (can't verify freshness)
Problem Statement
The skill's name is "last30days" - users expect ONLY content from the last 30 days. Currently:
- Reddit search prompt says "prefer recent threads, but include older relevant ones if recent ones are scarce" - this is too permissive
- X search prompt explicitly includes
from_dateandto_date- this is why it works - WebSearch returns pages without publication dates - we can't verify they're recent
- Scoring penalties (-10 for low date confidence) don't prevent old content from appearing
Proposed Solution
Strategy: "Hard Filter, Not Soft Penalty"
Instead of penalizing old content, exclude it entirely. If it's not from the last 30 days, it shouldn't appear.
| Source | Current Behavior | New Behavior |
|---|---|---|
| Weak "prefer recent" | Explicit date range + hard filter | |
| X | Explicit date range (working) | No change needed |
| WebSearch | No date awareness | Require recent markers OR exclude |
Technical Approach
Phase 1: Fix Reddit Date Filtering
File: scripts/lib/openai_reddit.py
Current prompt (line 33):
Find {min_items}-{max_items} relevant Reddit discussion threads.
Prefer recent threads, but include older relevant ones if recent ones are scarce.
New prompt:
Find {min_items}-{max_items} relevant Reddit discussion threads from {from_date} to {to_date}.
CRITICAL: Only include threads posted within the last 30 days (after {from_date}).
Do NOT include threads older than {from_date}, even if they seem relevant.
If you cannot find enough recent threads, return fewer results rather than older ones.
Changes needed:
- Add
from_dateandto_dateparameters tosearch_reddit()function - Inject dates into
REDDIT_SEARCH_PROMPTlike X does - Update caller in
last30days.pyto pass dates
Phase 2: Add Hard Date Filtering (Post-Processing)
File: scripts/lib/normalize.py
Add a filter step that DROPS items with dates before from_date:
def filter_by_date_range(
items: List[Union[RedditItem, XItem, WebSearchItem]],
from_date: str,
to_date: str,
require_date: bool = False,
) -> List:
"""Hard filter: Remove items outside the date range.
Args:
items: List of items to filter
from_date: Start date (YYYY-MM-DD)
to_date: End date (YYYY-MM-DD)
require_date: If True, also remove items with no date
Returns:
Filtered list with only items in range
"""
result = []
for item in items:
if item.date is None:
if not require_date:
result.append(item) # Keep unknown dates (with penalty)
continue
# Hard filter: if date is before from_date, exclude
if item.date < from_date:
continue # DROP - too old
if item.date > to_date:
continue # DROP - future date (likely parsing error)
result.append(item)
return result
Phase 3: WebSearch Date Intelligence
WebSearch CAN find recent content - Medium posts have dates, GitHub has commit timestamps, news sites have publication dates. We should extract and prioritize these signals.
Strategy: "Date Detective"
-
Extract dates from URLs: Many sites embed dates in URLs
- Medium:
medium.com/@author/title-abc123(no date) vs news sites - GitHub: Look for commit dates, release dates in snippets
- News:
/2026/01/24/article-title - Blogs:
/blog/2026/01/title
- Medium:
-
Extract dates from snippets: Look for date markers
- "January 24, 2026", "Jan 2026", "yesterday", "this week"
- "Published:", "Posted:", "Updated:"
- Relative markers: "2 days ago", "last week"
-
Prioritize results with verifiable dates:
- Results with recent dates (within 30 days): Full score
- Results with old dates: EXCLUDE
- Results with no date signals: Heavy penalty (-20) but keep as supplementary
File: scripts/lib/websearch.py
Add date extraction functions:
import re
from datetime import datetime, timedelta
# Patterns for date extraction
URL_DATE_PATTERNS = [
r'/(\d{4})/(\d{2})/(\d{2})/', # /2026/01/24/
r'/(\d{4})-(\d{2})-(\d{2})/', # /2026-01-24/
r'/(\d{4})(\d{2})(\d{2})/', # /20260124/
]
SNIPPET_DATE_PATTERNS = [
r'(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* (\d{1,2}),? (\d{4})',
r'(\d{1,2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* (\d{4})',
r'(\d{4})-(\d{2})-(\d{2})',
r'Published:?\s*(\d{4}-\d{2}-\d{2})',
r'(\d{1,2}) (days?|hours?|minutes?) ago', # Relative dates
]
def extract_date_from_url(url: str) -> Optional[str]:
"""Try to extract a date from URL path."""
for pattern in URL_DATE_PATTERNS:
match = re.search(pattern, url)
if match:
# Parse and return YYYY-MM-DD format
...
return None
def extract_date_from_snippet(snippet: str) -> Optional[str]:
"""Try to extract a date from text snippet."""
for pattern in SNIPPET_DATE_PATTERNS:
match = re.search(pattern, snippet, re.IGNORECASE)
if match:
# Parse and return YYYY-MM-DD format
...
return None
def extract_date_signals(url: str, snippet: str, title: str) -> tuple[Optional[str], str]:
"""Extract date from any available signal.
Returns: (date_string, confidence)
- date from URL: 'high' confidence
- date from snippet: 'med' confidence
- no date found: None, 'low' confidence
"""
# Try URL first (most reliable)
url_date = extract_date_from_url(url)
if url_date:
return url_date, 'high'
# Try snippet
snippet_date = extract_date_from_snippet(snippet)
if snippet_date:
return snippet_date, 'med'
# Try title
title_date = extract_date_from_snippet(title)
if title_date:
return title_date, 'med'
return None, 'low'
Update WebSearch parsing to use date extraction:
def parse_websearch_results(results, topic, from_date, to_date):
items = []
for result in results:
url = result.get('url', '')
snippet = result.get('snippet', '')
title = result.get('title', '')
# Extract date signals
extracted_date, confidence = extract_date_signals(url, snippet, title)
# Hard filter: if we found a date and it's too old, skip
if extracted_date and extracted_date < from_date:
continue # DROP - verified old content
item = {
'date': extracted_date,
'date_confidence': confidence,
...
}
items.append(item)
return items
File: scripts/lib/score.py
Update WebSearch scoring to reward date-verified results:
# WebSearch date confidence adjustments
WEBSEARCH_NO_DATE_PENALTY = 20 # Heavy penalty for no date (was 10)
WEBSEARCH_VERIFIED_BONUS = 10 # Bonus for URL-verified recent date
def score_websearch_items(items):
for item in items:
...
# Date confidence adjustments
if item.date_confidence == 'high':
overall += WEBSEARCH_VERIFIED_BONUS # Reward verified dates
elif item.date_confidence == 'low':
overall -= WEBSEARCH_NO_DATE_PENALTY # Heavy penalty for unknown
...
Result: WebSearch results with verifiable recent dates rank well. Results with no dates are heavily penalized but still appear as supplementary context. Old verified content is excluded entirely.
Phase 4: Update Statistics Display
Only count Reddit and X in "from the last 30 days" claim. WebSearch should be clearly labeled as supplementary.
Acceptance Criteria
Functional Requirements
- Reddit search prompt includes explicit
from_dateandto_date - Items with dates before
from_dateare EXCLUDED, not just penalized - X search continues working (no regression)
- WebSearch extracts dates from URLs (e.g.,
/2026/01/24/) - WebSearch extracts dates from snippets (e.g., "January 24, 2026")
- WebSearch with verified recent dates gets +10 bonus
- WebSearch with no date signals gets -20 penalty (but still appears)
- WebSearch with verified OLD dates is EXCLUDED
Non-Functional Requirements
- No increase in API latency
- Graceful handling when few recent results exist (return fewer, not older)
- Clear user messaging when results are limited due to strict filtering
Quality Gates
- Test: Reddit search returns 0% results older than 30 days
- Test: X search continues to return 100% recent results
- Test: WebSearch is clearly differentiated in output
- Test: Edge case - topic with no recent content shows helpful message
Implementation Order
- Phase 1: Fix Reddit prompt (highest impact, simple change)
- Phase 2: Add hard date filter in normalize.py (safety net)
- Phase 3: Add WebSearch date extraction (URL + snippet parsing)
- Phase 4: Update WebSearch scoring (bonus for verified, heavy penalty for unknown)
- Phase 5: Update output display to show date confidence
Testing Plan
Before/After Test
Run same query before and after fix:
/last30days remotion launch videos
Expected Before:
- Reddit: 40% within 30 days
Expected After:
- Reddit: 100% within 30 days (or fewer results if not enough recent content)
Edge Case Tests
| Scenario | Expected Behavior |
|---|---|
| Topic with no recent content | Return 0 results + helpful message |
| Topic with 5 recent results | Return 5 results (not pad with old ones) |
| Mixed old/new results | Only return new ones |
WebSearch Date Extraction Tests
| URL/Snippet | Expected Date | Confidence |
|---|---|---|
medium.com/blog/2026/01/15/title |
2026-01-15 | high |
github.com/repo + "Released Jan 20, 2026" |
2026-01-20 | med |
docs.example.com/guide (no date signals) |
None | low |
news.site.com/2024/05/old-article |
2024-05-XX | EXCLUDE (too old) |
| Snippet: "Updated 3 days ago" | calculated | med |
Risk Analysis
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Fewer results for niche topics | High | Medium | Explain why in output |
| User confusion about reduced results | Medium | Low | Clear messaging |
| Date parsing errors exclude valid content | Low | Medium | Keep items with unknown dates, just label clearly |
References
Internal References
- Reddit search:
scripts/lib/openai_reddit.py:25-63 - X search (working example):
scripts/lib/xai_x.py:26-55 - Date confidence:
scripts/lib/dates.py:62-90 - Scoring penalties:
scripts/lib/score.py:149-153 - Normalization:
scripts/lib/normalize.py:49,99
External References
- OpenAI Responses API lacks native date filtering
- Must rely on prompt engineering + post-processing