Skip to content

feat: dedicated interpellations content generator with ministerial accountability analysis#1172

Merged
pethers merged 35 commits into
mainfrom
copilot/enhance-content-generators-pipeline
Mar 16, 2026
Merged

feat: dedicated interpellations content generator with ministerial accountability analysis#1172
pethers merged 35 commits into
mainfrom
copilot/enhance-content-generators-pipeline

Conversation

Copilot AI commented Mar 13, 2026

Copy link
Copy Markdown
Contributor
  • Dedicated interpellations routing in data-transformers/index.ts
  • Interpellations generator (interpellations.ts)
  • Interpellation-specific policy analysis in policy-analysis.ts
  • Type cleanup (duplicate mottagare removed)
  • Merge conflict resolution (×4 rounds)
  • 96 interpellations-specific tests
  • ip fallback localized for all 14 languages
  • Fix da/no/fi ipFallback to reference Swedish Riksdag, not other parliaments
  • Remove duplicate interpellations JSDoc bullet in content-generators/index.ts
  • Fix Finnish ipFallback inflection: Riksdagenin → Riksdagin (consistent with repo convention)
  • Hoist ipFallback to module-level IP_FALLBACK const (avoid per-call allocation)
  • Update JSDoc for generatePolicySignificance() to include 'ip'
  • Replace hard-coded UI text in tests with CONTENT_LABELS references
  • Consolidate overlapping interpellations test files (delete redundant file)
  • Replace weak toContain('3') assertion with specific '3 interpellations' match
Original prompt

This section details on the original issue you should resolve

<issue_title>Enhance Content Generators with AI-Powered Political Analysis Pipeline</issue_title>
<issue_description>## 📋 Issue Type
Feature / Enhancement

🎯 Objective

