euparliamentmonitor 0.8.4
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.
- package/LICENSE +201 -0
- package/README.md +1005 -0
- package/SECURITY.md +151 -0
- package/package.json +131 -0
- package/scripts/constants/committee-indicator-map.d.ts +199 -0
- package/scripts/constants/committee-indicator-map.d.ts.map +1 -0
- package/scripts/constants/committee-indicator-map.js +1224 -0
- package/scripts/constants/committee-indicator-map.js.map +1 -0
- package/scripts/constants/config.d.ts +38 -0
- package/scripts/constants/config.d.ts.map +1 -0
- package/scripts/constants/config.js +66 -0
- package/scripts/constants/config.js.map +1 -0
- package/scripts/constants/language-articles.d.ts +84 -0
- package/scripts/constants/language-articles.d.ts.map +1 -0
- package/scripts/constants/language-articles.js +6771 -0
- package/scripts/constants/language-articles.js.map +1 -0
- package/scripts/constants/language-core.d.ts +38 -0
- package/scripts/constants/language-core.d.ts.map +1 -0
- package/scripts/constants/language-core.js +90 -0
- package/scripts/constants/language-core.js.map +1 -0
- package/scripts/constants/language-ui.d.ts +82 -0
- package/scripts/constants/language-ui.d.ts.map +1 -0
- package/scripts/constants/language-ui.js +889 -0
- package/scripts/constants/language-ui.js.map +1 -0
- package/scripts/constants/languages.d.ts +14 -0
- package/scripts/constants/languages.d.ts.map +1 -0
- package/scripts/constants/languages.js +15 -0
- package/scripts/constants/languages.js.map +1 -0
- package/scripts/generators/analysis-builders.d.ts +266 -0
- package/scripts/generators/analysis-builders.d.ts.map +1 -0
- package/scripts/generators/analysis-builders.js +2903 -0
- package/scripts/generators/analysis-builders.js.map +1 -0
- package/scripts/generators/breaking-content.d.ts +45 -0
- package/scripts/generators/breaking-content.d.ts.map +1 -0
- package/scripts/generators/breaking-content.js +530 -0
- package/scripts/generators/breaking-content.js.map +1 -0
- package/scripts/generators/committee-helpers.d.ts +54 -0
- package/scripts/generators/committee-helpers.d.ts.map +1 -0
- package/scripts/generators/committee-helpers.js +154 -0
- package/scripts/generators/committee-helpers.js.map +1 -0
- package/scripts/generators/dashboard-content.d.ts +95 -0
- package/scripts/generators/dashboard-content.d.ts.map +1 -0
- package/scripts/generators/dashboard-content.js +630 -0
- package/scripts/generators/dashboard-content.js.map +1 -0
- package/scripts/generators/deep-analysis-content.d.ts +23 -0
- package/scripts/generators/deep-analysis-content.d.ts.map +1 -0
- package/scripts/generators/deep-analysis-content.js +831 -0
- package/scripts/generators/deep-analysis-content.js.map +1 -0
- package/scripts/generators/mindmap-content.d.ts +55 -0
- package/scripts/generators/mindmap-content.d.ts.map +1 -0
- package/scripts/generators/mindmap-content.js +512 -0
- package/scripts/generators/mindmap-content.js.map +1 -0
- package/scripts/generators/motions-content.d.ts +50 -0
- package/scripts/generators/motions-content.d.ts.map +1 -0
- package/scripts/generators/motions-content.js +391 -0
- package/scripts/generators/motions-content.js.map +1 -0
- package/scripts/generators/news-enhanced.d.ts +14 -0
- package/scripts/generators/news-enhanced.d.ts.map +1 -0
- package/scripts/generators/news-enhanced.js +169 -0
- package/scripts/generators/news-enhanced.js.map +1 -0
- package/scripts/generators/news-indexes.d.ts +31 -0
- package/scripts/generators/news-indexes.d.ts.map +1 -0
- package/scripts/generators/news-indexes.js +410 -0
- package/scripts/generators/news-indexes.js.map +1 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts +352 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/fetch-stage.js +1522 -0
- package/scripts/generators/pipeline/fetch-stage.js.map +1 -0
- package/scripts/generators/pipeline/generate-stage.d.ts +43 -0
- package/scripts/generators/pipeline/generate-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/generate-stage.js +204 -0
- package/scripts/generators/pipeline/generate-stage.js.map +1 -0
- package/scripts/generators/pipeline/output-stage.d.ts +48 -0
- package/scripts/generators/pipeline/output-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/output-stage.js +145 -0
- package/scripts/generators/pipeline/output-stage.js.map +1 -0
- package/scripts/generators/pipeline/transform-stage.d.ts +57 -0
- package/scripts/generators/pipeline/transform-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/transform-stage.js +111 -0
- package/scripts/generators/pipeline/transform-stage.js.map +1 -0
- package/scripts/generators/propositions-content.d.ts +29 -0
- package/scripts/generators/propositions-content.d.ts.map +1 -0
- package/scripts/generators/propositions-content.js +90 -0
- package/scripts/generators/propositions-content.js.map +1 -0
- package/scripts/generators/sankey-content.d.ts +45 -0
- package/scripts/generators/sankey-content.d.ts.map +1 -0
- package/scripts/generators/sankey-content.js +227 -0
- package/scripts/generators/sankey-content.js.map +1 -0
- package/scripts/generators/sitemap.d.ts +66 -0
- package/scripts/generators/sitemap.d.ts.map +1 -0
- package/scripts/generators/sitemap.js +562 -0
- package/scripts/generators/sitemap.js.map +1 -0
- package/scripts/generators/strategies/article-strategy.d.ts +146 -0
- package/scripts/generators/strategies/article-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/article-strategy.js +4 -0
- package/scripts/generators/strategies/article-strategy.js.map +1 -0
- package/scripts/generators/strategies/breaking-news-strategy.d.ts +64 -0
- package/scripts/generators/strategies/breaking-news-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/breaking-news-strategy.js +246 -0
- package/scripts/generators/strategies/breaking-news-strategy.js.map +1 -0
- package/scripts/generators/strategies/committee-reports-strategy.d.ts +93 -0
- package/scripts/generators/strategies/committee-reports-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/committee-reports-strategy.js +447 -0
- package/scripts/generators/strategies/committee-reports-strategy.js.map +1 -0
- package/scripts/generators/strategies/month-ahead-strategy.d.ts +60 -0
- package/scripts/generators/strategies/month-ahead-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/month-ahead-strategy.js +175 -0
- package/scripts/generators/strategies/month-ahead-strategy.js.map +1 -0
- package/scripts/generators/strategies/monthly-review-strategy.d.ts +66 -0
- package/scripts/generators/strategies/monthly-review-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/monthly-review-strategy.js +204 -0
- package/scripts/generators/strategies/monthly-review-strategy.js.map +1 -0
- package/scripts/generators/strategies/motions-strategy.d.ts +61 -0
- package/scripts/generators/strategies/motions-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/motions-strategy.js +215 -0
- package/scripts/generators/strategies/motions-strategy.js.map +1 -0
- package/scripts/generators/strategies/propositions-strategy.d.ts +60 -0
- package/scripts/generators/strategies/propositions-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/propositions-strategy.js +257 -0
- package/scripts/generators/strategies/propositions-strategy.js.map +1 -0
- package/scripts/generators/strategies/week-ahead-strategy.d.ts +57 -0
- package/scripts/generators/strategies/week-ahead-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/week-ahead-strategy.js +178 -0
- package/scripts/generators/strategies/week-ahead-strategy.js.map +1 -0
- package/scripts/generators/strategies/weekly-review-strategy.d.ts +63 -0
- package/scripts/generators/strategies/weekly-review-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/weekly-review-strategy.js +211 -0
- package/scripts/generators/strategies/weekly-review-strategy.js.map +1 -0
- package/scripts/generators/swot-content.d.ts +42 -0
- package/scripts/generators/swot-content.d.ts.map +1 -0
- package/scripts/generators/swot-content.js +366 -0
- package/scripts/generators/swot-content.js.map +1 -0
- package/scripts/generators/week-ahead-content.d.ts +103 -0
- package/scripts/generators/week-ahead-content.d.ts.map +1 -0
- package/scripts/generators/week-ahead-content.js +610 -0
- package/scripts/generators/week-ahead-content.js.map +1 -0
- package/scripts/index.d.ts +40 -0
- package/scripts/index.d.ts.map +1 -0
- package/scripts/index.js +53 -0
- package/scripts/index.js.map +1 -0
- package/scripts/mcp/ep-mcp-client.d.ts +471 -0
- package/scripts/mcp/ep-mcp-client.d.ts.map +1 -0
- package/scripts/mcp/ep-mcp-client.js +734 -0
- package/scripts/mcp/ep-mcp-client.js.map +1 -0
- package/scripts/mcp/mcp-connection.d.ts +264 -0
- package/scripts/mcp/mcp-connection.d.ts.map +1 -0
- package/scripts/mcp/mcp-connection.js +790 -0
- package/scripts/mcp/mcp-connection.js.map +1 -0
- package/scripts/mcp/mcp-health.d.ts +75 -0
- package/scripts/mcp/mcp-health.d.ts.map +1 -0
- package/scripts/mcp/mcp-health.js +78 -0
- package/scripts/mcp/mcp-health.js.map +1 -0
- package/scripts/mcp/mcp-retry.d.ts +94 -0
- package/scripts/mcp/mcp-retry.d.ts.map +1 -0
- package/scripts/mcp/mcp-retry.js +127 -0
- package/scripts/mcp/mcp-retry.js.map +1 -0
- package/scripts/mcp/wb-mcp-client.d.ts +38 -0
- package/scripts/mcp/wb-mcp-client.d.ts.map +1 -0
- package/scripts/mcp/wb-mcp-client.js +112 -0
- package/scripts/mcp/wb-mcp-client.js.map +1 -0
- package/scripts/templates/article-template.d.ts +9 -0
- package/scripts/templates/article-template.d.ts.map +1 -0
- package/scripts/templates/article-template.js +378 -0
- package/scripts/templates/article-template.js.map +1 -0
- package/scripts/templates/section-builders.d.ts +28 -0
- package/scripts/templates/section-builders.d.ts.map +1 -0
- package/scripts/templates/section-builders.js +142 -0
- package/scripts/templates/section-builders.js.map +1 -0
- package/scripts/types/analysis.d.ts +115 -0
- package/scripts/types/analysis.d.ts.map +1 -0
- package/scripts/types/analysis.js +4 -0
- package/scripts/types/analysis.js.map +1 -0
- package/scripts/types/common.d.ts +584 -0
- package/scripts/types/common.d.ts.map +1 -0
- package/scripts/types/common.js +96 -0
- package/scripts/types/common.js.map +1 -0
- package/scripts/types/generation.d.ts +104 -0
- package/scripts/types/generation.d.ts.map +1 -0
- package/scripts/types/generation.js +4 -0
- package/scripts/types/generation.js.map +1 -0
- package/scripts/types/index.d.ts +24 -0
- package/scripts/types/index.d.ts.map +1 -0
- package/scripts/types/index.js +16 -0
- package/scripts/types/index.js.map +1 -0
- package/scripts/types/intelligence.d.ts +129 -0
- package/scripts/types/intelligence.d.ts.map +1 -0
- package/scripts/types/intelligence.js +4 -0
- package/scripts/types/intelligence.js.map +1 -0
- package/scripts/types/mcp.d.ts +418 -0
- package/scripts/types/mcp.d.ts.map +1 -0
- package/scripts/types/mcp.js +4 -0
- package/scripts/types/mcp.js.map +1 -0
- package/scripts/types/parliament.d.ts +388 -0
- package/scripts/types/parliament.d.ts.map +1 -0
- package/scripts/types/parliament.js +4 -0
- package/scripts/types/parliament.js.map +1 -0
- package/scripts/types/quality.d.ts +114 -0
- package/scripts/types/quality.d.ts.map +1 -0
- package/scripts/types/quality.js +4 -0
- package/scripts/types/quality.js.map +1 -0
- package/scripts/types/stakeholder.d.ts +88 -0
- package/scripts/types/stakeholder.d.ts.map +1 -0
- package/scripts/types/stakeholder.js +16 -0
- package/scripts/types/stakeholder.js.map +1 -0
- package/scripts/types/visualization.d.ts +708 -0
- package/scripts/types/visualization.d.ts.map +1 -0
- package/scripts/types/visualization.js +4 -0
- package/scripts/types/visualization.js.map +1 -0
- package/scripts/types/world-bank.d.ts +85 -0
- package/scripts/types/world-bank.d.ts.map +1 -0
- package/scripts/types/world-bank.js +4 -0
- package/scripts/types/world-bank.js.map +1 -0
- package/scripts/utils/article-category.d.ts +18 -0
- package/scripts/utils/article-category.d.ts.map +1 -0
- package/scripts/utils/article-category.js +49 -0
- package/scripts/utils/article-category.js.map +1 -0
- package/scripts/utils/article-quality-scorer.d.ts +87 -0
- package/scripts/utils/article-quality-scorer.d.ts.map +1 -0
- package/scripts/utils/article-quality-scorer.js +1048 -0
- package/scripts/utils/article-quality-scorer.js.map +1 -0
- package/scripts/utils/content-metadata.d.ts +34 -0
- package/scripts/utils/content-metadata.d.ts.map +1 -0
- package/scripts/utils/content-metadata.js +249 -0
- package/scripts/utils/content-metadata.js.map +1 -0
- package/scripts/utils/content-validator.d.ts +94 -0
- package/scripts/utils/content-validator.d.ts.map +1 -0
- package/scripts/utils/content-validator.js +489 -0
- package/scripts/utils/content-validator.js.map +1 -0
- package/scripts/utils/copy-test-reports.d.ts +9 -0
- package/scripts/utils/copy-test-reports.d.ts.map +1 -0
- package/scripts/utils/copy-test-reports.js +508 -0
- package/scripts/utils/copy-test-reports.js.map +1 -0
- package/scripts/utils/file-utils.d.ts +144 -0
- package/scripts/utils/file-utils.d.ts.map +1 -0
- package/scripts/utils/file-utils.js +374 -0
- package/scripts/utils/file-utils.js.map +1 -0
- package/scripts/utils/fix-articles.d.ts +27 -0
- package/scripts/utils/fix-articles.d.ts.map +1 -0
- package/scripts/utils/fix-articles.js +510 -0
- package/scripts/utils/fix-articles.js.map +1 -0
- package/scripts/utils/generate-docs-index.d.ts +8 -0
- package/scripts/utils/generate-docs-index.d.ts.map +1 -0
- package/scripts/utils/generate-docs-index.js +275 -0
- package/scripts/utils/generate-docs-index.js.map +1 -0
- package/scripts/utils/html-sanitize.d.ts +18 -0
- package/scripts/utils/html-sanitize.d.ts.map +1 -0
- package/scripts/utils/html-sanitize.js +57 -0
- package/scripts/utils/html-sanitize.js.map +1 -0
- package/scripts/utils/intelligence-analysis.d.ts +173 -0
- package/scripts/utils/intelligence-analysis.d.ts.map +1 -0
- package/scripts/utils/intelligence-analysis.js +936 -0
- package/scripts/utils/intelligence-analysis.js.map +1 -0
- package/scripts/utils/intelligence-index.d.ts +126 -0
- package/scripts/utils/intelligence-index.d.ts.map +1 -0
- package/scripts/utils/intelligence-index.js +731 -0
- package/scripts/utils/intelligence-index.js.map +1 -0
- package/scripts/utils/metadata-utils.d.ts +14 -0
- package/scripts/utils/metadata-utils.d.ts.map +1 -0
- package/scripts/utils/metadata-utils.js +18 -0
- package/scripts/utils/metadata-utils.js.map +1 -0
- package/scripts/utils/news-metadata.d.ts +47 -0
- package/scripts/utils/news-metadata.d.ts.map +1 -0
- package/scripts/utils/news-metadata.js +259 -0
- package/scripts/utils/news-metadata.js.map +1 -0
- package/scripts/utils/validate-articles.d.ts +2 -0
- package/scripts/utils/validate-articles.d.ts.map +1 -0
- package/scripts/utils/validate-articles.js +284 -0
- package/scripts/utils/validate-articles.js.map +1 -0
- package/scripts/utils/validate-ep-api.d.ts +51 -0
- package/scripts/utils/validate-ep-api.d.ts.map +1 -0
- package/scripts/utils/validate-ep-api.js +160 -0
- package/scripts/utils/validate-ep-api.js.map +1 -0
- package/scripts/utils/world-bank-data.d.ts +84 -0
- package/scripts/utils/world-bank-data.d.ts.map +1 -0
- package/scripts/utils/world-bank-data.js +311 -0
- package/scripts/utils/world-bank-data.js.map +1 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
4
|
+
import { MONTH_AHEAD_TITLES, getLocalizedString } from '../../constants/languages.js';
|
|
5
|
+
import { fetchWeekAheadData, fetchEPFeedData } from '../pipeline/fetch-stage.js';
|
|
6
|
+
import { buildWeekAheadContent, buildKeywords } from '../week-ahead-content.js';
|
|
7
|
+
import { buildDeepAnalysisSection } from '../deep-analysis-content.js';
|
|
8
|
+
import { buildProspectiveAnalysis, buildProspectiveSwot, buildProspectiveDashboard, buildProspectiveMindmap, } from '../analysis-builders.js';
|
|
9
|
+
import { buildSwotSection } from '../swot-content.js';
|
|
10
|
+
import { buildDashboardSection } from '../dashboard-content.js';
|
|
11
|
+
import { buildIntelligenceMindmapSection } from '../mindmap-content.js';
|
|
12
|
+
import { pl } from '../../utils/metadata-utils.js';
|
|
13
|
+
/** Keywords shared by all Month Ahead articles */
|
|
14
|
+
const MONTH_AHEAD_KEYWORDS = [
|
|
15
|
+
'European Parliament',
|
|
16
|
+
'month ahead',
|
|
17
|
+
'strategic outlook',
|
|
18
|
+
'legislative calendar',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Build a content-aware title suffix from month-ahead data counts.
|
|
22
|
+
*
|
|
23
|
+
* @param monthData - Aggregated month-ahead domain data
|
|
24
|
+
* @returns Short suffix for the title, or empty string
|
|
25
|
+
*/
|
|
26
|
+
function buildMonthAheadTitleSuffix(monthData) {
|
|
27
|
+
const parts = [];
|
|
28
|
+
if (monthData.events.length > 0)
|
|
29
|
+
parts.push(pl(monthData.events.length, 'Event', 'Events'));
|
|
30
|
+
if (monthData.committees.length > 0)
|
|
31
|
+
parts.push(pl(monthData.committees.length, 'Committee Meeting', 'Committee Meetings'));
|
|
32
|
+
if (monthData.pipeline.length > 0)
|
|
33
|
+
parts.push(pl(monthData.pipeline.length, 'Pipeline Item', 'Pipeline Items'));
|
|
34
|
+
return parts.join(', ');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a content-aware description from month-ahead data.
|
|
38
|
+
*
|
|
39
|
+
* @param monthData - Aggregated month-ahead domain data
|
|
40
|
+
* @param monthLabel - Display label for the target month
|
|
41
|
+
* @returns SEO-friendly description (≤ 200 chars)
|
|
42
|
+
*/
|
|
43
|
+
function buildMonthAheadDescription(monthData, monthLabel) {
|
|
44
|
+
const parts = [];
|
|
45
|
+
if (monthData.events.length > 0)
|
|
46
|
+
parts.push(pl(monthData.events.length, 'scheduled event', 'scheduled events'));
|
|
47
|
+
if (monthData.committees.length > 0)
|
|
48
|
+
parts.push(pl(monthData.committees.length, 'committee meeting', 'committee meetings'));
|
|
49
|
+
if (monthData.pipeline.length > 0)
|
|
50
|
+
parts.push(pl(monthData.pipeline.length, 'pipeline procedure', 'pipeline procedures'));
|
|
51
|
+
if (monthData.questions.length > 0)
|
|
52
|
+
parts.push(pl(monthData.questions.length, 'parliamentary question', 'parliamentary questions'));
|
|
53
|
+
if (parts.length === 0) {
|
|
54
|
+
return `European Parliament strategic outlook for ${monthLabel} — legislative milestones and policy agenda.`;
|
|
55
|
+
}
|
|
56
|
+
const desc = `EP month ahead (${monthLabel}): ${parts.join(', ')}.`;
|
|
57
|
+
return desc.length > 200 ? desc.slice(0, 197) + '...' : desc;
|
|
58
|
+
}
|
|
59
|
+
// ─── Date-range helper ────────────────────────────────────────────────────────
|
|
60
|
+
/**
|
|
61
|
+
* Compute the month-ahead date range spanning 30 days from the day after `baseDate`.
|
|
62
|
+
*
|
|
63
|
+
* @param baseDate - ISO 8601 publication date (YYYY-MM-DD)
|
|
64
|
+
* @returns Date range spanning the next 30 days
|
|
65
|
+
*/
|
|
66
|
+
function computeMonthAheadDateRange(baseDate) {
|
|
67
|
+
const base = new Date(`${baseDate}T00:00:00Z`);
|
|
68
|
+
const startDate = new Date(base);
|
|
69
|
+
startDate.setUTCDate(base.getUTCDate() + 1);
|
|
70
|
+
const endDate = new Date(startDate);
|
|
71
|
+
endDate.setUTCDate(startDate.getUTCDate() + 30);
|
|
72
|
+
const startParts = startDate.toISOString().split('T');
|
|
73
|
+
const endParts = endDate.toISOString().split('T');
|
|
74
|
+
if (!startParts[0] || !endParts[0]) {
|
|
75
|
+
throw new Error('Invalid date format generated in computeMonthAheadDateRange');
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
start: startParts[0],
|
|
79
|
+
end: endParts[0],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Format a month label from a date string (e.g. "February 2026").
|
|
84
|
+
*
|
|
85
|
+
* @param dateStr - ISO 8601 date
|
|
86
|
+
* @returns Human-readable month label, using the runtime's default locale
|
|
87
|
+
*/
|
|
88
|
+
function formatMonthLabel(dateStr) {
|
|
89
|
+
const date = new Date(`${dateStr}T00:00:00Z`);
|
|
90
|
+
return date.toLocaleDateString(undefined, { month: 'long', year: 'numeric', timeZone: 'UTC' });
|
|
91
|
+
}
|
|
92
|
+
// ─── Strategy implementation ──────────────────────────────────────────────────
|
|
93
|
+
/**
|
|
94
|
+
* Article strategy for {@link ArticleCategory.MONTH_AHEAD}.
|
|
95
|
+
* Fetches plenary, committee, document, and pipeline data then builds
|
|
96
|
+
* a forward-looking 30-day strategic outlook of parliamentary activity.
|
|
97
|
+
*/
|
|
98
|
+
export class MonthAheadStrategy {
|
|
99
|
+
type = ArticleCategory.MONTH_AHEAD;
|
|
100
|
+
requiredMCPTools = [
|
|
101
|
+
'get_plenary_sessions',
|
|
102
|
+
'get_committee_info',
|
|
103
|
+
'search_documents',
|
|
104
|
+
'monitor_legislative_pipeline',
|
|
105
|
+
'get_parliamentary_questions',
|
|
106
|
+
'get_events',
|
|
107
|
+
'get_events_feed',
|
|
108
|
+
'get_adopted_texts_feed',
|
|
109
|
+
'get_procedures_feed',
|
|
110
|
+
];
|
|
111
|
+
/**
|
|
112
|
+
* Fetch month-ahead data from MCP.
|
|
113
|
+
*
|
|
114
|
+
* @param client - MCP client or null
|
|
115
|
+
* @param date - ISO 8601 publication date
|
|
116
|
+
* @returns Populated month-ahead data payload
|
|
117
|
+
*/
|
|
118
|
+
async fetchData(client, date) {
|
|
119
|
+
const dateRange = computeMonthAheadDateRange(date);
|
|
120
|
+
console.log(` 📆 Month-ahead range: ${dateRange.start} to ${dateRange.end}`);
|
|
121
|
+
// Fetch traditional MCP data and EP feeds in parallel
|
|
122
|
+
const [monthData, feedData] = await Promise.all([
|
|
123
|
+
fetchWeekAheadData(client, dateRange),
|
|
124
|
+
fetchEPFeedData(client, 'one-month', dateRange),
|
|
125
|
+
]);
|
|
126
|
+
const keywords = [...MONTH_AHEAD_KEYWORDS, ...buildKeywords(monthData)];
|
|
127
|
+
const monthLabel = formatMonthLabel(dateRange.start);
|
|
128
|
+
return { date, dateRange, monthData, keywords, monthLabel, feedData };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build the month-ahead HTML body for the specified language.
|
|
132
|
+
*
|
|
133
|
+
* @param data - Month-ahead data payload
|
|
134
|
+
* @param lang - Target language code used for editorial strings
|
|
135
|
+
* @returns Article HTML body
|
|
136
|
+
*/
|
|
137
|
+
buildContent(data, lang) {
|
|
138
|
+
const base = buildWeekAheadContent(data.monthData, data.dateRange, lang);
|
|
139
|
+
const analysis = buildProspectiveAnalysis(data.monthData, data.dateRange, 'month');
|
|
140
|
+
const analysisSection = buildDeepAnalysisSection(analysis, lang, 'en');
|
|
141
|
+
const mindmapData = buildProspectiveMindmap(data.monthData, lang);
|
|
142
|
+
const mindmapSection = buildIntelligenceMindmapSection(mindmapData, lang);
|
|
143
|
+
const swotData = buildProspectiveSwot(data.monthData, 'month', lang);
|
|
144
|
+
const swotSection = buildSwotSection(swotData, lang);
|
|
145
|
+
const dashboardData = buildProspectiveDashboard(data.monthData, 'month', lang);
|
|
146
|
+
const dashboardSection = buildDashboardSection(dashboardData, lang);
|
|
147
|
+
return base.replace('<!-- /article-content -->', analysisSection + mindmapSection + swotSection + dashboardSection);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Return language-specific metadata for the month-ahead article.
|
|
151
|
+
*
|
|
152
|
+
* @param data - Month-ahead data payload
|
|
153
|
+
* @param lang - Target language code
|
|
154
|
+
* @returns Localised metadata
|
|
155
|
+
*/
|
|
156
|
+
getMetadata(data, lang) {
|
|
157
|
+
const titleFn = getLocalizedString(MONTH_AHEAD_TITLES, lang);
|
|
158
|
+
const { title: baseTitle, subtitle: baseSubtitle } = titleFn(data.monthLabel);
|
|
159
|
+
const suffix = lang === 'en' ? buildMonthAheadTitleSuffix(data.monthData) : '';
|
|
160
|
+
const title = suffix ? `${baseTitle} — ${suffix}` : baseTitle;
|
|
161
|
+
const subtitle = lang === 'en'
|
|
162
|
+
? buildMonthAheadDescription(data.monthData, data.monthLabel) || baseSubtitle
|
|
163
|
+
: baseSubtitle;
|
|
164
|
+
return {
|
|
165
|
+
title,
|
|
166
|
+
subtitle,
|
|
167
|
+
keywords: data.keywords,
|
|
168
|
+
category: ArticleCategory.MONTH_AHEAD,
|
|
169
|
+
sources: [],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** Singleton instance for use by the strategy registry */
|
|
174
|
+
export const monthAheadStrategy = new MonthAheadStrategy();
|
|
175
|
+
//# sourceMappingURL=month-ahead-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"month-ahead-strategy.js","sourceRoot":"","sources":["../../../src/generators/strategies/month-ahead-strategy.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,sCAAsC;AAWtC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAE,EAAE,EAAE,MAAM,+BAA+B,CAAC;AAkBnD,kDAAkD;AAClD,MAAM,oBAAoB,GAAG;IAC3B,qBAAqB;IACrB,aAAa;IACb,mBAAmB;IACnB,sBAAsB;CACd,CAAC;AAEX;;;;;GAKG;AACH,SAAS,0BAA0B,CAAC,SAAwB;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC5F,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,CAAC,CAAC,CAAC;IACzF,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,0BAA0B,CAAC,SAAwB,EAAE,UAAkB;IAC9E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACjF,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,CAAC,CAAC,CAAC;IACzF,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,CAAC,CAAC;IACzF,IAAI,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,wBAAwB,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAElG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,6CAA6C,UAAU,8CAA8C,CAAC;IAC/G,CAAC;IAED,MAAM,IAAI,GAAG,mBAAmB,UAAU,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACpE,OAAO,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC;AAED,iFAAiF;AAEjF;;;;;GAKG;AACH,SAAS,0BAA0B,CAAC,QAAgB;IAClD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,QAAQ,YAAY,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IAEhD,MAAM,UAAU,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAElD,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;QACpB,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;KACjB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,OAAO,YAAY,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AACjG,CAAC;AAED,iFAAiF;AAEjF;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IACpB,IAAI,GAAG,eAAe,CAAC,WAAW,CAAC;IAEnC,gBAAgB,GAAG;QAC1B,sBAAsB;QACtB,oBAAoB;QACpB,kBAAkB;QAClB,8BAA8B;QAC9B,6BAA6B;QAC7B,YAAY;QACZ,iBAAiB;QACjB,wBAAwB;QACxB,qBAAqB;KACb,CAAC;IAEX;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CACb,MAA0C,EAC1C,IAAY;QAEZ,MAAM,SAAS,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,2BAA2B,SAAS,CAAC,KAAK,OAAO,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;QAE9E,sDAAsD;QACtD,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC9C,kBAAkB,CAAC,MAAM,EAAE,SAAS,CAAC;YACrC,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC;SAChD,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,CAAC,GAAG,oBAAoB,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QACxE,MAAM,UAAU,GAAG,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAErD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;IACxE,CAAC;IAED;;;;;;OAMG;IACH,YAAY,CAAC,IAA2B,EAAE,IAAkB;QAC1D,MAAM,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,wBAAwB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACnF,MAAM,eAAe,GAAG,wBAAwB,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACvE,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAClE,MAAM,cAAc,GAAG,+BAA+B,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,yBAAyB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC/E,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,OAAO,CACjB,2BAA2B,EAC3B,eAAe,GAAG,cAAc,GAAG,WAAW,GAAG,gBAAgB,CAClE,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,WAAW,CAAC,IAA2B,EAAE,IAAkB;QACzD,MAAM,OAAO,GAAG,kBAAkB,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9E,MAAM,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,0BAA0B,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,MAAM,QAAQ,GACZ,IAAI,KAAK,IAAI;YACX,CAAC,CAAC,0BAA0B,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,YAAY;YAC7E,CAAC,CAAC,YAAY,CAAC;QACnB,OAAO;YACL,KAAK;YACL,QAAQ;YACR,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,eAAe,CAAC,WAAW;YACrC,OAAO,EAAE,EAAE;SACZ,CAAC;IACJ,CAAC;CACF;AAED,0DAA0D;AAC1D,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Strategies/MonthlyReviewStrategy
|
|
3
|
+
* @description Article strategy for the Month In Review article type.
|
|
4
|
+
* Fetches voting records, voting patterns, voting anomalies, and
|
|
5
|
+
* parliamentary questions from the past 30 days, then renders a
|
|
6
|
+
* comprehensive retrospective analysis article.
|
|
7
|
+
*/
|
|
8
|
+
import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
|
|
9
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
10
|
+
import type { LanguageCode, DateRange, VotingRecord, VotingPattern, VotingAnomaly, MotionsQuestion, EPFeedData } from '../../types/index.js';
|
|
11
|
+
import type { ArticleStrategy, ArticleData, ArticleMetadata } from './article-strategy.js';
|
|
12
|
+
/** Data fetched and pre-processed by {@link MonthlyReviewStrategy} */
|
|
13
|
+
export interface MonthlyReviewArticleData extends ArticleData {
|
|
14
|
+
/** Review period date range (30 days) */
|
|
15
|
+
readonly dateRange: DateRange;
|
|
16
|
+
/** Voting records from the review period */
|
|
17
|
+
readonly votingRecords: readonly VotingRecord[];
|
|
18
|
+
/** Voting patterns analysis */
|
|
19
|
+
readonly votingPatterns: readonly VotingPattern[];
|
|
20
|
+
/** Detected voting anomalies */
|
|
21
|
+
readonly anomalies: readonly VotingAnomaly[];
|
|
22
|
+
/** Parliamentary questions from the period */
|
|
23
|
+
readonly questions: readonly MotionsQuestion[];
|
|
24
|
+
/** Start date string for display */
|
|
25
|
+
readonly dateFromStr: string;
|
|
26
|
+
/** Display label for the review month */
|
|
27
|
+
readonly monthLabel: string;
|
|
28
|
+
/** EP feed data for enrichment (when available) */
|
|
29
|
+
readonly feedData?: EPFeedData | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Article strategy for {@link ArticleCategory.MONTH_IN_REVIEW}.
|
|
33
|
+
* Fetches voting records, anomalies, patterns, and questions for the
|
|
34
|
+
* past 30 days and builds a comprehensive retrospective analysis.
|
|
35
|
+
*/
|
|
36
|
+
export declare class MonthlyReviewStrategy implements ArticleStrategy<MonthlyReviewArticleData> {
|
|
37
|
+
readonly type = ArticleCategory.MONTH_IN_REVIEW;
|
|
38
|
+
readonly requiredMCPTools: readonly ["get_voting_records", "analyze_voting_patterns", "detect_voting_anomalies", "get_parliamentary_questions", "get_adopted_texts_feed", "get_procedures_feed", "get_events_feed"];
|
|
39
|
+
/**
|
|
40
|
+
* Fetch monthly review data from MCP.
|
|
41
|
+
*
|
|
42
|
+
* @param client - MCP client or null
|
|
43
|
+
* @param date - ISO 8601 publication date
|
|
44
|
+
* @returns Populated monthly review data payload
|
|
45
|
+
*/
|
|
46
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<MonthlyReviewArticleData>;
|
|
47
|
+
/**
|
|
48
|
+
* Build the monthly review HTML body for the specified language.
|
|
49
|
+
*
|
|
50
|
+
* @param data - Monthly review data payload
|
|
51
|
+
* @param lang - Target language code used for editorial strings
|
|
52
|
+
* @returns Article HTML body
|
|
53
|
+
*/
|
|
54
|
+
buildContent(data: MonthlyReviewArticleData, lang: LanguageCode): string;
|
|
55
|
+
/**
|
|
56
|
+
* Return language-specific metadata for the monthly review article.
|
|
57
|
+
*
|
|
58
|
+
* @param data - Monthly review data payload
|
|
59
|
+
* @param lang - Target language code
|
|
60
|
+
* @returns Localised metadata
|
|
61
|
+
*/
|
|
62
|
+
getMetadata(data: MonthlyReviewArticleData, lang: LanguageCode): ArticleMetadata;
|
|
63
|
+
}
|
|
64
|
+
/** Singleton instance for use by the strategy registry */
|
|
65
|
+
export declare const monthlyReviewStrategy: MonthlyReviewStrategy;
|
|
66
|
+
//# sourceMappingURL=monthly-review-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monthly-review-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/monthly-review-strategy.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,UAAU,EACX,MAAM,sBAAsB,CAAC;AAoB9B,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAK3F,sEAAsE;AACtE,MAAM,WAAW,wBAAyB,SAAQ,WAAW;IAC3D,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,4CAA4C;IAC5C,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IAChD,+BAA+B;IAC/B,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;IAClD,gCAAgC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,oCAAoC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAiHD;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,eAAe,CAAC,wBAAwB,CAAC;IACrF,QAAQ,CAAC,IAAI,mCAAmC;IAEhD,QAAQ,CAAC,gBAAgB,2LAQd;IAEX;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,wBAAwB,CAAC;IA4BpC;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IAyCxE;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe;CAejF;AAED,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
4
|
+
import { MONTHLY_REVIEW_TITLES, getLocalizedString } from '../../constants/languages.js';
|
|
5
|
+
import { fetchVotingRecords, fetchVotingPatterns, fetchMotionsAnomalies, fetchParliamentaryQuestionsForMotions, fetchEPFeedData, } from '../pipeline/fetch-stage.js';
|
|
6
|
+
import { generateMotionsContent } from '../motions-content.js';
|
|
7
|
+
import { buildDeepAnalysisSection } from '../deep-analysis-content.js';
|
|
8
|
+
import { buildVotingAnalysis, buildVotingSwot, buildVotingDashboard, buildVotingMindmap, } from '../analysis-builders.js';
|
|
9
|
+
import { buildSwotSection } from '../swot-content.js';
|
|
10
|
+
import { buildDashboardSection } from '../dashboard-content.js';
|
|
11
|
+
import { buildIntelligenceMindmapSection } from '../mindmap-content.js';
|
|
12
|
+
import { pl } from '../../utils/metadata-utils.js';
|
|
13
|
+
/** Base keywords shared by all Monthly Review articles */
|
|
14
|
+
const MONTHLY_REVIEW_BASE_KEYWORDS = [
|
|
15
|
+
'European Parliament',
|
|
16
|
+
'monthly review',
|
|
17
|
+
'legislative output',
|
|
18
|
+
'coalition dynamics',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Extract content-aware keywords from monthly review data.
|
|
22
|
+
*
|
|
23
|
+
* @param data - Monthly review article data payload
|
|
24
|
+
* @returns Deduplicated keyword array
|
|
25
|
+
*/
|
|
26
|
+
function buildMonthlyReviewKeywords(data) {
|
|
27
|
+
const keywords = [...MONTHLY_REVIEW_BASE_KEYWORDS];
|
|
28
|
+
for (const r of data.votingRecords.slice(0, 5)) {
|
|
29
|
+
if (r.title)
|
|
30
|
+
keywords.push(r.title.slice(0, 60));
|
|
31
|
+
}
|
|
32
|
+
for (const a of data.anomalies.slice(0, 3)) {
|
|
33
|
+
if (a.type)
|
|
34
|
+
keywords.push(a.type);
|
|
35
|
+
}
|
|
36
|
+
for (const q of data.questions.slice(0, 3)) {
|
|
37
|
+
if (q.topic)
|
|
38
|
+
keywords.push(q.topic);
|
|
39
|
+
}
|
|
40
|
+
return [...new Set(keywords)];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build a content-aware description from monthly review data.
|
|
44
|
+
*
|
|
45
|
+
* @param data - Monthly review article data payload
|
|
46
|
+
* @returns SEO-friendly description (≤ 200 chars)
|
|
47
|
+
*/
|
|
48
|
+
function buildMonthlyReviewDescription(data) {
|
|
49
|
+
const parts = [];
|
|
50
|
+
if (data.votingRecords.length > 0)
|
|
51
|
+
parts.push(`${pl(data.votingRecords.length, 'vote', 'votes')} analysed`);
|
|
52
|
+
if (data.anomalies.length > 0)
|
|
53
|
+
parts.push(pl(data.anomalies.length, 'voting anomaly', 'voting anomalies'));
|
|
54
|
+
if (data.questions.length > 0)
|
|
55
|
+
parts.push(`${pl(data.questions.length, 'question', 'questions')} tabled`);
|
|
56
|
+
if (parts.length === 0) {
|
|
57
|
+
return `European Parliament monthly review for ${data.monthLabel} — legislative output and coalition dynamics.`;
|
|
58
|
+
}
|
|
59
|
+
const highlight = data.votingRecords[0]?.title ?? '';
|
|
60
|
+
const base = `EP month in review (${data.monthLabel}): ${parts.join(', ')}`;
|
|
61
|
+
if (highlight) {
|
|
62
|
+
const full = `${base}. Key: ${highlight}`;
|
|
63
|
+
return full.length > 200 ? full.slice(0, 197) + '...' : full;
|
|
64
|
+
}
|
|
65
|
+
return base.length > 200 ? base.slice(0, 197) + '...' : base;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build a content-aware title suffix from monthly review data counts.
|
|
69
|
+
*
|
|
70
|
+
* @param data - Monthly review article data payload
|
|
71
|
+
* @returns Short suffix for the title, or empty string
|
|
72
|
+
*/
|
|
73
|
+
function buildMonthlyReviewTitleSuffix(data) {
|
|
74
|
+
const parts = [];
|
|
75
|
+
if (data.votingRecords.length > 0)
|
|
76
|
+
parts.push(pl(data.votingRecords.length, 'Vote', 'Votes'));
|
|
77
|
+
if (data.anomalies.length > 0)
|
|
78
|
+
parts.push(pl(data.anomalies.length, 'Anomaly', 'Anomalies'));
|
|
79
|
+
return parts.join(', ');
|
|
80
|
+
}
|
|
81
|
+
// ─── Date-range helper ────────────────────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Compute the review period covering the 30 days ending on `baseDate`.
|
|
84
|
+
*
|
|
85
|
+
* @param baseDate - ISO 8601 publication date (YYYY-MM-DD)
|
|
86
|
+
* @returns Date range covering the past 30 days
|
|
87
|
+
*/
|
|
88
|
+
function computeMonthlyReviewDateRange(baseDate) {
|
|
89
|
+
const end = new Date(`${baseDate}T00:00:00Z`);
|
|
90
|
+
const start = new Date(end);
|
|
91
|
+
start.setUTCDate(end.getUTCDate() - 30);
|
|
92
|
+
const startParts = start.toISOString().split('T');
|
|
93
|
+
const endParts = end.toISOString().split('T');
|
|
94
|
+
if (!startParts[0] || !endParts[0]) {
|
|
95
|
+
throw new Error('Invalid date format generated in computeMonthlyReviewDateRange');
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
start: startParts[0],
|
|
99
|
+
end: endParts[0],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Format a month label from a date string (e.g. "February 2026").
|
|
104
|
+
*
|
|
105
|
+
* @param dateStr - ISO 8601 date
|
|
106
|
+
* @returns Human-readable month label, using the runtime's default locale
|
|
107
|
+
*/
|
|
108
|
+
function formatMonthLabel(dateStr) {
|
|
109
|
+
const date = new Date(`${dateStr}T00:00:00Z`);
|
|
110
|
+
return date.toLocaleDateString(undefined, { month: 'long', year: 'numeric', timeZone: 'UTC' });
|
|
111
|
+
}
|
|
112
|
+
// ─── Strategy implementation ──────────────────────────────────────────────────
|
|
113
|
+
/**
|
|
114
|
+
* Article strategy for {@link ArticleCategory.MONTH_IN_REVIEW}.
|
|
115
|
+
* Fetches voting records, anomalies, patterns, and questions for the
|
|
116
|
+
* past 30 days and builds a comprehensive retrospective analysis.
|
|
117
|
+
*/
|
|
118
|
+
export class MonthlyReviewStrategy {
|
|
119
|
+
type = ArticleCategory.MONTH_IN_REVIEW;
|
|
120
|
+
requiredMCPTools = [
|
|
121
|
+
'get_voting_records',
|
|
122
|
+
'analyze_voting_patterns',
|
|
123
|
+
'detect_voting_anomalies',
|
|
124
|
+
'get_parliamentary_questions',
|
|
125
|
+
'get_adopted_texts_feed',
|
|
126
|
+
'get_procedures_feed',
|
|
127
|
+
'get_events_feed',
|
|
128
|
+
];
|
|
129
|
+
/**
|
|
130
|
+
* Fetch monthly review data from MCP.
|
|
131
|
+
*
|
|
132
|
+
* @param client - MCP client or null
|
|
133
|
+
* @param date - ISO 8601 publication date
|
|
134
|
+
* @returns Populated monthly review data payload
|
|
135
|
+
*/
|
|
136
|
+
async fetchData(client, date) {
|
|
137
|
+
const dateRange = computeMonthlyReviewDateRange(date);
|
|
138
|
+
console.log(` 📊 Monthly review range: ${dateRange.start} to ${dateRange.end}`);
|
|
139
|
+
// Fetch voting data and EP feed data in parallel
|
|
140
|
+
const [votingRecords, votingPatterns, anomalies, questions, feedData] = await Promise.all([
|
|
141
|
+
fetchVotingRecords(client, dateRange.start, dateRange.end),
|
|
142
|
+
fetchVotingPatterns(client, dateRange.start, dateRange.end),
|
|
143
|
+
fetchMotionsAnomalies(client, dateRange.start, dateRange.end),
|
|
144
|
+
fetchParliamentaryQuestionsForMotions(client, dateRange.start, dateRange.end),
|
|
145
|
+
fetchEPFeedData(client, 'one-month', dateRange),
|
|
146
|
+
]);
|
|
147
|
+
const monthLabel = formatMonthLabel(dateRange.start);
|
|
148
|
+
return {
|
|
149
|
+
date,
|
|
150
|
+
dateRange,
|
|
151
|
+
dateFromStr: dateRange.start,
|
|
152
|
+
votingRecords,
|
|
153
|
+
votingPatterns,
|
|
154
|
+
anomalies,
|
|
155
|
+
questions,
|
|
156
|
+
monthLabel,
|
|
157
|
+
feedData,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Build the monthly review HTML body for the specified language.
|
|
162
|
+
*
|
|
163
|
+
* @param data - Monthly review data payload
|
|
164
|
+
* @param lang - Target language code used for editorial strings
|
|
165
|
+
* @returns Article HTML body
|
|
166
|
+
*/
|
|
167
|
+
buildContent(data, lang) {
|
|
168
|
+
const base = generateMotionsContent(data.dateRange.start, data.dateRange.end, [...data.votingRecords], [...data.votingPatterns], [...data.anomalies], [...data.questions], lang);
|
|
169
|
+
const analysis = buildVotingAnalysis(data.dateRange.start, data.dateRange.end, data.votingRecords, data.votingPatterns, data.anomalies, data.questions);
|
|
170
|
+
const deepSection = buildDeepAnalysisSection(analysis, lang, 'en');
|
|
171
|
+
const mindmapData = buildVotingMindmap(data.votingRecords, data.votingPatterns, data.anomalies, lang);
|
|
172
|
+
const mindmapSection = buildIntelligenceMindmapSection(mindmapData, lang);
|
|
173
|
+
const swotData = buildVotingSwot(data.votingRecords, data.votingPatterns, data.anomalies, lang);
|
|
174
|
+
const swotSection = buildSwotSection(swotData, lang);
|
|
175
|
+
const dashboardData = buildVotingDashboard(data.votingRecords, data.votingPatterns, data.anomalies, lang);
|
|
176
|
+
const dashboardSection = buildDashboardSection(dashboardData, lang);
|
|
177
|
+
return base.replace('<!-- /article-content -->', deepSection + mindmapSection + swotSection + dashboardSection);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Return language-specific metadata for the monthly review article.
|
|
181
|
+
*
|
|
182
|
+
* @param data - Monthly review data payload
|
|
183
|
+
* @param lang - Target language code
|
|
184
|
+
* @returns Localised metadata
|
|
185
|
+
*/
|
|
186
|
+
getMetadata(data, lang) {
|
|
187
|
+
const titleFn = getLocalizedString(MONTHLY_REVIEW_TITLES, lang);
|
|
188
|
+
const { title: baseTitle, subtitle: baseSubtitle } = titleFn(data.monthLabel);
|
|
189
|
+
const suffix = lang === 'en' ? buildMonthlyReviewTitleSuffix(data) : '';
|
|
190
|
+
const title = suffix ? `${baseTitle} — ${suffix}` : baseTitle;
|
|
191
|
+
const description = lang === 'en' ? buildMonthlyReviewDescription(data) : '';
|
|
192
|
+
const subtitle = description || baseSubtitle;
|
|
193
|
+
return {
|
|
194
|
+
title,
|
|
195
|
+
subtitle,
|
|
196
|
+
keywords: buildMonthlyReviewKeywords(data),
|
|
197
|
+
category: ArticleCategory.MONTH_IN_REVIEW,
|
|
198
|
+
sources: [],
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Singleton instance for use by the strategy registry */
|
|
203
|
+
export const monthlyReviewStrategy = new MonthlyReviewStrategy();
|
|
204
|
+
//# sourceMappingURL=monthly-review-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monthly-review-strategy.js","sourceRoot":"","sources":["../../../src/generators/strategies/monthly-review-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Strategies/MotionsStrategy
|
|
3
|
+
* @description Article strategy for the Motions article type.
|
|
4
|
+
* Fetches voting records, patterns, anomalies and parliamentary questions
|
|
5
|
+
* over a rolling 30-day window then renders a voting-behaviour overview.
|
|
6
|
+
*/
|
|
7
|
+
import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
|
|
8
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
9
|
+
import type { LanguageCode, VotingRecord, VotingPattern, VotingAnomaly, MotionsQuestion, EPFeedData } from '../../types/index.js';
|
|
10
|
+
import type { ArticleStrategy, ArticleData, ArticleMetadata } from './article-strategy.js';
|
|
11
|
+
/** Data fetched and pre-processed by {@link MotionsStrategy} */
|
|
12
|
+
export interface MotionsArticleData extends ArticleData {
|
|
13
|
+
/** Start of the 30-day look-back window */
|
|
14
|
+
readonly dateFromStr: string;
|
|
15
|
+
/** Voting records for the period */
|
|
16
|
+
readonly votingRecords: readonly VotingRecord[];
|
|
17
|
+
/** Voting patterns for the period */
|
|
18
|
+
readonly votingPatterns: readonly VotingPattern[];
|
|
19
|
+
/** Voting anomalies detected in the period */
|
|
20
|
+
readonly anomalies: readonly VotingAnomaly[];
|
|
21
|
+
/** Parliamentary questions raised in the period */
|
|
22
|
+
readonly questions: readonly MotionsQuestion[];
|
|
23
|
+
/** EP feed data for enrichment (when available) */
|
|
24
|
+
readonly feedData?: EPFeedData | undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Article strategy for {@link ArticleCategory.MOTIONS}.
|
|
28
|
+
* Aggregates voting data over a rolling 30-day window and surfaces
|
|
29
|
+
* patterns, anomalies and parliamentary questions.
|
|
30
|
+
*/
|
|
31
|
+
export declare class MotionsStrategy implements ArticleStrategy<MotionsArticleData> {
|
|
32
|
+
readonly type = ArticleCategory.MOTIONS;
|
|
33
|
+
readonly requiredMCPTools: readonly ["get_voting_records", "analyze_voting_patterns", "detect_voting_anomalies", "get_parliamentary_questions", "get_adopted_texts_feed", "get_parliamentary_questions_feed"];
|
|
34
|
+
/**
|
|
35
|
+
* Fetch all motions data for the last 30 days.
|
|
36
|
+
*
|
|
37
|
+
* @param client - MCP client or null
|
|
38
|
+
* @param date - ISO 8601 publication date (end of the look-back window)
|
|
39
|
+
* @returns Populated motions data payload
|
|
40
|
+
*/
|
|
41
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<MotionsArticleData>;
|
|
42
|
+
/**
|
|
43
|
+
* Build the motions HTML body for the specified language.
|
|
44
|
+
*
|
|
45
|
+
* @param data - Motions data payload
|
|
46
|
+
* @param lang - Target language code used for editorial strings
|
|
47
|
+
* @returns Article HTML body
|
|
48
|
+
*/
|
|
49
|
+
buildContent(data: MotionsArticleData, lang: LanguageCode): string;
|
|
50
|
+
/**
|
|
51
|
+
* Return language-specific metadata for the motions article.
|
|
52
|
+
*
|
|
53
|
+
* @param data - Motions data payload
|
|
54
|
+
* @param lang - Target language code
|
|
55
|
+
* @returns Localised metadata
|
|
56
|
+
*/
|
|
57
|
+
getMetadata(data: MotionsArticleData, lang: LanguageCode): ArticleMetadata;
|
|
58
|
+
}
|
|
59
|
+
/** Singleton instance for use by the strategy registry */
|
|
60
|
+
export declare const motionsStrategy: MotionsStrategy;
|
|
61
|
+
//# sourceMappingURL=motions-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motions-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/motions-strategy.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,UAAU,EACX,MAAM,sBAAsB,CAAC;AAmB9B,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAoG3F,gEAAgE;AAChE,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oCAAoC;IACpC,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IAChD,qCAAqC;IACrC,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;IAClD,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAID;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,eAAe,CAAC,kBAAkB,CAAC;IACzE,QAAQ,CAAC,IAAI,2BAA2B;IAExC,QAAQ,CAAC,gBAAgB,qLAOd;IAEX;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,kBAAkB,CAAC;IA6B9B;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IAsDlE;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe;CAe3E;AAED,0DAA0D;AAC1D,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|