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.
- package/package.json +7 -7
- package/scripts/constants/language-articles.d.ts +4 -0
- package/scripts/constants/language-articles.js +20 -0
- package/scripts/constants/language-ui.d.ts +8 -8
- package/scripts/constants/language-ui.js +64 -64
- package/scripts/constants/languages.d.ts +2 -2
- package/scripts/constants/languages.js +2 -2
- package/scripts/generators/news-enhanced.js +13 -3
- package/scripts/generators/pipeline/analysis-classification.d.ts +49 -0
- package/scripts/generators/pipeline/analysis-classification.js +333 -0
- package/scripts/generators/pipeline/analysis-existing.d.ts +67 -0
- package/scripts/generators/pipeline/analysis-existing.js +547 -0
- package/scripts/generators/pipeline/analysis-helpers.d.ts +140 -0
- package/scripts/generators/pipeline/analysis-helpers.js +266 -0
- package/scripts/generators/pipeline/analysis-risk.d.ts +49 -0
- package/scripts/generators/pipeline/analysis-risk.js +417 -0
- package/scripts/generators/pipeline/analysis-stage.d.ts +19 -39
- package/scripts/generators/pipeline/analysis-stage.js +219 -1704
- package/scripts/generators/pipeline/analysis-threats.d.ts +41 -0
- package/scripts/generators/pipeline/analysis-threats.js +142 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts +25 -15
- package/scripts/generators/pipeline/fetch-stage.js +293 -117
- package/scripts/generators/strategies/article-strategy.d.ts +126 -7
- package/scripts/generators/strategies/article-strategy.js +491 -1
- package/scripts/generators/strategies/breaking-news-strategy.js +98 -8
- package/scripts/generators/strategies/committee-reports-strategy.js +23 -2
- package/scripts/generators/strategies/month-ahead-strategy.js +23 -2
- package/scripts/generators/strategies/monthly-review-strategy.js +13 -1
- package/scripts/generators/strategies/motions-strategy.js +15 -1
- package/scripts/generators/strategies/propositions-strategy.js +15 -1
- package/scripts/generators/strategies/week-ahead-strategy.js +19 -1
- package/scripts/generators/strategies/weekly-review-strategy.js +17 -1
- package/scripts/generators/synthesis-summary.d.ts +93 -0
- package/scripts/generators/synthesis-summary.js +364 -0
- package/scripts/index.d.ts +5 -2
- package/scripts/index.js +6 -1
- package/scripts/mcp/ep-mcp-client.d.ts +34 -1
- package/scripts/mcp/ep-mcp-client.js +110 -2
- package/scripts/mcp/mcp-connection.d.ts +3 -1
- package/scripts/mcp/mcp-connection.js +35 -4
- package/scripts/templates/article-template.js +24 -22
- package/scripts/templates/section-builders.js +2 -5
- package/scripts/types/index.d.ts +2 -1
- package/scripts/types/mcp.d.ts +7 -0
- package/scripts/types/political-classification.d.ts +1 -1
- package/scripts/types/quality.d.ts +9 -6
- package/scripts/types/significance.d.ts +130 -0
- package/scripts/types/significance.js +4 -0
- package/scripts/utils/article-quality-scorer.d.ts +13 -11
- package/scripts/utils/article-quality-scorer.js +36 -23
- package/scripts/utils/file-utils.d.ts +2 -2
- package/scripts/utils/file-utils.js +2 -2
- package/scripts/utils/html-sanitize.d.ts +10 -0
- package/scripts/utils/html-sanitize.js +32 -0
- package/scripts/utils/political-classification.d.ts +8 -7
- package/scripts/utils/political-classification.js +8 -7
- package/scripts/utils/political-risk-assessment.d.ts +1 -1
- package/scripts/utils/political-risk-assessment.js +1 -1
- package/scripts/utils/significance-scoring.d.ts +97 -0
- package/scripts/utils/significance-scoring.js +190 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Pipeline/AnalysisHelpers
|
|
3
|
+
* @description Shared utility functions for the analysis pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Provides sanitization, data coercion, markdown formatting, and file I/O
|
|
6
|
+
* helpers consumed by the category-specific analysis builder modules
|
|
7
|
+
* (`analysis-classification.ts`, `analysis-threats.ts`, `analysis-risk.ts`,
|
|
8
|
+
* `analysis-existing.ts`) and the orchestrator (`analysis-stage.ts`).
|
|
9
|
+
*/
|
|
10
|
+
import type { ConfidenceLevel } from '../../types/index.js';
|
|
11
|
+
import type { ClassificationInput } from '../../types/political-classification.js';
|
|
12
|
+
import type { ThreatAssessmentInput } from '../../types/political-threats.js';
|
|
13
|
+
import type { AnalysisMethod } from './analysis-stage.js';
|
|
14
|
+
/** Empty table row placeholder for 6-column tables */
|
|
15
|
+
export declare const EMPTY_TABLE_ROW_6 = "| \u2014 | \u2014 | \u2014 | \u2014 | \u2014 | \u2014 |";
|
|
16
|
+
/**
|
|
17
|
+
* Sanitize untrusted text for safe use in a Markdown table cell.
|
|
18
|
+
*
|
|
19
|
+
* Escapes pipe characters, backslashes, and HTML entities, then normalizes
|
|
20
|
+
* whitespace to prevent table layout corruption from external MCP data.
|
|
21
|
+
*
|
|
22
|
+
* @param input - Untrusted cell text
|
|
23
|
+
* @returns Sanitized text safe for Markdown table cells
|
|
24
|
+
*/
|
|
25
|
+
export declare function sanitizeCell(input: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Sanitize a document identifier for safe use as a filesystem filename.
|
|
28
|
+
*
|
|
29
|
+
* Replaces characters unsafe for filenames with hyphens, collapses runs of
|
|
30
|
+
* hyphens, trims, and lowercases. When the result exceeds 80 characters,
|
|
31
|
+
* a deterministic hash suffix is appended to avoid collisions between IDs
|
|
32
|
+
* that share the same first 80 characters. Falls back to a deterministic
|
|
33
|
+
* hash of the input when the sanitized result is empty.
|
|
34
|
+
*
|
|
35
|
+
* @param id - Raw document identifier (e.g. "TA-10-2026-0094", procedure reference)
|
|
36
|
+
* @returns Filesystem-safe identifier string (max 80 chars)
|
|
37
|
+
*/
|
|
38
|
+
export declare function sanitizeDocumentId(id: string): string;
|
|
39
|
+
/** All feed array keys that contain individually-analysable documents */
|
|
40
|
+
export declare const DOCUMENT_FEED_KEYS: readonly ["adoptedTexts", "procedures", "documents", "plenaryDocuments", "committeeDocuments", "plenarySessionDocuments", "externalDocuments", "events"];
|
|
41
|
+
/**
|
|
42
|
+
* Extract a human-readable identifier from a raw feed item.
|
|
43
|
+
*
|
|
44
|
+
* Tries common EP data shapes (`docId`, `procedureId`, `id`, `eventId`,
|
|
45
|
+
* `title`) and falls back to a deterministic hash of the item's JSON
|
|
46
|
+
* representation for truly anonymous items, ensuring reproducibility.
|
|
47
|
+
*
|
|
48
|
+
* @param item - Raw feed item object
|
|
49
|
+
* @returns Best-effort identifier string
|
|
50
|
+
*/
|
|
51
|
+
export declare function extractDocumentId(item: Record<string, unknown>): string;
|
|
52
|
+
/**
|
|
53
|
+
* Extract a human-readable title from a raw feed item.
|
|
54
|
+
*
|
|
55
|
+
* @param item - Raw feed item object
|
|
56
|
+
* @returns Title string or fallback
|
|
57
|
+
*/
|
|
58
|
+
export declare function extractDocumentTitle(item: Record<string, unknown>): string;
|
|
59
|
+
/**
|
|
60
|
+
* Safely extract an array from fetchedData by key.
|
|
61
|
+
* @param data - Raw fetched data record
|
|
62
|
+
* @param key - Key to extract
|
|
63
|
+
* @returns Array or empty array if missing/invalid
|
|
64
|
+
*/
|
|
65
|
+
export declare function safeArr(data: Record<string, unknown>, key: string): readonly unknown[];
|
|
66
|
+
/**
|
|
67
|
+
* Cast fetchedData to ClassificationInput for the classification functions.
|
|
68
|
+
* @param data - Raw fetched data record
|
|
69
|
+
* @returns ClassificationInput-compatible object
|
|
70
|
+
*/
|
|
71
|
+
export declare function toClassificationInput(data: Record<string, unknown>): ClassificationInput;
|
|
72
|
+
/**
|
|
73
|
+
* Cast fetchedData to ThreatAssessmentInput for the threat assessment functions.
|
|
74
|
+
* @param data - Raw fetched data record
|
|
75
|
+
* @returns ThreatAssessmentInput-compatible object
|
|
76
|
+
*/
|
|
77
|
+
export declare function toThreatInput(data: Record<string, unknown>): ThreatAssessmentInput;
|
|
78
|
+
/**
|
|
79
|
+
* Build a YAML-frontmatter header block for analysis markdown files.
|
|
80
|
+
*
|
|
81
|
+
* @param method - Analysis method identifier
|
|
82
|
+
* @param date - ISO date of the analysis
|
|
83
|
+
* @param confidence - Confidence level for this result
|
|
84
|
+
* @returns Markdown frontmatter string
|
|
85
|
+
*/
|
|
86
|
+
export declare function buildMarkdownHeader(method: AnalysisMethod | string, date: string, confidence: ConfidenceLevel): string;
|
|
87
|
+
/**
|
|
88
|
+
* Write a text file to disk.
|
|
89
|
+
*
|
|
90
|
+
* Used for both analysis markdown files and the analysis `manifest.json`.
|
|
91
|
+
*
|
|
92
|
+
* @param filePath - Absolute file path
|
|
93
|
+
* @param content - File content as a UTF-8 string
|
|
94
|
+
*/
|
|
95
|
+
export declare function writeTextFile(filePath: string, content: string): void;
|
|
96
|
+
/**
|
|
97
|
+
* Map an impact level to a numeric value for Mermaid pie charts.
|
|
98
|
+
*
|
|
99
|
+
* @param level - Impact level string (e.g. 'none', 'low', 'moderate', 'high', 'critical')
|
|
100
|
+
* @returns Numeric value for chart rendering
|
|
101
|
+
*/
|
|
102
|
+
export declare function impactToNum(level: string): number;
|
|
103
|
+
/**
|
|
104
|
+
* Map an impact level string to a coloured indicator emoji.
|
|
105
|
+
*
|
|
106
|
+
* @param level - Impact level string
|
|
107
|
+
* @returns Emoji indicator
|
|
108
|
+
*/
|
|
109
|
+
export declare function impactIndicator(level: string): string;
|
|
110
|
+
/**
|
|
111
|
+
* Return the name of the highest-impact dimension from an impact matrix.
|
|
112
|
+
*
|
|
113
|
+
* @param matrix - Impact matrix with five dimension levels
|
|
114
|
+
* @param matrix.legislativeImpact - Legislative impact level
|
|
115
|
+
* @param matrix.coalitionImpact - Coalition impact level
|
|
116
|
+
* @param matrix.publicOpinionImpact - Public opinion impact level
|
|
117
|
+
* @param matrix.institutionalImpact - Institutional impact level
|
|
118
|
+
* @param matrix.economicImpact - Economic impact level
|
|
119
|
+
* @returns Name of the dimension with the highest impact score
|
|
120
|
+
*/
|
|
121
|
+
export declare function highestImpactDimension(matrix: {
|
|
122
|
+
legislativeImpact: string;
|
|
123
|
+
coalitionImpact: string;
|
|
124
|
+
publicOpinionImpact: string;
|
|
125
|
+
institutionalImpact: string;
|
|
126
|
+
economicImpact: string;
|
|
127
|
+
}): string;
|
|
128
|
+
/**
|
|
129
|
+
* Check whether the fetched data contains any substantive EP data.
|
|
130
|
+
*
|
|
131
|
+
* Returns `true` when at least one data category has non-empty arrays.
|
|
132
|
+
* Used to gate analysis execution — analysis should not run on empty data.
|
|
133
|
+
*
|
|
134
|
+
* @param data - Raw fetched data record
|
|
135
|
+
* @returns true if any substantive data is present
|
|
136
|
+
*/
|
|
137
|
+
export declare function hasSubstantiveData(data: Record<string, unknown>): boolean;
|
|
138
|
+
/** Type for analysis method markdown builder functions */
|
|
139
|
+
export type MarkdownBuilder = (fetchedData: Record<string, unknown>, date: string) => string;
|
|
140
|
+
//# sourceMappingURL=analysis-helpers.d.ts.map
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { atomicWrite } from '../../utils/file-utils.js';
|
|
4
|
+
// ─── Markdown constants ───────────────────────────────────────────────────────
|
|
5
|
+
/** Empty table row placeholder for 6-column tables */
|
|
6
|
+
export const EMPTY_TABLE_ROW_6 = '| — | — | — | — | — | — |';
|
|
7
|
+
// ─── Sanitization helpers ─────────────────────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* Sanitize untrusted text for safe use in a Markdown table cell.
|
|
10
|
+
*
|
|
11
|
+
* Escapes pipe characters, backslashes, and HTML entities, then normalizes
|
|
12
|
+
* whitespace to prevent table layout corruption from external MCP data.
|
|
13
|
+
*
|
|
14
|
+
* @param input - Untrusted cell text
|
|
15
|
+
* @returns Sanitized text safe for Markdown table cells
|
|
16
|
+
*/
|
|
17
|
+
export function sanitizeCell(input) {
|
|
18
|
+
return input
|
|
19
|
+
.replace(/\\/g, '\\\\')
|
|
20
|
+
.replace(/\|/g, '\\|')
|
|
21
|
+
.replace(/&/g, '&')
|
|
22
|
+
.replace(/</g, '<')
|
|
23
|
+
.replace(/>/g, '>')
|
|
24
|
+
.replace(/[\r\n]+/g, ' ')
|
|
25
|
+
.trim();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sanitize a document identifier for safe use as a filesystem filename.
|
|
29
|
+
*
|
|
30
|
+
* Replaces characters unsafe for filenames with hyphens, collapses runs of
|
|
31
|
+
* hyphens, trims, and lowercases. When the result exceeds 80 characters,
|
|
32
|
+
* a deterministic hash suffix is appended to avoid collisions between IDs
|
|
33
|
+
* that share the same first 80 characters. Falls back to a deterministic
|
|
34
|
+
* hash of the input when the sanitized result is empty.
|
|
35
|
+
*
|
|
36
|
+
* @param id - Raw document identifier (e.g. "TA-10-2026-0094", procedure reference)
|
|
37
|
+
* @returns Filesystem-safe identifier string (max 80 chars)
|
|
38
|
+
*/
|
|
39
|
+
export function sanitizeDocumentId(id) {
|
|
40
|
+
const full = id
|
|
41
|
+
.toLowerCase()
|
|
42
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
43
|
+
.replace(/^-/, '')
|
|
44
|
+
.replace(/-$/, '');
|
|
45
|
+
if (!full) {
|
|
46
|
+
let hash = 0;
|
|
47
|
+
for (let i = 0; i < id.length; i++) {
|
|
48
|
+
hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;
|
|
49
|
+
}
|
|
50
|
+
return `anon-${Math.abs(hash).toString(36).slice(0, 12)}`;
|
|
51
|
+
}
|
|
52
|
+
if (full.length > 80) {
|
|
53
|
+
let hash = 0;
|
|
54
|
+
for (let i = 0; i < id.length; i++) {
|
|
55
|
+
hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;
|
|
56
|
+
}
|
|
57
|
+
return `${full.slice(0, 72)}-${Math.abs(hash).toString(36).slice(0, 7)}`;
|
|
58
|
+
}
|
|
59
|
+
return full;
|
|
60
|
+
}
|
|
61
|
+
// ─── Data coercion helpers ────────────────────────────────────────────────────
|
|
62
|
+
/** All feed array keys that contain individually-analysable documents */
|
|
63
|
+
export const DOCUMENT_FEED_KEYS = [
|
|
64
|
+
'adoptedTexts',
|
|
65
|
+
'procedures',
|
|
66
|
+
'documents',
|
|
67
|
+
'plenaryDocuments',
|
|
68
|
+
'committeeDocuments',
|
|
69
|
+
'plenarySessionDocuments',
|
|
70
|
+
'externalDocuments',
|
|
71
|
+
'events',
|
|
72
|
+
];
|
|
73
|
+
/**
|
|
74
|
+
* Extract a human-readable identifier from a raw feed item.
|
|
75
|
+
*
|
|
76
|
+
* Tries common EP data shapes (`docId`, `procedureId`, `id`, `eventId`,
|
|
77
|
+
* `title`) and falls back to a deterministic hash of the item's JSON
|
|
78
|
+
* representation for truly anonymous items, ensuring reproducibility.
|
|
79
|
+
*
|
|
80
|
+
* @param item - Raw feed item object
|
|
81
|
+
* @returns Best-effort identifier string
|
|
82
|
+
*/
|
|
83
|
+
export function extractDocumentId(item) {
|
|
84
|
+
for (const key of ['docId', 'procedureId', 'id', 'eventId']) {
|
|
85
|
+
const val = item[key]; // eslint-disable-line security/detect-object-injection -- keys are string literals
|
|
86
|
+
if (typeof val === 'string' && val.length > 0)
|
|
87
|
+
return val;
|
|
88
|
+
}
|
|
89
|
+
const title = item['title'];
|
|
90
|
+
if (typeof title === 'string' && title.length > 0) {
|
|
91
|
+
const repr = JSON.stringify(item);
|
|
92
|
+
let hash = 0;
|
|
93
|
+
for (let i = 0; i < repr.length; i++) {
|
|
94
|
+
hash = ((hash << 5) - hash + repr.charCodeAt(i)) | 0;
|
|
95
|
+
}
|
|
96
|
+
return `${title.slice(0, 50)}-${Math.abs(hash).toString(36).slice(0, 8)}`;
|
|
97
|
+
}
|
|
98
|
+
const repr = JSON.stringify(item);
|
|
99
|
+
let hash = 0;
|
|
100
|
+
for (let i = 0; i < repr.length; i++) {
|
|
101
|
+
hash = ((hash << 5) - hash + repr.charCodeAt(i)) | 0;
|
|
102
|
+
}
|
|
103
|
+
return `anonymous-${Math.abs(hash).toString(36)}`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extract a human-readable title from a raw feed item.
|
|
107
|
+
*
|
|
108
|
+
* @param item - Raw feed item object
|
|
109
|
+
* @returns Title string or fallback
|
|
110
|
+
*/
|
|
111
|
+
export function extractDocumentTitle(item) {
|
|
112
|
+
const title = item['title'];
|
|
113
|
+
if (typeof title === 'string' && title.length > 0)
|
|
114
|
+
return title;
|
|
115
|
+
const label = item['label'] ?? item['name'] ?? item['description'];
|
|
116
|
+
if (typeof label === 'string' && label.length > 0)
|
|
117
|
+
return label;
|
|
118
|
+
return 'Untitled document';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Safely extract an array from fetchedData by key.
|
|
122
|
+
* @param data - Raw fetched data record
|
|
123
|
+
* @param key - Key to extract
|
|
124
|
+
* @returns Array or empty array if missing/invalid
|
|
125
|
+
*/
|
|
126
|
+
export function safeArr(data, key) {
|
|
127
|
+
const val = data[key]; // eslint-disable-line security/detect-object-injection -- key is a literal string from caller
|
|
128
|
+
return Array.isArray(val) ? val : [];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Cast fetchedData to ClassificationInput for the classification functions.
|
|
132
|
+
* @param data - Raw fetched data record
|
|
133
|
+
* @returns ClassificationInput-compatible object
|
|
134
|
+
*/
|
|
135
|
+
export function toClassificationInput(data) {
|
|
136
|
+
return data;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Cast fetchedData to ThreatAssessmentInput for the threat assessment functions.
|
|
140
|
+
* @param data - Raw fetched data record
|
|
141
|
+
* @returns ThreatAssessmentInput-compatible object
|
|
142
|
+
*/
|
|
143
|
+
export function toThreatInput(data) {
|
|
144
|
+
return {
|
|
145
|
+
votingRecords: safeArr(data, 'votingRecords'),
|
|
146
|
+
coalitionData: safeArr(data, 'coalitions'),
|
|
147
|
+
mepInfluence: safeArr(data, 'mepUpdates'),
|
|
148
|
+
procedures: safeArr(data, 'procedures'),
|
|
149
|
+
anomalies: safeArr(data, 'anomalies'),
|
|
150
|
+
questions: safeArr(data, 'questions'),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// ─── Markdown helpers ─────────────────────────────────────────────────────────
|
|
154
|
+
/**
|
|
155
|
+
* Build a YAML-frontmatter header block for analysis markdown files.
|
|
156
|
+
*
|
|
157
|
+
* @param method - Analysis method identifier
|
|
158
|
+
* @param date - ISO date of the analysis
|
|
159
|
+
* @param confidence - Confidence level for this result
|
|
160
|
+
* @returns Markdown frontmatter string
|
|
161
|
+
*/
|
|
162
|
+
export function buildMarkdownHeader(method, date, confidence) {
|
|
163
|
+
return `---
|
|
164
|
+
method: ${method}
|
|
165
|
+
date: ${date}
|
|
166
|
+
confidence: ${confidence}
|
|
167
|
+
generated: ${new Date().toISOString()}
|
|
168
|
+
source: pipeline
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
`;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Write a text file to disk.
|
|
175
|
+
*
|
|
176
|
+
* Used for both analysis markdown files and the analysis `manifest.json`.
|
|
177
|
+
*
|
|
178
|
+
* @param filePath - Absolute file path
|
|
179
|
+
* @param content - File content as a UTF-8 string
|
|
180
|
+
*/
|
|
181
|
+
export function writeTextFile(filePath, content) {
|
|
182
|
+
atomicWrite(filePath, content);
|
|
183
|
+
}
|
|
184
|
+
// ─── Mermaid chart helpers ────────────────────────────────────────────────────
|
|
185
|
+
/**
|
|
186
|
+
* Map an impact level to a numeric value for Mermaid pie charts.
|
|
187
|
+
*
|
|
188
|
+
* @param level - Impact level string (e.g. 'none', 'low', 'moderate', 'high', 'critical')
|
|
189
|
+
* @returns Numeric value for chart rendering
|
|
190
|
+
*/
|
|
191
|
+
export function impactToNum(level) {
|
|
192
|
+
const map = {
|
|
193
|
+
none: 5,
|
|
194
|
+
low: 20,
|
|
195
|
+
moderate: 45,
|
|
196
|
+
high: 70,
|
|
197
|
+
critical: 90,
|
|
198
|
+
};
|
|
199
|
+
return map[level.toLowerCase()] ?? 30;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Map an impact level string to a coloured indicator emoji.
|
|
203
|
+
*
|
|
204
|
+
* @param level - Impact level string
|
|
205
|
+
* @returns Emoji indicator
|
|
206
|
+
*/
|
|
207
|
+
export function impactIndicator(level) {
|
|
208
|
+
const lower = level.toLowerCase();
|
|
209
|
+
return lower === 'high' || lower === 'critical' ? '🔴' : lower === 'moderate' ? '🟡' : '🟢';
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Return the name of the highest-impact dimension from an impact matrix.
|
|
213
|
+
*
|
|
214
|
+
* @param matrix - Impact matrix with five dimension levels
|
|
215
|
+
* @param matrix.legislativeImpact - Legislative impact level
|
|
216
|
+
* @param matrix.coalitionImpact - Coalition impact level
|
|
217
|
+
* @param matrix.publicOpinionImpact - Public opinion impact level
|
|
218
|
+
* @param matrix.institutionalImpact - Institutional impact level
|
|
219
|
+
* @param matrix.economicImpact - Economic impact level
|
|
220
|
+
* @returns Name of the dimension with the highest impact score
|
|
221
|
+
*/
|
|
222
|
+
export function highestImpactDimension(matrix) {
|
|
223
|
+
return ([
|
|
224
|
+
{ name: 'Legislative', level: matrix.legislativeImpact },
|
|
225
|
+
{ name: 'Coalition', level: matrix.coalitionImpact },
|
|
226
|
+
{ name: 'Public Opinion', level: matrix.publicOpinionImpact },
|
|
227
|
+
{ name: 'Institutional', level: matrix.institutionalImpact },
|
|
228
|
+
{ name: 'Economic', level: matrix.economicImpact },
|
|
229
|
+
].sort((a, b) => impactToNum(b.level) - impactToNum(a.level))[0]?.name ?? 'N/A');
|
|
230
|
+
}
|
|
231
|
+
// ─── Substantive data check ───────────────────────────────────────────────────
|
|
232
|
+
/** Keys in fetchedData that count as substantive EP data */
|
|
233
|
+
const SUBSTANTIVE_DATA_KEYS = [
|
|
234
|
+
'events',
|
|
235
|
+
'procedures',
|
|
236
|
+
'adoptedTexts',
|
|
237
|
+
'documents',
|
|
238
|
+
'votingRecords',
|
|
239
|
+
'coalitions',
|
|
240
|
+
'questions',
|
|
241
|
+
'mepUpdates',
|
|
242
|
+
'plenaryDocuments',
|
|
243
|
+
'committeeDocuments',
|
|
244
|
+
'plenarySessionDocuments',
|
|
245
|
+
'externalDocuments',
|
|
246
|
+
'declarations',
|
|
247
|
+
'corporateBodies',
|
|
248
|
+
];
|
|
249
|
+
/**
|
|
250
|
+
* Check whether the fetched data contains any substantive EP data.
|
|
251
|
+
*
|
|
252
|
+
* Returns `true` when at least one data category has non-empty arrays.
|
|
253
|
+
* Used to gate analysis execution — analysis should not run on empty data.
|
|
254
|
+
*
|
|
255
|
+
* @param data - Raw fetched data record
|
|
256
|
+
* @returns true if any substantive data is present
|
|
257
|
+
*/
|
|
258
|
+
export function hasSubstantiveData(data) {
|
|
259
|
+
for (const key of SUBSTANTIVE_DATA_KEYS) {
|
|
260
|
+
const arr = safeArr(data, key);
|
|
261
|
+
if (arr.length > 0)
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=analysis-helpers.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { MarkdownBuilder } from './analysis-helpers.js';
|
|
2
|
+
import type { AnalysisMethod } from './analysis-stage.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build markdown for the risk scoring matrix.
|
|
5
|
+
*
|
|
6
|
+
* @param fetchedData - Raw fetched EP data
|
|
7
|
+
* @param date - Analysis date
|
|
8
|
+
* @returns Markdown content string
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildRiskMatrixMarkdown(fetchedData: Record<string, unknown>, date: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Build markdown for political capital at risk analysis.
|
|
13
|
+
*
|
|
14
|
+
* @param fetchedData - Raw fetched EP data
|
|
15
|
+
* @param date - Analysis date
|
|
16
|
+
* @returns Markdown content string
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildPoliticalCapitalRiskMarkdown(fetchedData: Record<string, unknown>, date: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Build markdown for the quantitative SWOT analysis.
|
|
21
|
+
*
|
|
22
|
+
* Produces a full narrative SWOT analysis modelled after the repository's
|
|
23
|
+
* SWOT.md — each quadrant item has a description, strategic value, evidence
|
|
24
|
+
* bullets, and a scored impact rating derived from actual fetched EP data.
|
|
25
|
+
*
|
|
26
|
+
* @param fetchedData - Raw fetched EP data
|
|
27
|
+
* @param date - Analysis date
|
|
28
|
+
* @returns Markdown content string
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildQuantitativeSwotMarkdown(fetchedData: Record<string, unknown>, date: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Build markdown for legislative velocity risk analysis.
|
|
33
|
+
*
|
|
34
|
+
* @param fetchedData - Raw fetched EP data
|
|
35
|
+
* @param date - Analysis date
|
|
36
|
+
* @returns Markdown content string
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildLegislativeVelocityRiskMarkdown(fetchedData: Record<string, unknown>, date: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Build markdown for the agent risk assessment workflow.
|
|
41
|
+
*
|
|
42
|
+
* @param fetchedData - Raw fetched EP data
|
|
43
|
+
* @param date - Analysis date
|
|
44
|
+
* @returns Markdown content string
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildAgentRiskWorkflowMarkdown(fetchedData: Record<string, unknown>, date: string): string;
|
|
47
|
+
/** All risk scoring method builders keyed by their AnalysisMethod identifier */
|
|
48
|
+
export declare const RISK_BUILDERS: Readonly<Partial<Record<AnalysisMethod, MarkdownBuilder>>>;
|
|
49
|
+
//# sourceMappingURL=analysis-risk.d.ts.map
|