Transform all content generator modules (scripts/data-transformers/content-generators/*.ts and scripts/news-types/*.ts) from template-based text producers into AI-powered political analysis generators that analyze document content, identify policy implications, assess political dynamics, and produce nuanced political journalism. Currently, generators like propositions.ts, motions.ts, committee.ts produce content by formatting document metadata into HTML — the "analysis" is template text, not genuine AI analysis of what the documents say.

📊 Current State

  • 17 content generator files in scripts/data-transformers/content-generators/:
    • propositions.ts, motions.ts, committee.ts — article type generators using template formatting
    • generic.ts — fallback generator with basic document listing
    • shared.ts — shared utilities (document type labels, etc.)
    • swot-section.ts, stakeholder-swot-section.ts, dashboard-section.ts, mindmap-section.ts, sankey-section.ts, cia-overview-section.ts, economic-dashboard-section.ts — visualization generators
    • newsworthiness.ts — scoring function
    • month-ahead.ts, monthly-review.ts, week-ahead.ts — calendar-based generators
  • 8 news-type files in scripts/news-types/: weekly-review (5 files), monthly-review, month-ahead, breaking-news, motions, propositions, committee-reports, week-ahead
  • Template-based content: Functions like generateArticleContent() format document titles, dates, and committee names into HTML paragraphs — no analysis of document substance
  • No policy analysis: The policy-analysis.ts module has detectPolicyDomains() (keyword-based) and assessConfidenceLevel() — basic pattern matching, not AI analysis
  • "Deep analysis" is template text: generateDeepAnalysisSection() generates section headers and document lists, not analytical prose
  • Why it matters sections: Hardcoded explanatory sentences that are the same for every article of that type

🚀 Desired State

  • AI-generated political analysis in every content generator:
    • Propositions: AI analyzes what each proposition proposes, its policy implications, budget impact, affected populations, and political feasibility
    • Motions: AI assesses opposition strategy, likelihood of adoption, coalition dynamics, and policy alternatives being proposed
    • Committee reports: AI evaluates committee findings, dissenting opinions, cross-party agreements, and implementation recommendations
    • Interpellations: AI analyzes the debate dynamics, minister responses, accountability implications (with its own dedicated generator, not shared with motions)
    • Weekly/Monthly reviews: AI synthesizes the week/month's political developments into narrative analysis
  • Document content analysis: Generators must pass full document text (via enrichDocumentsWithContent()) to AI for substantive analysis
  • Political context injection: AI connects individual documents to broader political dynamics (coalition stability, election positioning, EU alignment)
  • "Why it matters" from AI: Explanatory text generated per-document from AI analysis, not hardcoded template sentences
  • Newsworthiness AI scoring: Replace keyword-based scoring with AI-assessed newsworthiness based on political significance, public impact, and precedent

🔧 Implementation Approach

Step 1: Create AI Content Analysis Module

// New: scripts/ai-analysis/content-analyzer.ts
interface ContentAnalysis {
  summary: string;
  policyImplications: string[];
  politicalContext: string;
  affectedPopulations: string[];
  budgetImpact?: string;
  feasibilityAssessment: string;
  whyItMatters: string;
  newsworthinessScore: number;
  relatedPolicies: string[];
}

async function analyzeDocumentContent(
  doc: RawDocument,
  topic: string | null,
  lang: Language
): Promise<ContentAnalysis>;

Step 2: Upgrade Each Content Generator

For each generator in content-generators/:

  1. Replace template formatting with AI content analysis call
  2. Pass enriched document full text (not just titles)
  3. Generate language-specific analysis (not translate-after)
  4. Include political context and policy implications
  5. Add confidence levels to claims

Step 3: Create Dedicated Interpellations Generator

  • New file: scripts/data-transformers/content-generators/interpellations.ts
  • Remove routing to motions generator in scripts/data-transformers/index.ts line 130
  • AI-focused on debate dynamics, accountability, and minister response quality

Step 4: Upgrade Newsworthiness Scoring

  • Replace keyword-based scoreNewsworthiness() with AI-assessed scoring
  • Score dimensions: political significance, p...

📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

…lity analysis

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copilot AI changed the title [WIP] Add AI-powered political analysis to content generators feat: dedicated interpellations content generator with ministerial accountability analysis Mar 13, 2026
Copilot AI requested a review from pethers March 13, 2026 18:24
@pethers
pethers requested a review from Copilot March 14, 2026 16:40
@github-actions github-actions Bot added refactor Code refactoring size-l Large change (250-1000 lines) labels Mar 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a dedicated interpellations content generator so interpellation articles are rendered with accountability/debate framing instead of being routed through the motions generator.

Changes:

  • Added generateInterpellationsContent() and wired interpellations routing to use it instead of generateMotionsContent().
  • Extended ContentLabelSet and populated new interpellations-specific labels across all 14 languages.
  • Updated barrel exports so the new generator is available throughout the data-transformers API.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
scripts/types/content.ts Adds interpellations-specific label keys to the shared label interface.
scripts/data-transformers/index.ts Routes interpellations article type to the dedicated generator and re-exports it.
scripts/data-transformers/content-generators/interpellations.ts New interpellations generator with thematic grouping and accountability section.
scripts/data-transformers/content-generators/index.ts Exports the new generator from the content-generators barrel.
scripts/data-transformers/content-generators.ts Re-exports the new generator from the legacy barrel entrypoint.
scripts/data-transformers/constants/content-labels-part1.ts Adds interpellations label strings/functions for en/sv/da/no/fi/de/fr.
scripts/data-transformers/constants/content-labels-part2.ts Adds interpellations label strings/functions for es/nl/ar/he/ja/ko/zh.

Comment on lines +144 to +148
const breakdownFn = L(lang, 'interpellationsBreakdown') as string | ((n: number) => string);
const breakdownText = typeof breakdownFn === 'function'
? breakdownFn(interpellations.length)
: `${interpellations.length} new interpellations filed.`;
content += `<p class="article-lede">${escapeHtml(String(breakdownText))}</p>\n`;
Comment on lines +44 to +49
// Fall back to looking for "till X statsråd" / "till statsminister" pattern in the title
const titleText = doc.titel || doc.title || '';
const toMatch = titleText.match(/(?:till|to|an|à)\s+([^–—\-]{3,60}?)(?:\s*[-–—]|\s*$)/i);
if (toMatch?.[1]) {
return toMatch[1].trim();
}

const docName = escapeHtml(doc.dokumentnamn || doc.dok_id || titleText);
const authorText = escapeHtml(doc.intressent_namn || doc.author || '');
const partyText = escapeHtml(normalizePartyKey(doc.parti).toUpperCase());
Comment on lines +162 to +166
const strategyFn = L(lang, 'oppositionStrategyContext') as string | ((n: number) => string);
const strategyContext = typeof strategyFn === 'function'
? strategyFn(partyCount)
: `Interpellations from ${partyCount} different parties demonstrate broad parliamentary scrutiny.`;
content += ` <p>${escapeHtml(String(strategyContext))}</p>\n`;
Comment on lines +201 to +205
const policyImpFn = L(lang, 'policyImplicationsContext') as string | ((p: number, d: number) => string);
const policyImpText = typeof policyImpFn === 'function'
? policyImpFn(interpellations.length, themeCount)
: `These ${interpellations.length} interpellations span ${themeCount} policy domain${themeCount !== 1 ? 's' : ''}, reflecting the breadth of parliamentary accountability demands.`;
content += ` <p>${escapeHtml(String(policyImpText))}</p>\n`;
Comment on lines +223 to +231
content += `\n <h2>${L(lang, 'coalitionDynamics')}</h2>\n`;
content += ` <div class="context-box">\n <ul>\n`;
Object.entries(byParty).forEach(([party, partyIps]) => {
if (party !== 'other') {
const detailFn = L(lang, 'partyMotionsFiled') as string | ((party: string, n: number) => string);
const detail = typeof detailFn === 'function'
? detailFn(party, partyIps.length)
: `${party}: ${partyIps.length} interpellations filed`;
content += ` <li>${escapeHtml(String(detail))}</li>\n`;
interpellationDefault: 'Parliamentary interpellation addressed to a minister.',
interpellationsBreakdown: (n: number): string => `Opposition MPs have filed ${n} interpellations demanding ministerial accountability. Interpellations are formal parliamentary questions that ministers must answer in chamber debate, making them a key tool of parliamentary scrutiny.`,
debateDynamics: 'Debate Dynamics & Accountability',
ministerAccountability: 'Minister Response',
@pethers

pethers commented Mar 14, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

- Tighten extractMinisterTarget() regex to require statsråd/minister terms
- Skip party display when parti is missing/unknown (no "OTHER" shown)
- Add interpellationsScrutinyContext label (replaces motion-specific oppositionStrategyContext)
- Add interpellationsAccountabilityContext label (replaces proposition-specific policyImplicationsContext)
- Add partyInterpellationsFiled label (replaces motion-specific partyMotionsFiled)
- Change ministerAccountability label to "Directed to" across all 14 languages
- Add comprehensive test suite (170 tests)

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>

Copilot AI commented Mar 14, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

All 7 review comments addressed in 6ea42be:

  1. Tests added — 170 tests covering label keys (all 14 langs), output content, minister target extraction, party rendering, empty state
  2. extractMinisterTarget() tightened — Regex now requires statsråd|statsminister|minister after match; "till Gaza" no longer misparsed
  3. Party rendering — Skips display when parti is missing/empty/"Unknown"; never shows OTHER
  4. oppositionStrategyContextinterpellationsScrutinyContext — New label in all 14 langs, no motion phrasing
  5. policyImplicationsContextinterpellationsAccountabilityContext — New label in all 14 langs, no proposition phrasing
  6. partyMotionsFiledpartyInterpellationsFiled — New label in all 14 langs, says "interpellations filed"
  7. ministerAccountability — Changed from "Minister Response" to "Directed to" / "Riktat till" across all 14 languages

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a dedicated content-generation path for the interpellations article type so interpellation articles render with interpellation-specific headings, labels, and accountability-focused analysis instead of reusing the motions generator.

Changes:

  • Introduces generateInterpellationsContent() with minister-target extraction, thematic grouping, accountability section, and deep analysis integration.
  • Routes interpellations article type to the new generator and exports it through existing barrels.
  • Extends ContentLabelSet and label constants across all 14 languages, and adds Vitest coverage for labels/output expectations.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/interpellations.test.ts Adds unit tests for interpellations labels and generator output constraints (no motions/propositions phrasing, minister extraction, party rendering).
scripts/types/content.ts Adds required interpellations-specific label keys to ContentLabelSet.
scripts/data-transformers/index.ts Routes interpellations to the dedicated generator and re-exports it.
scripts/data-transformers/content-generators/interpellations.ts Implements the new interpellations content generator (entries, grouping, accountability + deep analysis).
scripts/data-transformers/content-generators/index.ts Exposes generateInterpellationsContent from the content-generators barrel.
scripts/data-transformers/content-generators.ts Re-exports generateInterpellationsContent through the higher-level barrel.
scripts/data-transformers/constants/content-labels-part1.ts Adds interpellations label strings/functions for en/sv/da/no/fi/de/fr.
scripts/data-transformers/constants/content-labels-part2.ts Adds interpellations label strings/functions for es/nl/ar/he/ja/ko/zh.

Comment on lines +66 to +71
const docName = escapeHtml(doc.dokumentnamn || doc.dok_id || titleText);
const authorText = escapeHtml(doc.intressent_namn || doc.author || '');
// Only show party when the raw value is present and not an "Unknown" sentinel
const rawParti = typeof doc.parti === 'string' ? doc.parti.trim() : '';
const hasParty = rawParti !== '' && rawParti.toLowerCase() !== 'unknown';
const partyText = hasParty ? escapeHtml(rawParti.toUpperCase()) : '';
Comment on lines +44 to +52
// Fall back to looking for "till [name] statsråd|statsminister|minister" pattern in the title
// Only match when followed by a minister-related term to avoid false positives (e.g. "till Gaza")
const titleText = doc.titel || doc.title || '';
const ministerMatch = titleText.match(
/(?:till|to)\s+(.{3,60}?)\s*(?:statsråd|statsminister|minister)/i
);
if (ministerMatch?.[1]) {
return ministerMatch[1].trim();
}
*/
function extractMinisterTarget(doc: RawDocument): string {
// Some MCP responses include a mottagare (recipient) field
const mottagare = (doc as Record<string, unknown>)['mottagare'];
@pethers

pethers commented Mar 14, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread and TypeScript & JavaScript Testing / Unit Tests (Vitest) (pull_request)
TypeScript & JavaScript Testing / Unit Tests (Vitest) (pull_request)Failing after 1m

…, fix docstring, restore CI patterns

- Filter out "Unknown" sentinel values from author names (intressent_namn/author)
  so internal placeholders never leak to readers; added 3 tests.
- Add `mottagare` as a typed optional field on RawDocument instead of
  casting through Record<string, unknown>.
- Fix extractMinisterTarget() docstring to accurately describe checked
  fields (mottagare and title, not summary).
- Restore missing cross-referencing examples and date calculation helpers
  in news-evening-analysis.md to fix 4 pre-existing CI test failures
  (Example 1/2/3 patterns, .filter(), millisecond constants).

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

…Fallback inflection (Riksdagenin → Riksdagin)

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>

Copilot AI commented Mar 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

Fixed in 2f59a74:

  1. Duplicate JSDoc bullet — Removed the duplicate interpellations line in content-generators/index.ts, keeping the single entry with the "(dedicated, separate from motions)" qualifier.
  2. Finnish ipFallback inflection — Changed "Riksdagenin" → "Riksdagin" to match the established Finnish form used in coalition-loader.ts, generators.ts, and cia-overview-section.ts.

All 96 interpellations tests pass, TypeScript clean, CodeQL clean.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds and validates a dedicated interpellations content path in the data-transformers pipeline, including interpellation-specific policy-significance fallback text and type cleanup, backed by expanded tests.

Changes:

  • Added new interpellations-focused unit tests and expanded existing transformer tests for ip analysis behavior.
  • Updated policy significance generation with an ip-specific fallback message (localized) and updated JSDoc for deep analysis implied doc types.
  • Cleaned up RawDocument typing for mottagare and re-exported generateInterpellationsContent from the data-transformers barrel.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/interpellations.test.ts Adds interpellations-specific generator/label/output assertions.
tests/data-transformers.test.ts Adds ip-specific policy-analysis assertions to the main transformer test suite.
scripts/data-transformers/types.ts Moves/defines mottagare on RawDocument and removes duplicate field.
scripts/data-transformers/policy-analysis.ts Adds interpellation (ip) fallback significance text and updates deep-analysis JSDoc.
scripts/data-transformers/index.ts Re-exports generateInterpellationsContent from the data-transformers barrel.

Comment thread tests/interpellations.test.ts Outdated
Comment on lines +143 to +146
// Should contain multi-party strategy context heading
expect(result).toContain('Opposition Strategy');
// Should contain interpellation-specific strategy context (not motions phrasing)
expect(result).toContain('parliamentary oversight');
Comment on lines +596 to +613
// Interpellation-specific fallback: references minister obligation, not committee review
const doktyp2 = doc.doktyp || doc.documentType || impliedDoktyp || '';
if (doktyp2 === 'ip') {
const ipFallback: Record<string, string> = {
sv: 'Interpellationen debatteras i kammaren där ministern är skyldig att svara och förklara sina beslut.',
da: 'Interpellationen debatteres i Riksdagens kammare, hvor ministeren er forpligtet til at svare og stå til ansvar.',
no: 'Interpellasjonen debatteres i Riksdagens kammare, der ministeren er forpliktet til å svare og stå til ansvar.',
fi: 'Välikysymys käsitellään Riksdagin täysistunnossa, jossa ministerin on vastattava ja oltava tilivelvollinen.',
de: 'Die Interpellation wird in der Kammer debattiert, wobei der Minister verpflichtet ist, Rede und Antwort zu stehen.',
fr: "L'interpellation est débattue en séance plénière, où le ministre est tenu de répondre et de rendre des comptes.",
es: 'La interpelación se debate en el pleno, donde el ministro está obligado a responder y rendir cuentas.',
nl: 'De interpellatie wordt besproken in de Kamer, waar de minister verplicht is te antwoorden en verantwoording af te leggen.',
ar: 'تتم مناقشة الاستجواب في الجلسة العامة حيث يتعين على الوزير الرد وتحمل المسؤولية.',
he: 'האינטרפלציה נדונה במליאה, שם השר מחויב להשיב ולתת דין וחשבון.',
ja: '質問主意書は本会議で審議され、大臣は答弁と説明責任を果たす義務があります。',
ko: '대정부질문은 본회의에서 논의되며, 장관은 답변하고 책임을 져야 할 의무가 있습니다.',
zh: '质询在全体会议上进行辩论,部长有义务回应并承担责任。',
};
Comment on lines +596 to +600
// Interpellation-specific fallback: references minister obligation, not committee review
const doktyp2 = doc.doktyp || doc.documentType || impliedDoktyp || '';
if (doktyp2 === 'ip') {
const ipFallback: Record<string, string> = {
sv: 'Interpellationen debatteras i kammaren där ministern är skyldig att svara och förklara sina beslut.',
Comment thread tests/interpellations.test.ts Outdated
Comment on lines +1 to +16
/**
* Unit Tests for Interpellations Content Generator
* Validates:
* - Output does not contain motion/proposition-specific phrasing
* - Interpellations label keys exist for all 14 languages
* - Party rendering and coalition dynamics work correctly
* - Empty state renders appropriately
*/

import { describe, it, expect, afterEach, vi } from 'vitest';
import {
generateArticleContent,
CONTENT_LABELS,
} from '../scripts/data-transformers.js';
import type { Language } from '../scripts/types/language.js';

@pethers

pethers commented Mar 15, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

…e tests

1. Hoist ipFallback → module-level IP_FALLBACK const (Readonly<Record>)
   to avoid per-call allocation in generatePolicySignificance().
2. Update JSDoc to document 'ip' in impliedDoktyp param.
3. Replace hard-coded UI text in tests with CONTENT_LABELS references.
4. Delete redundant interpellations.test.ts; merge unique tests into
   interpellations-content-generator.test.ts (64 tests, no overlap).

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>

Copilot AI commented Mar 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

All 4 review comments addressed in ad4ab83:

  1. Hoisted ipFallback → module-level IP_FALLBACKReadonly<Record<string, string>> const avoids per-call allocation.
  2. Updated JSDocgeneratePolicySignificance() now documents 'ip' alongside 'mot', 'bet', 'prop'.
  3. Replaced hard-coded UI text in tests with CONTENT_LABELS.en.<key> references.
  4. Consolidated test files — Deleted redundant tests/interpellations.test.ts, merged unique tests (CSS class markers, analytical lede, ip policy fallback, label smoke tests) into tests/interpellations-content-generator.test.ts (64 tests).

All 3218 tests pass, TypeScript clean, CodeQL clean.

@pethers
pethers requested a review from Copilot March 16, 2026 00:09
@github-actions github-actions Bot added the size-m Medium change (50-250 lines) label Mar 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR finalizes first-class interpellations support in the data-transformers pipeline by adding dedicated generator plumbing and interpellation-specific policy significance fallbacks, backed by expanded regression tests.

Changes:

  • Added/expanded tests to verify interpellation-specific rendering (CSS markers, lede) and interpellation policy-analysis fallbacks across languages.
  • Cleaned up RawDocument typing by removing the duplicate mottagare field and keeping the canonical definition.
  • Added an interpellation-specific (ip) fallback path in generatePolicySignificance() (with a hoisted localized fallback map) and re-exported the interpellations generator via the data-transformers barrel.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/interpellations-content-generator.test.ts Adds regression tests for interpellation CSS markers, lede presence, and label/fallback smoke tests.
tests/data-transformers.test.ts Adds integration-style assertions ensuring interpellations uses ip-specific analysis (incl. localized fallback expectations).
scripts/data-transformers/types.ts Removes duplicated mottagare field and documents the remaining canonical property.
scripts/data-transformers/policy-analysis.ts Introduces module-level IP_FALLBACK and adds 'ip' handling in generatePolicySignificance()/JSDoc.
scripts/data-transformers/index.ts Re-exports generateInterpellationsContent from the data-transformers public API.

it('should include article-lede class with document count', () => {
const content = generateArticleContent({ interpellations: sampleInterpellations }, 'interpellations', 'en') as string;
expect(content).toContain('article-lede');
expect(content).toContain('3');
@pethers

pethers commented Mar 16, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

…ations' match

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>

Copilot AI commented Mar 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

Fixed in 5aa4b33: replaced toContain('3') with toContain('3 interpellations') so the assertion won't match unrelated digits. All 64 interpellations tests pass.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Signed-off-by: James Pether Sörling <pethers@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentic-workflow Agentic workflow changes ci-cd CI/CD pipeline changes documentation Documentation updates news News articles and content generation refactor Code refactoring size-l Large change (250-1000 lines) size-m Medium change (50-250 lines) size-xl Extra large change (> 1000 lines) testing Test coverage workflow GitHub Actions workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance Content Generators with AI-Powered Political Analysis Pipeline

3 participants