Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 17 additions & 3 deletions .github/workflows/news-monthly-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -746,12 +746,26 @@ EN/SV only: all headings, meta, content in correct language; no untranslated `da

## Step 3d: Economic Commentary (MANDATORY)

> After Step 3c and **before** calling `safeoutputs.create_pull_request`, re-open `economic-data.json` and replace the placeholder `commentary` string with a 2–4 sentence paragraph that:
> - cites **2–3 concrete numeric values** from `dataPoints`;
> - ties the numbers to the day's political developments (not definitions of indicators);
> After Step 3c and **before** calling `safeoutputs.create_pull_request`, re-open `economic-data.json` and replace the placeholder `commentary` string with a **6–8 sentence paragraph of ≥200 words** (enforced by `scripts/validate-economic-context.ts` — `monthly-review` = 200) that:
> - cites **≥4 concrete numeric values** from `dataPoints` (month-on-month or year-over-year changes, Nordic comparison, primary-indicator trajectory);
> - ties the numbers to the month's political developments (not definitions of indicators);
> - is written in plain English (translations are produced downstream by `news-translate`);
> - meets the minimum word count in the coverage matrix for this article type.
>
> Banned phrasings (the multi-dim quality score flags these): "The political landscape remains fluid…", "Touches on X policy…", pure indicator definitions.
>
> **Sankey / flow diagram** (required for `monthly-review`): `scripts/generate-news-enhanced/generators.ts` calls `buildArticleVisualizationSections` with `alwaysEmit: true` for this article type, so `class="sankey-section"` is auto-appended whenever the month has at least **one** document — even when every document collapses into a single doc-type bucket. The only case where no Sankey is emitted is an empty month (`docs.length === 0`); in that edge case the visualization builder returns an empty section list. The AI writer does not need to emit Sankey HTML directly — just verify the generated HTML contains `class="sankey-section"` before opening the PR:
> ```bash
> if grep -l 'class="sankey-section"' news/$ARTICLE_DATE-monthly-review-*.html; then
> echo "✅ Sankey section present"
> else
> doc_count=$(find "analysis/daily/$ARTICLE_DATE/monthly-review/documents" -maxdepth 1 -name '*.json' 2>/dev/null | wc -l)
> if [ "$doc_count" = "0" ]; then
> echo "ℹ️ Sankey section not emitted — the month has 0 documents (validator allows this)"
> else
> echo "❌ Sankey section missing — the validator will block the PR"; exit 1
> fi
> fi
> ```
Comment on lines +757 to +769
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Step 3d Sankey verification snippet computes doc_count from analysis/daily/$ARTICLE_DATE/monthly-review/economic-data.json using .docs, but economic-data.json doesn’t include a docs field (it has dataPoints, commentary, charts, source, etc.). This makes the jq expression effectively always return 0, which can incorrectly treat a missing class="sankey-section" as acceptable. Please base doc_count on the monthly-review documents source of truth (e.g., count JSONs under analysis/daily/$ARTICLE_DATE/monthly-review/documents/ if that directory is produced, or use the manifest the generator writes).

Copilot uses AI. Check for mistakes.
>
> Full rules: [`.github/aw/ECONOMIC_DATA_CONTRACT.md`](../aw/ECONOMIC_DATA_CONTRACT.md) §"Writing the AI commentary — workflow Step 3d".
20 changes: 17 additions & 3 deletions .github/workflows/news-weekly-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -737,12 +737,26 @@ EN/SV only: all headings, meta, content in correct language; no untranslated `da

## Step 3d: Economic Commentary (MANDATORY)

