Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | 243x 28x 28x 48x 48x 76x 41x 7x 67x 243x 67x 48x 67x 67x 67x 1x 47x 107x 32x | /**
* @module mcp-client/coverage
* @description Coverage-state and provenance helpers for riksdag-regering MCP data.
*/
import { isPersonProfileText } from '../data-transformers/helpers.js';
import type { MCPCoverageState, MCPProvenance, MCPStructuredSignal } from '../types/mcp.js';
import { FULL_TEXT_MIN_LENGTH as SUBSTANTIVE_TEXT_MIN_LENGTH } from '../parliamentary-data/full-text-threshold.js';
function asCleanString(value: unknown): string {
if (typeof value !== 'string') return '';
const trimmed = value.trim();
return isPersonProfileText(trimmed) ? '' : trimmed;
}
/**
* Extract the best-effort primary date for a document-like payload.
*/
export function extractDocumentDate(record: Record<string, unknown>): string | null {
const candidates = [
record['datum'],
record['inlämnad'],
record['inlamnad'],
record['publicerad'],
record['date'],
];
for (const candidate of candidates) {
if (typeof candidate === 'string' && candidate.trim().length >= 10) {
return candidate.trim().slice(0, 10);
}
}
return null;
}
/**
* Returns true when the payload carries meaningful document text.
*/
export function hasSubstantiveFullText(record: Record<string, unknown>): boolean {
const contentFields = ['fullText', 'fullContent', 'text', 'html'];
return contentFields.some((field) => asCleanString(record[field]).length > SUBSTANTIVE_TEXT_MIN_LENGTH);
}
/**
* Infer the machine-readable MCP coverage state for a document payload.
*
* The `requestedDate` should be the current analysis/run date (i.e. "today"),
* NOT the document's own publication date. Only when the document was published
* on the same day as the analysis run and still lacks full text do we infer
* `not_indexed` (indexing lag). For older documents without full text, the
* correct state is `metadata_only`.
*/
export function inferDocumentCoverageState(
record: Record<string, unknown>,
options: { requestedDate?: string | null; fullTextRequested?: boolean } = {},
): MCPCoverageState {
if (hasSubstantiveFullText(record)) return 'full_text';
const requestedDate = options.requestedDate?.slice(0, 10) ?? null;
const documentDate = extractDocumentDate(record);
// Only infer `not_indexed` when:
// 1. Full text was requested
// 2. We have BOTH a run date and a document date
// 3. The document was published on the SAME day as the analysis run
// This means the document is brand new and likely not yet indexed.
const sameDay = Boolean(
requestedDate && documentDate && requestedDate === documentDate,
);
if (options.fullTextRequested && sameDay) {
return 'not_indexed';
}
return 'metadata_only';
}
/**
* Build the standardised MCP provenance block for an MCP-derived payload.
*/
export function buildMcpProvenance(options: {
endpoint: string;
tool: string;
query: Record<string, unknown>;
resultCount: number;
coverageState: MCPCoverageState;
retrieval?: 'live' | 'retry_queue' | 'cache';
retrievedAt?: string;
signals?: MCPStructuredSignal[];
}): MCPProvenance {
return {
provider: 'riksdag-regering',
endpoint: options.endpoint,
tool: options.tool,
query: { ...options.query },
resultCount: options.resultCount,
coverageState: options.coverageState,
retrieval: options.retrieval ?? 'live',
retrievedAt: options.retrievedAt ?? new Date().toISOString(),
...(options.signals && options.signals.length > 0 ? { signals: options.signals } : {}),
};
}
/**
* Attach coverage-state metadata to an arbitrary record.
*/
export function attachCoverageMetadata<T extends Record<string, unknown>>(
record: T,
provenance: MCPProvenance,
): T & {
mcpCoverageState: MCPCoverageState;
mcpProvenance: MCPProvenance;
mcpSignals?: MCPStructuredSignal[];
} {
return {
...record,
mcpCoverageState: provenance.coverageState,
mcpProvenance: provenance,
...(provenance.signals && provenance.signals.length > 0
? { mcpSignals: provenance.signals }
: {}),
};
}
|