euparliamentmonitor 0.8.19 → 0.8.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/package.json +7 -7
  2. package/scripts/constants/language-articles.d.ts +4 -0
  3. package/scripts/constants/language-articles.js +20 -0
  4. package/scripts/constants/language-ui.d.ts +8 -8
  5. package/scripts/constants/language-ui.js +64 -64
  6. package/scripts/constants/languages.d.ts +2 -2
  7. package/scripts/constants/languages.js +2 -2
  8. package/scripts/generators/news-enhanced.js +13 -3
  9. package/scripts/generators/pipeline/analysis-classification.d.ts +49 -0
  10. package/scripts/generators/pipeline/analysis-classification.js +333 -0
  11. package/scripts/generators/pipeline/analysis-existing.d.ts +67 -0
  12. package/scripts/generators/pipeline/analysis-existing.js +547 -0
  13. package/scripts/generators/pipeline/analysis-helpers.d.ts +140 -0
  14. package/scripts/generators/pipeline/analysis-helpers.js +266 -0
  15. package/scripts/generators/pipeline/analysis-risk.d.ts +49 -0
  16. package/scripts/generators/pipeline/analysis-risk.js +417 -0
  17. package/scripts/generators/pipeline/analysis-stage.d.ts +19 -39
  18. package/scripts/generators/pipeline/analysis-stage.js +219 -1704
  19. package/scripts/generators/pipeline/analysis-threats.d.ts +41 -0
  20. package/scripts/generators/pipeline/analysis-threats.js +142 -0
  21. package/scripts/generators/pipeline/fetch-stage.d.ts +25 -15
  22. package/scripts/generators/pipeline/fetch-stage.js +293 -117
  23. package/scripts/generators/strategies/article-strategy.d.ts +126 -7
  24. package/scripts/generators/strategies/article-strategy.js +491 -1
  25. package/scripts/generators/strategies/breaking-news-strategy.js +98 -8
  26. package/scripts/generators/strategies/committee-reports-strategy.js +23 -2
  27. package/scripts/generators/strategies/month-ahead-strategy.js +23 -2
  28. package/scripts/generators/strategies/monthly-review-strategy.js +13 -1
  29. package/scripts/generators/strategies/motions-strategy.js +15 -1
  30. package/scripts/generators/strategies/propositions-strategy.js +15 -1
  31. package/scripts/generators/strategies/week-ahead-strategy.js +19 -1
  32. package/scripts/generators/strategies/weekly-review-strategy.js +17 -1
  33. package/scripts/generators/synthesis-summary.d.ts +93 -0
  34. package/scripts/generators/synthesis-summary.js +364 -0
  35. package/scripts/index.d.ts +5 -2
  36. package/scripts/index.js +6 -1
  37. package/scripts/mcp/ep-mcp-client.d.ts +34 -1
  38. package/scripts/mcp/ep-mcp-client.js +110 -2
  39. package/scripts/mcp/mcp-connection.d.ts +3 -1
  40. package/scripts/mcp/mcp-connection.js +35 -4
  41. package/scripts/templates/article-template.js +24 -22
  42. package/scripts/templates/section-builders.js +2 -5
  43. package/scripts/types/index.d.ts +2 -1
  44. package/scripts/types/mcp.d.ts +7 -0
  45. package/scripts/types/political-classification.d.ts +1 -1
  46. package/scripts/types/quality.d.ts +9 -6
  47. package/scripts/types/significance.d.ts +130 -0
  48. package/scripts/types/significance.js +4 -0
  49. package/scripts/utils/article-quality-scorer.d.ts +13 -11
  50. package/scripts/utils/article-quality-scorer.js +36 -23
  51. package/scripts/utils/file-utils.d.ts +2 -2
  52. package/scripts/utils/file-utils.js +2 -2
  53. package/scripts/utils/html-sanitize.d.ts +10 -0
  54. package/scripts/utils/html-sanitize.js +32 -0
  55. package/scripts/utils/political-classification.d.ts +8 -7
  56. package/scripts/utils/political-classification.js +8 -7
  57. package/scripts/utils/political-risk-assessment.d.ts +1 -1
  58. package/scripts/utils/political-risk-assessment.js +1 -1
  59. package/scripts/utils/significance-scoring.d.ts +97 -0
  60. package/scripts/utils/significance-scoring.js +190 -0