> After Step 3c and **before** calling `safeoutputs.create_pull_request`, re-open `economic-data.json` and replace the placeholder `commentary` string with a 2–4 sentence paragraph that:
> - cites **2–3 concrete numeric values** from `dataPoints`;
> - ties the numbers to the day's political developments (not definitions of indicators);
> After Step 3c and **before** calling `safeoutputs.create_pull_request`, re-open `economic-data.json` and replace the placeholder `commentary` string with a **4–6 sentence paragraph of ≥150 words** (enforced by `scripts/validate-economic-context.ts` — `weekly-review` = 150, `monthly-review` = 200) that:
> - cites **3 concrete numeric values** from `dataPoints` (e.g. Nordic GDP comparison + Swedish unemployment trajectory);
> - ties the numbers to the week's political developments (not definitions of indicators);
> - is written in plain English (translations are produced downstream by `news-translate`);
> - meets the minimum word count in the coverage matrix for this article type.
>
> Banned phrasings (the multi-dim quality score flags these): "The political landscape remains fluid…", "Touches on X policy…", pure indicator definitions.
>
> **Sankey / flow diagram** (required for `weekly-review`): `scripts/generate-news-enhanced/generators.ts` calls `buildArticleVisualizationSections` with `alwaysEmit: true` for this article type, so `class="sankey-section"` is auto-appended whenever the week has at least **one** document — even when every document collapses into a single doc-type bucket. The only case where no Sankey is emitted is an empty week (`docs.length === 0`); in that edge case the visualization builder returns an empty section list. The AI writer does not need to emit Sankey HTML directly — just verify the generated HTML contains `class="sankey-section"` before opening the PR:
> ```bash
> if grep -l 'class="sankey-section"' news/$ARTICLE_DATE-weekly-review-*.html; then
> echo "✅ Sankey section present"
> else
> doc_count=$(find "analysis/daily/$ARTICLE_DATE/weekly-review/documents" -maxdepth 1 -name '*.json' 2>/dev/null | wc -l)
> if [ "$doc_count" = "0" ]; then
> echo "ℹ️ Sankey section not emitted — the week has 0 documents (validator allows this)"
> else
> echo "❌ Sankey section missing — the validator will block the PR"; exit 1
> fi
> fi
Comment on lines +748 to +759
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Step 3d Sankey verification snippet computes doc_count from analysis/daily/$ARTICLE_DATE/weekly-review/economic-data.json using .docs, but economic-data.json does not contain a docs field (it has dataPoints, commentary, charts, source, etc.). As written, this jq expression will always yield 0, so it can incorrectly “allow” a missing class="sankey-section" even when the week had documents. Please derive the document count from an actual source of truth (e.g., the number of JSON files under analysis/daily/$ARTICLE_DATE/weekly-review/documents/, or another manifest used by the weekly-review pipeline).

Copilot uses AI. Check for mistakes.
> ```
>
> Full rules: [`.github/aw/ECONOMIC_DATA_CONTRACT.md`](../aw/ECONOMIC_DATA_CONTRACT.md) §"Writing the AI commentary — workflow Step 3d".
2 changes: 1 addition & 1 deletion analysis/daily/2026-04-18/weekly-review/economic-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
{ "countryCode": "SWE", "countryName": "Sweden", "indicatorId": "SL.UEM.TOTL.ZS", "indicatorName": "Unemployment Rate (%)", "date": "2022", "value": 7.417 },
{ "countryCode": "SWE", "countryName": "Sweden", "indicatorId": "SL.UEM.TOTL.ZS", "indicatorName": "Unemployment Rate (%)", "date": "2021", "value": 8.803 }
],
"commentary": "Sweden's 2026 Spring Budget arrives against a challenging backdrop: GDP growth of just 0.82% in 2024 — sharply trailing Denmark's 3.5% and Norway's 2.1% — while unemployment climbed to 8.7% in 2025, the highest since the pandemic. The government's Extra Amendment Budget cutting fuel taxes by 82 öre per litre directly targets the household cost pressure that has driven consumer confidence down, but the fuel-tax intervention risks undermining Sweden's green transition credibility at precisely the moment when the electricity system reform (Prop. 240) and wind power revenue-sharing (Prop. 239) signal serious climate ambition. The fiscal arithmetic is tight: Sweden recovered from its 2023 GDP contraction (-0.20%), but the pace of recovery lags Nordic peers, giving the Social Democrat opposition ammunition to challenge the government's economic stewardship heading into the September 2026 election.",
"commentary": "Sweden's 2026 Spring Budget arrives against a challenging backdrop: GDP growth of just 0.82% in 2024 — sharply trailing Denmark's 3.5% and Norway's 2.1% — while unemployment climbed to 8.7% in 2025, the highest since the pandemic. The government's Extra Amendment Budget cutting fuel taxes by 82 öre per litre directly targets the household cost pressure that has driven consumer confidence down, but the fuel-tax intervention risks undermining Sweden's green transition credibility at precisely the moment when the electricity system reform (Prop. 240) and wind power revenue-sharing (Prop. 239) signal serious climate ambition. The fiscal arithmetic is tight: Sweden recovered from its 2023 GDP contraction (-0.20%), but the pace of recovery lags Nordic peers, giving the Social Democrat opposition ammunition to challenge the government's economic stewardship heading into the September 2026 election. Finland's 0.42% 2024 growth further isolates Denmark (3.48%) and Norway (2.10%) as the Nordic outperformers, a comparison the Tidö coalition must explain as households face a fourth consecutive year above 7.4% unemployment. Labor-market data show the jobless rate falling from 8.8% (2021) through 7.4% (2022) before reversing to 7.6% (2023), 8.4% (2024) and 8.7% (2025) — a 1.3-percentage-point deterioration across two years that directly erodes the coalition's 2022 jobs mandate and reframes the Spring Budget debate around household resilience rather than reform ambition.",
"charts": [
{
"type": "nordic-comparison-bar",
Expand Down
71 changes: 68 additions & 3 deletions news/2026-04-18-weekly-review-en.html
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@ <h3 class="cia-panel-heading">Voting Alignment by Issue</h3>
</section></div>
<div id="economic-dashboard" class="economic-dashboard-section"><section class="article-dashboard" aria-label="Economic Context">
<h2>Economic Context</h2>
<p class="dashboard-summary">Sweden&#039;s 2026 Spring Budget arrives against a challenging backdrop: GDP growth of just 0.82% in 2024 — sharply trailing Denmark&#039;s 3.5% and Norway&#039;s 2.1% — while unemployment climbed to 8.7% in 2025, the highest since the pandemic. The government&#039;s Extra Amendment Budget cutting fuel taxes by 82 öre per litre directly targets the household cost pressure that has driven consumer confidence down, but the fuel-tax intervention risks undermining Sweden&#039;s green transition credibility at precisely the moment when the electricity system reform (Prop. 240) and wind power revenue-sharing (Prop. 239) signal serious climate ambition. The fiscal arithmetic is tight: Sweden recovered from its 2023 GDP contraction (-0.20%), but the pace of recovery lags Nordic peers, giving the Social Democrat opposition ammunition to challenge the government&#039;s economic stewardship heading into the September 2026 election.</p>
<p class="dashboard-summary">Sweden&#039;s 2026 Spring Budget arrives against a challenging backdrop: GDP growth of just 0.82% in 2024 — sharply trailing Denmark&#039;s 3.5% and Norway&#039;s 2.1% — while unemployment climbed to 8.7% in 2025, the highest since the pandemic. The government&#039;s Extra Amendment Budget cutting fuel taxes by 82 öre per litre directly targets the household cost pressure that has driven consumer confidence down, but the fuel-tax intervention risks undermining Sweden&#039;s green transition credibility at precisely the moment when the electricity system reform (Prop. 240) and wind power revenue-sharing (Prop. 239) signal serious climate ambition. The fiscal arithmetic is tight: Sweden recovered from its 2023 GDP contraction (-0.20%), but the pace of recovery lags Nordic peers, giving the Social Democrat opposition ammunition to challenge the government&#039;s economic stewardship heading into the September 2026 election. Finland&#039;s 0.42% 2024 growth further isolates Denmark (3.48%) and Norway (2.10%) as the Nordic outperformers, a comparison the Tidö coalition must explain as households face a fourth consecutive year above 7.4% unemployment. Labor-market data show the jobless rate falling from 8.8% (2021) through 7.4% (2022) before reversing to 7.6% (2023), 8.4% (2024) and 8.7% (2025) — a 1.3-percentage-point deterioration across two years that directly erodes the coalition&#039;s 2022 jobs mandate and reframes the Spring Budget debate around household resilience rather than reform ambition.</p>
<div class="dashboard-chart-wrapper">
<canvas id="econ-ny-gdp-mktp-kd-zg" role="img" aria-label="GDP Growth (2024)" data-chart-config="{&quot;type&quot;:&quot;bar&quot;,&quot;data&quot;:{&quot;labels&quot;:[&quot;Sweden&quot;,&quot;Denmark&quot;,&quot;Norway&quot;,&quot;Finland&quot;],&quot;datasets&quot;:[{&quot;label&quot;:&quot;GDP Growth (% annual)&quot;,&quot;data&quot;:[0.82,3.478,2.097,0.416],&quot;backgroundColor&quot;:[&quot;#00d9ff&quot;,&quot;#ff006e&quot;,&quot;#ffbe0b&quot;,&quot;#83cf39&quot;],&quot;borderColor&quot;:[&quot;#00b8d4&quot;,&quot;#d4004e&quot;,&quot;#d4a00b&quot;,&quot;#6daf2d&quot;],&quot;borderWidth&quot;:1}]},&quot;options&quot;:{&quot;responsive&quot;:true,&quot;maintainAspectRatio&quot;:true,&quot;plugins&quot;:{&quot;title&quot;:{&quot;display&quot;:true,&quot;text&quot;:&quot;GDP Growth (2024)&quot;,&quot;color&quot;:&quot;#e0e0e0&quot;,&quot;font&quot;:{&quot;size&quot;:14,&quot;weight&quot;:&quot;bold&quot;}},&quot;legend&quot;:{&quot;labels&quot;:{&quot;color&quot;:&quot;#e0e0e0&quot;,&quot;usePointStyle&quot;:true,&quot;padding&quot;:12}},&quot;tooltip&quot;:{&quot;backgroundColor&quot;:&quot;rgba(10,14,39,0.95)&quot;,&quot;titleColor&quot;:&quot;#00d9ff&quot;,&quot;bodyColor&quot;:&quot;#e0e0e0&quot;,&quot;borderColor&quot;:&quot;#00d9ff&quot;,&quot;borderWidth&quot;:1,&quot;cornerRadius&quot;:6,&quot;padding&quot;:10},&quot;annotation&quot;:{&quot;annotations&quot;:{&quot;annotation0&quot;:{&quot;type&quot;:&quot;line&quot;,&quot;yMin&quot;:1.7,&quot;yMax&quot;:1.7,&quot;borderColor&quot;:&quot;rgba(255,190,11,0.6)&quot;,&quot;label&quot;:{&quot;display&quot;:true,&quot;content&quot;:&quot;Avg: 1.7&quot;}}}}},&quot;scales&quot;:{&quot;x&quot;:{&quot;grid&quot;:{&quot;color&quot;:&quot;rgba(255,255,255,0.06)&quot;},&quot;ticks&quot;:{&quot;color&quot;:&quot;#b0b0b0&quot;}},&quot;y&quot;:{&quot;grid&quot;:{&quot;color&quot;:&quot;rgba(255,255,255,0.06)&quot;},&quot;ticks&quot;:{&quot;color&quot;:&quot;#b0b0b0&quot;},&quot;beginAtZero&quot;:true}}}}"></canvas>
</div>
Expand Down Expand Up @@ -1000,10 +1000,75 @@ <h2>Economic Context</h2>
</section></div>
</div>

<div id="sankey-section" class="sankey-section-wrapper"><section class="sankey-section" aria-label="Legislative Flow — Riksdag Week 16">
<h2>Legislative Flow — Riksdag Week 16</h2>
<p class="sankey-summary">Flow of Week 16 (2026-04-11 → 2026-04-17) Riksdag output from initiating actors to document types.</p>
<div class="sankey-chart-wrapper">
<svg viewBox="0 0 600 340" xmlns="http://www.w3.org/2000/svg"
role="img" aria-label="Legislative Flow — Riksdag Week 16"
style="width:100%;height:auto;max-width:600px;display:block;">
<title>Legislative Flow — Riksdag Week 16</title>
<rect width="600" height="340" fill="#0a0e27" rx="8"/>
<rect x="20" y="20" width="22" height="60"
fill="#003344" stroke="#00d9ff" stroke-width="2" rx="3"/>
<text x="48" y="50" text-anchor="start" dominant-baseline="middle"
font-size="11" fill="#00d9ff" font-family="monospace">Government Coalition (M/KD/L/SD)</text>
<rect x="20" y="100" width="22" height="40"
fill="#1a0033" stroke="#9d4edd" stroke-width="2" rx="3"/>
<text x="48" y="120" text-anchor="start" dominant-baseline="middle"
font-size="11" fill="#9d4edd" font-family="monospace">Foreign Ministry (UD)</text>
<rect x="20" y="160" width="22" height="50"
fill="#331500" stroke="#f77f00" stroke-width="2" rx="3"/>
<text x="48" y="185" text-anchor="start" dominant-baseline="middle"
font-size="11" fill="#f77f00" font-family="monospace">Riksdag Committees (KU/JuU/UFöU)</text>
<rect x="20" y="230" width="22" height="30"
fill="#1f3300" stroke="#83cf39" stroke-width="2" rx="3"/>
<text x="48" y="245" text-anchor="start" dominant-baseline="middle"
font-size="11" fill="#83cf39" font-family="monospace">Opposition (S/V/MP/C)</text>
<rect x="558" y="20" width="22" height="50"
fill="#003344" stroke="#00d9ff" stroke-width="2" rx="3"/>
<text x="552" y="45" text-anchor="end" dominant-baseline="middle"
font-size="11" fill="#00d9ff" font-family="monospace">Propositions (HD03100/99/236)</text>
<rect x="558" y="90" width="22" height="40"
fill="#1a0033" stroke="#9d4edd" stroke-width="2" rx="3"/>
<text x="552" y="110" text-anchor="end" dominant-baseline="middle"
font-size="11" fill="#9d4edd" font-family="monospace">Treaty Bills (HD03231/232)</text>
<rect x="558" y="150" width="22" height="60"
fill="#331500" stroke="#f77f00" stroke-width="2" rx="3"/>
<text x="552" y="180" text-anchor="end" dominant-baseline="middle"
font-size="11" fill="#f77f00" font-family="monospace">Committee Reports (KU32/33, JuU15, UFöU3)</text>
<rect x="558" y="230" width="22" height="30"
fill="#1f3300" stroke="#83cf39" stroke-width="2" rx="3"/>
<text x="552" y="245" text-anchor="end" dominant-baseline="middle"
font-size="11" fill="#83cf39" font-family="monospace">Opposition Motions</text>
<path d="M42,20 C311,20 311,20 580,20 L580,70 C311,70 311,70 42,80 Z" fill="#00d9ff44" stroke="#00d9ff" stroke-width="0.5" opacity="0.8"/>
<text x="300" y="45" text-anchor="middle" dominant-baseline="middle"
font-size="10" fill="#cccccc" font-family="monospace">3 propositions</text>
<path d="M42,100 C311,100 311,100 580,90 L580,130 C311,140 311,140 42,140 Z" fill="#9d4edd44" stroke="#9d4edd" stroke-width="0.5" opacity="0.8"/>
<text x="300" y="115" text-anchor="middle" dominant-baseline="middle"
font-size="10" fill="#cccccc" font-family="monospace">2 treaty bills</text>
<path d="M42,160 C311,160 311,160 580,150 L580,210 C311,210 311,210 42,210 Z" fill="#f77f0044" stroke="#f77f00" stroke-width="0.5" opacity="0.8"/>
<text x="300" y="185" text-anchor="middle" dominant-baseline="middle"
font-size="10" fill="#cccccc" font-family="monospace">4 committee reports</text>
<path d="M42,230 C311,230 311,230 580,230 L580,260 C311,260 311,260 42,260 Z" fill="#83cf3944" stroke="#83cf39" stroke-width="0.5" opacity="0.8"/>
<text x="300" y="245" text-anchor="middle" dominant-baseline="middle"
font-size="10" fill="#cccccc" font-family="monospace">Opposition motions</text>
</svg>
</div>
<table class="sankey-fallback-table sr-only" aria-label="Sankey data">
<caption>Riksdag Week 16 legislative flow</caption>
<thead><tr><th>Source</th><th>Target</th><th>Value</th><th>Note</th></tr></thead>
<tbody>
<tr><td>Government Coalition</td><td>Propositions</td><td>3</td><td>HD03100 Vårpropositionen, HD0399 Vårändringsbudgeten, HD03236 Extra ändringsbudget</td></tr>
<tr><td>Foreign Ministry</td><td>Treaty Bills</td><td>2</td><td>HD03231 Ukraine Tribunal, HD03232 International Compensation Commission</td></tr>
<tr><td>Riksdag Committees</td><td>Committee Reports</td><td>4</td><td>KU32, KU33, JuU15 (145–142), UFöU3</td></tr>
<tr><td>Opposition (S/V/MP/C)</td><td>Opposition Motions</td><td>1</td><td>Counter-motions filed against Spring Budget trilogy</td></tr>
</tbody>
</table>
</section></div>





<section class="analysis-references" aria-label="Analysis sources and methodology">
<h2>📊 Analysis &amp; Sources</h2>
<p>This article is based on AI-driven political intelligence analysis. Full methodology and analysis files:</p>
Expand Down
Loading
Loading