Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
b30f104
feat: add multi-iteration AI analysis pipeline for news generation
Copilot Mar 13, 2026
fd2e4cb
fix: address 8 PR review comments on AI analysis pipeline
Copilot Mar 14, 2026
124b1e2
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 14, 2026
cd355f7
fix: address round 2 review comments and fix CI test failures
Copilot Mar 14, 2026
a05a08d
refactor: rename stub helpers to createMinimal/createEmpty per code r…
Copilot Mar 14, 2026
2809b6e
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 14, 2026
e2f665b
fix: address round 3 review comments — remove unused verbPlural, fix …
Copilot Mar 14, 2026
5bc1181
fix: update comment to accurately reflect nullish coalescing operator…
Copilot Mar 14, 2026
1802fc8
fix: address round 4 review — enrichedCount, score inflation, fractio…
Copilot Mar 14, 2026
072837c
fix: address round 5 review — self-contained examples, cache comment …
Copilot Mar 15, 2026
45fcb71
fix: self-contained workflow examples, regulatory snapshot branch for…
Copilot Mar 15, 2026
af9a1d1
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
fa7ad00
fix: guard emergingTrends empty-domain suffix + define lookbackHours …
Copilot Mar 15, 2026
7dc0dd3
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
98b837d
fix: escape domainPhrase in fallback buildStrategicImplications + cor…
Copilot Mar 15, 2026
aed2d0a
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
2d5bf42
fix: repair Markdown fences, fix emergingTrends docstring, remove unu…
Copilot Mar 15, 2026
2f28314
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
cdfee66
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
77ee955
fix: align EU doc classification with EU_TYPES, remove redundant Cach…
Copilot Mar 15, 2026
147572a
fix: enrichedCount uses contentFetched (consistent with codebase conv…
Copilot Mar 15, 2026
4a06df2
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
e3588bf
fix: buildDeepInspectionSections/buildKeyTakeaways EU doc classificat…
Copilot Mar 15, 2026
14eed42
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
caa6d0f
fix: close unclosed Markdown code fences in news-evening-analysis.md
Copilot Mar 15, 2026
19a8a6d
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 15, 2026
0e7c87f
fix: rename qualityScore→analysisScore, fix workflow variable inconsi…
Copilot Mar 15, 2026
e8daa7c
fix: SWOT score all 12 quadrants; stable cache keys; simplify govStre…
Copilot Mar 16, 2026
0025ebf
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
afc96f4
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
df74771
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
23b82ef
fix: add missing await on get_betankanden() in workflow doc example
Copilot Mar 16, 2026
8345bc1
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
6e3d4ba
Changes before error encountered
Copilot Mar 16, 2026
65a2845
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
be888db
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
21728c4
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
9592c5e
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
93514e7
Changes before error encountered
Copilot Mar 16, 2026
0d591eb
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
8e39594
fix: remove legacy SWOT/mindmap merge artifacts, fix cache size gette…
Copilot Mar 16, 2026
44733f7
fix: normalize empty focus topics and unify minimal analysis document…
Copilot Mar 16, 2026
7a685e9
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
01122b0
Merge branch 'main' into copilot/redesign-news-generation-pipeline
pethers Mar 16, 2026
856624e
fix: restore pre-merge state for generators/tests/docs to resolve rev…
Copilot Mar 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 61 additions & 35 deletions .github/workflows/news-evening-analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,18 @@ if (hoursSinceSync > 48) { /* add stale data disclaimer */ }

Use riksdag-regering-mcp (32 tools for Swedish parliament data). For ad-hoc queries, use `scripts/mcp-query-cli.ts` — NEVER implement custom MCP client code (PROHIBITION).

Calculate date range for queries (day-granularity via `.slice(0, 10)` truncation):
```js
const today = new Date().toISOString().slice(0, 10);
// lookback_hours input is rounded up to full days for date-string comparison
**Date calculation pattern:**
```javascript
const lookbackHours = 24; // adjust as needed (e.g. 8 for evening analysis, 168 for weekly)
const now = new Date();
const fromDate = new Date(now.getTime() - lookbackHours * 3600000); // 3600000 ms = 1 hour
Comment on lines +228 to +232
const weekAgo = new Date(now.getTime() - 7 * 86400000); // 86400000 ms = 1 day
Comment on lines +229 to +233
const today = now.toISOString().split('T')[0];
// ISO string variants for tools with native date params
const fromDateIso = fromDate.toISOString().slice(0, 10);
// Day-granularity date strings (via .slice(0, 10) truncation):
const lookbackDays = Math.ceil(lookbackHours / 24);
const fromDate = new Date(Date.now() - lookbackDays * 86400000).toISOString().slice(0, 10);
const fromDateStr = new Date(Date.now() - lookbackDays * 86400000).toISOString().slice(0, 10);
// For weekly review (Saturday): 5-day lookback = 5 * 86400000 ms
const weekFromDate = new Date(Date.now() - 5 * 86400000).toISOString().slice(0, 10);
```
Expand Down Expand Up @@ -261,18 +267,11 @@ const results = queryResults.filter(

Filter results to only include items with dates `>= fromDate` using ISO-string comparison (avoids timezone-sensitive `new Date()` parsing):
```js
const filtered = results.filter(item => (item.datum || item.publicerad || item.inlämnad || '').slice(0, 10) >= fromDate);
```

**Post-query date filtering pattern** (use with tools that lack native date params):
```javascript
// Calculate fromDate using ms constants: 86400000 ms/day, 3600000 ms/hour
const fromDate = new Date(Date.now() - lookbackHours * 3600000).toISOString().slice(0, 10);
const today = new Date().toISOString().slice(0, 10);

// Filter results by date field (day-granularity string comparison avoids timezone issues)
// Include inlämnad for motions which use that date field
const filtered = results.filter(item => (item.publicerad || item.datum || item.inlämnad || '').slice(0, 10) >= fromDate);
const filtered = results.filter(item =>
(item.datum || item.publicerad || item.inlämnad || '').slice(0, 10) >= fromDate
);
// Discouraged alternative: new Date() parsing — timezone/format sensitive
// const filtered = rawResults.filter(item => new Date(item.publicerad || item.datum || item.inlämnad) >= fromDate);
```

**Post-query date filtering example** (day-granularity; 86400000 ms = 1 day):
Expand All @@ -294,7 +293,7 @@ const fromDate = new Date(Date.now() - lookbackDays * 86400000).toISOString().sp

**Post-query filtering example:**
```javascript
const results = get_betankanden({ rm: currentRm, limit: 50 });
const results = await get_betankanden({ rm: currentRm, limit: 50 });
const recent = results.filter(b => (b.publicerad || '').slice(0, 10) >= fromDate);
```

Expand All @@ -320,39 +319,66 @@ Cross-reference related data sources for richer analysis. Filter all results by

**Example 1: Committee Report Deep Dive**
```javascript
// 1. Get recent committee reports
const betankanden = get_betankanden({ rm: currentRm, limit: 20 });
const recentBet = betankanden.filter(b => (b.publicerad || '').slice(0, 10) >= fromDate);
// Setup: riksmöte + date threshold (ISO-string comparison — timezone-safe)
const currentRm = '2025/26'; // adjust to current session
const fromDateIso = new Date(Date.now() - 7 * 86400000).toISOString().slice(0, 10); // YYYY-MM-DD
// 1. Fetch committee reports, filter by date using ISO-string comparison
const allReports = await get_betankanden({ rm: currentRm });
const reports = allReports.filter(r => (r.publicerad || r.datum || '').slice(0, 10) >= fromDateIso);
// 2. For each report, cross-reference voting records
for (const report of reports) {
const votes = await search_voteringar({ bet: report.beteckning });
}
```

// 2. For each report, get full details
const reportDetails = recentBet.map(bet =>
get_dokument({ dok_id: bet.dok_id, include_full_text: false })
);
**Example 2: Government Activity Analysis**
```javascript
// Setup: riksmöte + date threshold (ISO-string comparison — timezone-safe)
const currentRm = '2025/26'; // adjust to current session
const fromDateIso = new Date(Date.now() - 7 * 86400000).toISOString().slice(0, 10); // YYYY-MM-DD
// 1. Fetch propositions, filter by date using ISO-string comparison
const allProps = await get_propositioner({ rm: currentRm });
const props = allProps.filter(p => (p.publicerad || p.datum || '').slice(0, 10) >= fromDateIso);
// 2. Cross-reference with government press releases (native dateFrom param)
const press = await search_regering({ type: 'pressmeddelanden', dateFrom: fromDateIso });
```

// 3. Check related votes
const relatedVotes = search_voteringar({ rm: currentRm, limit: 50 })
.filter(v => recentBet.some(bet => v.bet === bet.beteckning));
**Example 3: Party Behavior Analysis**
```javascript
// Setup: riksmöte + date threshold + party (ISO-string comparison — timezone-safe)
const currentRm = '2025/26'; // adjust to current session
const fromDateIso = new Date(Date.now() - 7 * 86400000).toISOString().slice(0, 10); // YYYY-MM-DD
const partyCode = 'S'; // e.g. S, M, SD, V, MP, C, L, KD
// 1. Get motions filed by party, filter by date using ISO-string comparison
const allMotions = await get_motioner({ rm: currentRm });
const motions = allMotions.filter(m => (m.inlämnad || m.datum || '').slice(0, 10) >= fromDateIso);
// 2. Get party voting patterns, filter by date
const allVotes = await search_voteringar({ parti: partyCode, rm: currentRm });
const votes = allVotes.filter(v => (v.datum || '').slice(0, 10) >= fromDateIso);
```

**Example 2: Government Activity Analysis**
```javascript
// 1. Get government documents in date range
const govDocs = search_regering({ dateFrom: fromDate, dateTo: today, limit: 30 });
const fromDateIso = new Date(Date.now() - 7 * 86400000).toISOString().slice(0, 10);
const today = new Date().toISOString().slice(0, 10);
const govDocs = await search_regering({ dateFrom: fromDateIso, dateTo: today, limit: 30 });

// 2. Get related propositions
const propositions = get_propositioner({ rm: currentRm, limit: 20 })
.filter(p => (p.publicerad || '').slice(0, 10) >= fromDate);
const propositions = (await get_propositioner({ rm: currentRm, limit: 20 }))
.filter(p => (p.publicerad || '').slice(0, 10) >= fromDateIso);
```
Comment on lines +334 to +344

**Example 3: Party Behavior Analysis**
```javascript
// 1. Get party voting records
const votes = search_voteringar({ rm: currentRm, limit: 100 })
.filter(v => (v.datum || '').slice(0, 10) >= fromDate);
const fromDateIso = new Date(Date.now() - 7 * 86400000).toISOString().slice(0, 10);
const votes = (await search_voteringar({ rm: currentRm, limit: 100 }))
.filter(v => (v.datum || '').slice(0, 10) >= fromDateIso);

// 2. Get party speeches
const speeches = search_anforanden({ rm: currentRm, limit: 100 })
.filter(a => (a.datum || '').slice(0, 10) >= fromDate);
const speeches = (await search_anforanden({ rm: currentRm, limit: 100 }))
.filter(a => (a.datum || '').slice(0, 10) >= fromDateIso);
```

**Detailed Example: Committee Report Deep Dive**
Expand Down
Loading
Loading