@@ -0,0 +1,41 @@
1
+ import type { MarkdownBuilder } from './analysis-helpers.js';
2
+ import type { AnalysisMethod } from './analysis-stage.js';
3
+ /**
4
+ * Build markdown for the political threat landscape assessment.
5
+ *
6
+ * Uses the pipeline `date` parameter to ensure the assessment date in the
7
+ * generated markdown matches the `analysis/daily/{date}/` folder, overriding
8
+ * the `new Date()` timestamp that `assessPoliticalThreats()` stamps internally.
9
+ *
10
+ * @param fetchedData - Raw fetched EP data
11
+ * @param date - Analysis date (used to override assessment date for consistency)
12
+ * @returns Markdown content string
13
+ */
14
+ export declare function buildThreatLandscapeMarkdown(fetchedData: Record<string, unknown>, date: string): string;
15
+ /**
16
+ * Build markdown for actor threat profiling.
17
+ *
18
+ * @param fetchedData - Raw fetched EP data
19
+ * @param date - Analysis date
20
+ * @returns Markdown content string
21
+ */
22
+ export declare function buildActorThreatProfilingMarkdown(fetchedData: Record<string, unknown>, date: string): string;
23
+ /**
24
+ * Build markdown for consequence tree analysis.
25
+ *
26
+ * @param fetchedData - Raw fetched EP data
27
+ * @param date - Analysis date
28
+ * @returns Markdown content string
29
+ */
30
+ export declare function buildConsequenceTreesMarkdown(fetchedData: Record<string, unknown>, date: string): string;
31
+ /**
32
+ * Build markdown for legislative disruption analysis.
33
+ *
34
+ * @param fetchedData - Raw fetched EP data
35
+ * @param date - Analysis date
36
+ * @returns Markdown content string
37
+ */
38
+ export declare function buildLegislativeDisruptionMarkdown(fetchedData: Record<string, unknown>, date: string): string;
39
+ /** All threat assessment method builders keyed by their AnalysisMethod identifier */
40
+ export declare const THREAT_BUILDERS: Readonly<Partial<Record<AnalysisMethod, MarkdownBuilder>>>;
41
+ //# sourceMappingURL=analysis-threats.d.ts.map
@@ -0,0 +1,142 @@
1
+ // SPDX-FileCopyrightText: 2024-2026 Hack23 AB
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * @module Generators/Pipeline/AnalysisThreats
5
+ * @description Threat assessment analysis method builders for the analysis pipeline.
6
+ *
7
+ * Contains markdown builders for the **Threat Assessment** analysis method group:
8
+ * - `political-threat-landscape` — overall political threat assessment
9
+ * - `actor-threat-profiling` — individual actor threat profiles
10
+ * - `consequence-trees` — action-consequence chain analysis
11
+ * - `legislative-disruption` — legislative process disruption identification
12
+ */
13
+ import { assessPoliticalThreats, buildActorThreatProfiles, buildConsequenceTree, analyzeLegislativeDisruption, generateThreatAssessmentMarkdown, } from '../../utils/political-threat-assessment.js';
14
+ import { sanitizeCell, safeArr, toThreatInput, buildMarkdownHeader, EMPTY_TABLE_ROW_6, } from './analysis-helpers.js';
15
+ // ─── Per-method markdown builders ────────────────────────────────────────────
16
+ /**
17
+ * Build markdown for the political threat landscape assessment.
18
+ *
19
+ * Uses the pipeline `date` parameter to ensure the assessment date in the
20
+ * generated markdown matches the `analysis/daily/{date}/` folder, overriding
21
+ * the `new Date()` timestamp that `assessPoliticalThreats()` stamps internally.
22
+ *
23
+ * @param fetchedData - Raw fetched EP data
24
+ * @param date - Analysis date (used to override assessment date for consistency)
25
+ * @returns Markdown content string
26
+ */
27
+ export function buildThreatLandscapeMarkdown(fetchedData, date) {
28
+ const input = toThreatInput(fetchedData);
29
+ const assessment = assessPoliticalThreats(input);
30
+ return generateThreatAssessmentMarkdown({ ...assessment, date });
31
+ }
32
+ /**
33
+ * Build markdown for actor threat profiling.
34
+ *
35
+ * @param fetchedData - Raw fetched EP data
36
+ * @param date - Analysis date
37
+ * @returns Markdown content string
38
+ */
39
+ export function buildActorThreatProfilingMarkdown(fetchedData, date) {
40
+ const input = toThreatInput(fetchedData);
41
+ const profiles = buildActorThreatProfiles(input);
42
+ const header = buildMarkdownHeader('actor-threat-profiling', date, profiles.length > 0 ? 'medium' : 'low');
43
+ const profileRows = profiles.length > 0
44
+ ? profiles
45
+ .map((p) => `| ${sanitizeCell(p.actor)} | ${sanitizeCell(p.actorType)} | ${sanitizeCell(p.capability)} | ${sanitizeCell(p.motivation)} | ${sanitizeCell(p.opportunity)} | ${sanitizeCell(p.overallThreatLevel)} |`)
46
+ .join('\n')
47
+ : EMPTY_TABLE_ROW_6;
48
+ return (header +
49
+ `# Actor Threat Profiles
50
+
51
+ ## Overview
52
+ Individual threat profiles for ${profiles.length} political actors.
53
+
54
+ ## Actor Threat Matrix
55
+ | Actor | Type | Capability | Motivation | Opportunity | Threat Level |
56
+ |-------|------|------------|------------|-------------|--------------|
57
+ ${profileRows}
58
+
59
+ ## Date: ${date}
60
+ `);
61
+ }
62
+ /**
63
+ * Build markdown for consequence tree analysis.
64
+ *
65
+ * @param fetchedData - Raw fetched EP data
66
+ * @param date - Analysis date
67
+ * @returns Markdown content string
68
+ */
69
+ export function buildConsequenceTreesMarkdown(fetchedData, date) {
70
+ const input = toThreatInput(fetchedData);
71
+ const procedures = safeArr(fetchedData, 'procedures');
72
+ const header = buildMarkdownHeader('consequence-trees', date, 'medium');
73
+ const trees = [];
74
+ for (const raw of procedures.slice(0, 5)) {
75
+ const proc = raw && typeof raw === 'object' ? raw : null;
76
+ const rawTitle = proc ? String(proc['title'] ?? '') : '';
77
+ if (!rawTitle)
78
+ continue;
79
+ const title = sanitizeCell(rawTitle);
80
+ const tree = buildConsequenceTree(rawTitle, input);
81
+ trees.push(`### ${title}\n` +
82
+ `- **Immediate**: ${tree.immediateConsequences.map((c) => sanitizeCell(c.description)).join('; ') || 'No immediate consequences identified'}\n` +
83
+ `- **Secondary**: ${tree.secondaryEffects.map((c) => sanitizeCell(c.description)).join('; ') || 'No secondary effects identified'}\n` +
84
+ `- **Long-term**: ${tree.longTermImplications.map((c) => sanitizeCell(c.description)).join('; ') || 'No long-term implications identified'}\n` +
85
+ `- **Mitigating factors**: ${tree.mitigatingFactors.map((f) => sanitizeCell(f)).join(', ') || '—'}\n` +
86
+ `- **Amplifying factors**: ${tree.amplifyingFactors.map((f) => sanitizeCell(f)).join(', ') || '—'}`);
87
+ }
88
+ return (header +
89
+ `# Consequence Tree Analysis
90
+
91
+ ## Overview
92
+ Structured analysis of action-consequence chains for ${Math.min(procedures.length, 5)} legislative procedures.
93
+
94
+ ${trees.length > 0 ? trees.join('\n\n') : '## No procedures available for consequence analysis'}
95
+
96
+ ## Date: ${date}
97
+ `);
98
+ }
99
+ /**
100
+ * Build markdown for legislative disruption analysis.
101
+ *
102
+ * @param fetchedData - Raw fetched EP data
103
+ * @param date - Analysis date
104
+ * @returns Markdown content string
105
+ */
106
+ export function buildLegislativeDisruptionMarkdown(fetchedData, date) {
107
+ const input = toThreatInput(fetchedData);
108
+ const procedures = safeArr(fetchedData, 'procedures');
109
+ const header = buildMarkdownHeader('legislative-disruption', date, 'medium');
110
+ const disruptions = [];
111
+ for (const raw of procedures.slice(0, 5)) {
112
+ const proc = raw && typeof raw === 'object' ? raw : null;
113
+ const id = proc ? String(proc['procedureId'] ?? proc['id'] ?? '') : '';
114
+ const title = proc ? String(proc['title'] ?? '') : '';
115
+ if (!id || !title)
116
+ continue;
117
+ const analysis = analyzeLegislativeDisruption(id, input);
118
+ const disruptionCount = analysis.disruptionPoints.length;
119
+ disruptions.push(`| ${sanitizeCell(id)} | ${sanitizeCell(title.slice(0, 50))} | ${sanitizeCell(analysis.currentStage)} | ${sanitizeCell(analysis.resilience)} | ${disruptionCount} |`);
120
+ }
121
+ return (header +
122
+ `# Legislative Disruption Analysis
123
+
124
+ ## Overview
125
+ Identification of factors disrupting the normal legislative process.
126
+
127
+ ## Disruption Assessment
128
+ | Procedure ID | Title | Stage | Resilience | Disruption Points |
129
+ |-------------|-------|-------|-----------|-------------------|
130
+ ${disruptions.length > 0 ? disruptions.join('\n') : '| — | — | — | — | — |'}
131
+
132
+ ## Date: ${date}
133
+ `);
134
+ }
135
+ /** All threat assessment method builders keyed by their AnalysisMethod identifier */
136
+ export const THREAT_BUILDERS = {
137
+ 'political-threat-landscape': buildThreatLandscapeMarkdown,
138
+ 'actor-threat-profiling': buildActorThreatProfilingMarkdown,
139
+ 'consequence-trees': buildConsequenceTreesMarkdown,
140
+ 'legislative-disruption': buildLegislativeDisruptionMarkdown,
141
+ };
142
+ //# sourceMappingURL=analysis-threats.js.map
@@ -217,25 +217,29 @@ export declare function fetchPipelineFromMCP(client: EuropeanParliamentMCPClient
217
217
  export declare function fetchProcedureStatusFromMCP(client: EuropeanParliamentMCPClient | null, procedureId: string): Promise<string>;
218
218
  /**
219
219
  * Fetch adopted texts feed from MCP.
220
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
220
221
  *
221
222
  * @param client - MCP client or null
222
- * @param timeframe - How far back to look (default: 'one-day')
223
+ * @param timeframe - How far back to look (default: 'one-week')
223
224
  * @returns Array of adopted text feed items
224
225
  */
225
226
  export declare function fetchAdoptedTextsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<AdoptedTextFeedItem[]>;
226
227
  /**
227
228
  * Fetch events feed from MCP.
229
+ * Falls back to a wider timeframe when the initial timeframe returns no data
230
+ * (common during parliamentary recess when the EP API returns 404 for narrow windows).
228
231
  *
229
232
  * @param client - MCP client or null
230
- * @param timeframe - How far back to look (default: 'one-day')
233
+ * @param timeframe - How far back to look (default: 'one-week')
231
234
  * @returns Array of event feed items
232
235
  */
233
236
  export declare function fetchEventsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<EventFeedItem[]>;
234
237
  /**
235
238
  * Fetch procedures feed from MCP.
239
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
236
240
  *
237
241
  * @param client - MCP client or null
238
- * @param timeframe - How far back to look (default: 'one-day')
242
+ * @param timeframe - How far back to look (default: 'one-week')
239
243
  * @returns Array of procedure feed items
240
244
  */
241
245
  export declare function fetchProceduresFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<ProcedureFeedItem[]>;
@@ -243,7 +247,7 @@ export declare function fetchProceduresFeed(client: EuropeanParliamentMCPClient
243
247
  * Fetch MEPs feed from MCP.
244
248
  *
245
249
  * @param client - MCP client or null
246
- * @param timeframe - How far back to look (default: 'one-day')
250
+ * @param timeframe - How far back to look (default: 'one-week')
247
251
  * @returns Array of MEP feed items
248
252
  */
249
253
  export declare function fetchMEPsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<MEPFeedItem[]>;
@@ -258,7 +262,7 @@ export declare function fetchMEPsFeed(client: EuropeanParliamentMCPClient | null
258
262
  * updates, the `total` field in the API response carries the true count.
259
263
  *
260
264
  * @param client - MCP client or null
261
- * @param timeframe - How far back to look (default: 'one-day')
265
+ * @param timeframe - How far back to look (default: 'one-week')
262
266
  * @returns Object with `items` array and `total` count from the API
263
267
  */
264
268
  export declare function fetchMEPsFeedWithTotal(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<{
@@ -267,49 +271,55 @@ export declare function fetchMEPsFeedWithTotal(client: EuropeanParliamentMCPClie
267
271
  }>;
268
272
  /**
269
273
  * Fetch documents feed from MCP.
274
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
270
275
  *
271
276
  * @param client - MCP client or null
272
- * @param timeframe - How far back to look (default: 'one-day')
277
+ * @param timeframe - How far back to look (default: 'one-week')
273
278
  * @returns Array of document feed items
274
279
  */
275
280
  export declare function fetchDocumentsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<DocumentFeedItem[]>;
276
281
  /**
277
282
  * Fetch plenary documents feed from MCP.
283
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
278
284
  *
279
285
  * @param client - MCP client or null
280
- * @param timeframe - How far back to look (default: 'one-day')
286
+ * @param timeframe - How far back to look (default: 'one-week')
281
287
  * @returns Array of document feed items
282
288
  */
283
289
  export declare function fetchPlenaryDocumentsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<DocumentFeedItem[]>;
284
290
  /**
285
291
  * Fetch committee documents feed from MCP.
292
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
286
293
  *
287
294
  * @param client - MCP client or null
288
- * @param timeframe - How far back to look (default: 'one-day')
295
+ * @param timeframe - How far back to look (default: 'one-week')
289
296
  * @returns Array of document feed items
290
297
  */
291
298
  export declare function fetchCommitteeDocumentsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<DocumentFeedItem[]>;
292
299
  /**
293
300
  * Fetch plenary session documents feed from MCP.
301
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
294
302
  *
295
303
  * @param client - MCP client or null
296
- * @param timeframe - How far back to look (default: 'one-day')
304
+ * @param timeframe - How far back to look (default: 'one-week')
297
305
  * @returns Array of document feed items
298
306
  */
299
307
  export declare function fetchPlenarySessionDocumentsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<DocumentFeedItem[]>;
300
308
  /**
301
309
  * Fetch external documents feed from MCP.
310
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
302
311
  *
303
312
  * @param client - MCP client or null
304
- * @param timeframe - How far back to look (default: 'one-day')
313
+ * @param timeframe - How far back to look (default: 'one-week')
305
314
  * @returns Array of document feed items
306
315
  */
307
316
  export declare function fetchExternalDocumentsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<DocumentFeedItem[]>;
308
317
  /**
309
318
  * Fetch parliamentary questions feed from MCP.
319
+ * Falls back to a wider timeframe when the initial timeframe returns no data.
310
320
  *
311
321
  * @param client - MCP client or null
312
- * @param timeframe - How far back to look (default: 'one-day')
322
+ * @param timeframe - How far back to look (default: 'one-week')
313
323
  * @returns Array of question feed items
314
324
  */
315
325
  export declare function fetchQuestionsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<QuestionFeedItem[]>;
@@ -317,7 +327,7 @@ export declare function fetchQuestionsFeed(client: EuropeanParliamentMCPClient |
317
327
  * Fetch MEP declarations feed from MCP.
318
328
  *
319
329
  * @param client - MCP client or null
320
- * @param timeframe - How far back to look (default: 'one-day')
330
+ * @param timeframe - How far back to look (default: 'one-week')
321
331
  * @returns Array of declaration feed items
322
332
  */
323
333
  export declare function fetchDeclarationsFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<DeclarationFeedItem[]>;
@@ -325,7 +335,7 @@ export declare function fetchDeclarationsFeed(client: EuropeanParliamentMCPClien
325
335
  * Fetch corporate bodies feed from MCP.
326
336
  *
327
337
  * @param client - MCP client or null
328
- * @param timeframe - How far back to look (default: 'one-day')
338
+ * @param timeframe - How far back to look (default: 'one-week')
329
339
  * @returns Array of corporate body feed items
330
340
  */
331
341
  export declare function fetchCorporateBodiesFeed(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<CorporateBodyFeedItem[]>;
@@ -335,7 +345,7 @@ export declare function fetchCorporateBodiesFeed(client: EuropeanParliamentMCPCl
335
345
  * Returns `undefined` when client is null (MCP unavailable).
336
346
  *
337
347
  * @param client - MCP client or null
338
- * @param timeframe - How far back to look (default: 'one-day')
348
+ * @param timeframe - How far back to look (default: 'one-week')
339
349
  * @returns Aggregated feed data for breaking news, or undefined when client is null
340
350
  */
341
351
  export declare function fetchBreakingNewsFeedData(client: EuropeanParliamentMCPClient | null, timeframe?: FeedTimeframe): Promise<BreakingNewsFeedData | undefined>;
@@ -344,7 +354,7 @@ export declare function fetchBreakingNewsFeedData(client: EuropeanParliamentMCPC
344
354
  * This is the primary data source for all article strategies.
345
355
  *
346
356
  * @param client - MCP client or null
347
- * @param timeframe - How far back to look (default: 'one-day')
357
+ * @param timeframe - How far back to look (default: 'one-week')
348
358
  * @param dateRange - Optional inclusive UTC window for filtering feed items
349
359
  * @returns Full EPFeedData or undefined when client is null
350
360
  */