"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION = void 0; exports.executeAssistantMcpDiscoveryPilot = executeAssistantMcpDiscoveryPilot; const addressMcpClient_1 = require("./addressMcpClient"); const assistantMcpDiscoveryRuntimeAdapter_1 = require("./assistantMcpDiscoveryRuntimeAdapter"); const assistantMcpDiscoveryPolicy_1 = require("./assistantMcpDiscoveryPolicy"); const addressRecipeCatalog_1 = require("./addressRecipeCatalog"); exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION = "assistant_mcp_discovery_pilot_executor_v1"; const DEFAULT_DEPS = { executeAddressMcpQuery: addressMcpClient_1.executeAddressMcpQuery, executeAddressMcpMetadata: addressMcpClient_1.executeAddressMcpMetadata }; const ENTITY_RESOLUTION_COUNTERPARTY_LOOKUP_LIMIT = 1000; const ENTITY_RESOLUTION_COUNTERPARTY_QUERY_TEMPLATE = ` ВЫБРАТЬ ПЕРВЫЕ __LIMIT__ ПРЕДСТАВЛЕНИЕ(Контрагенты.Ссылка) КАК Контрагент, ПРЕДСТАВЛЕНИЕ(Контрагенты.Ссылка) КАК Counterparty, Контрагенты.Ссылка КАК КонтрагентСсылка, Контрагенты.Ссылка КАК CounterpartyRef, Контрагенты.Наименование КАК Наименование ИЗ Справочник.Контрагенты КАК Контрагенты `; const ENTITY_RESOLUTION_STOPWORDS = new Set([ "ооо", "ао", "зао", "ип", "llc", "ltd", "company", "контрагент", "counterparty", "поставщик", "supplier", "клиент", "customer", "в", "1с", "1c", "найди", "найти", "поищи", "search", "find" ]); function toNonEmptyString(value) { if (value === null || value === undefined) { return null; } const text = String(value).trim(); return text.length > 0 ? text : null; } function normalizeReasonCode(value) { const normalized = value .trim() .replace(/[^\p{L}\p{N}_.:-]+/gu, "_") .replace(/^_+|_+$/g, "") .toLowerCase(); return normalized.length > 0 ? normalized.slice(0, 120) : null; } function pushReason(target, value) { const normalized = normalizeReasonCode(value); if (normalized && !target.includes(normalized)) { target.push(normalized); } } function pushUnique(target, value) { const text = value.trim(); if (text && !target.includes(text)) { target.push(text); } } function aggregationAxisForPlanner(planner) { const axis = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.asked_aggregation_axis)?.toLowerCase(); return axis === "month" ? "month" : null; } function firstEntityCandidate(planner) { const candidates = planner.discovery_plan.turn_meaning_ref?.explicit_entity_candidates ?? []; for (const candidate of candidates) { const text = toNonEmptyString(candidate); if (text) { return text; } } return null; } function dateScopeToFilters(dateScope) { if (!dateScope) { return {}; } const yearMatch = dateScope.match(/^(\d{4})$/); if (yearMatch) { return { period_from: `${yearMatch[1]}-01-01`, period_to: `${yearMatch[1]}-12-31` }; } const rangeMatch = dateScope.match(/^(\d{4}-\d{2}-\d{2})\.\.(\d{4}-\d{2}-\d{2})$/); if (rangeMatch) { return { period_from: rangeMatch[1], period_to: rangeMatch[2] }; } const dateMatch = dateScope.match(/^(\d{4})-(\d{2})-(\d{2})/); if (dateMatch) { const date = `${dateMatch[1]}-${dateMatch[2]}-${dateMatch[3]}`; return { period_from: date, period_to: date }; } return {}; } function asOfDateFromDateScope(dateScope) { if (!dateScope) { return null; } const dateMatch = dateScope.match(/^(\d{4})-(\d{2})-(\d{2})/); if (dateMatch) { return `${dateMatch[1]}-${dateMatch[2]}-${dateMatch[3]}`; } const monthMatch = dateScope.match(/^(\d{4})-(\d{2})$/); if (monthMatch) { const year = Number(monthMatch[1]); const month = Number(monthMatch[2]); if (Number.isFinite(year) && Number.isFinite(month) && month >= 1 && month <= 12) { const lastDay = new Date(Date.UTC(year, month, 0)).getUTCDate(); return `${monthMatch[1]}-${monthMatch[2]}-${String(lastDay).padStart(2, "0")}`; } } const yearMatch = dateScope.match(/^(\d{4})$/); return yearMatch ? `${yearMatch[1]}-12-31` : null; } function buildLifecycleFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const counterparty = firstEntityCandidate(planner); const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); return { ...dateScopeToFilters(dateScope), ...(counterparty ? { counterparty } : {}), ...(organization ? { organization } : {}), limit: planner.discovery_plan.execution_budget.max_rows_per_probe, sort: "period_asc" }; } function buildValueFlowFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const counterparty = firstEntityCandidate(planner); const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); return { ...dateScopeToFilters(dateScope), ...(counterparty ? { counterparty } : {}), ...(organization ? { organization } : {}), limit: planner.discovery_plan.execution_budget.max_rows_per_probe, sort: "period_asc" }; } function buildBusinessOverviewProfileFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); return { ...dateScopeToFilters(dateScope), ...(organization ? { organization } : {}), limit: planner.discovery_plan.execution_budget.max_rows_per_probe, sort: "period_asc" }; } function buildBusinessOverviewTaxFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); const periodFilters = dateScopeToFilters(dateScope); if (!periodFilters.period_from || !periodFilters.period_to) { return null; } return { ...periodFilters, ...(organization ? { organization } : {}) }; } function buildBusinessOverviewDebtFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); const asOfDate = asOfDateFromDateScope(dateScope); if (!asOfDate) { return null; } return { ...dateScopeToFilters(dateScope), as_of_date: asOfDate, ...(organization ? { organization } : {}), limit: planner.discovery_plan.execution_budget.max_rows_per_probe, sort: "period_asc" }; } function buildBusinessOverviewInventoryFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); const asOfDate = asOfDateFromDateScope(dateScope); if (!asOfDate) { return null; } return { ...dateScopeToFilters(dateScope), as_of_date: asOfDate, ...(organization ? { organization } : {}), limit: planner.discovery_plan.execution_budget.max_rows_per_probe, sort: "period_asc" }; } function buildBusinessOverviewTradingMarginFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); const periodFilters = dateScopeToFilters(dateScope); if (!periodFilters.period_from || !periodFilters.period_to) { return null; } return { ...periodFilters, ...(organization ? { organization } : {}), limit: planner.discovery_plan.execution_budget.max_rows_per_probe, sort: "period_asc" }; } function buildInventoryExactFilters(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const subject = firstEntityCandidate(planner); const organization = toNonEmptyString(meaning?.explicit_organization_scope); const dateScope = toNonEmptyString(meaning?.explicit_date_scope); const asOfDate = asOfDateFromDateScope(dateScope); const filters = { ...dateScopeToFilters(dateScope), ...(asOfDate ? { as_of_date: asOfDate } : {}), ...(organization ? { organization } : {}), limit: planner.discovery_plan.execution_budget.max_rows_per_probe, sort: "period_asc" }; if (planner.selected_chain_id === "inventory_purchase_provenance" || planner.selected_chain_id === "inventory_sale_trace") { return { ...filters, ...(subject ? { item: subject } : {}) }; } if (planner.selected_chain_id === "inventory_supplier_overlap") { return { ...filters, ...(subject ? { counterparty: subject } : {}) }; } return filters; } function organizationScopeForPlanner(planner) { return toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.explicit_organization_scope); } function rankingNeedForPlanner(planner) { const rankingNeed = toNonEmptyString(planner.data_need_graph?.ranking_need)?.toLowerCase(); if (rankingNeed === "top_desc" || rankingNeed === "bottom_asc") { return rankingNeed; } return null; } function normalizeEntityResolutionText(value) { return String(value ?? "") .toLowerCase() .replace(/ё/g, "е") .replace(/[«»"'`]/g, " ") .replace(/[^\p{L}\p{N}\s-]+/gu, " ") .replace(/\s+/g, " ") .trim(); } function tokenizeEntityResolutionText(value) { return normalizeEntityResolutionText(value) .split(" ") .map((token) => token.trim()) .filter((token) => token.length >= 2 && !ENTITY_RESOLUTION_STOPWORDS.has(token)); } function isLowQualityEntityResolutionAnchor(value) { return tokenizeEntityResolutionText(value).length <= 0; } function entityResolutionCandidateName(row) { const candidates = [ row["Контрагент"], row["Counterparty"], row["Наименование"], row["name"], row["Name"], row["registrator"], row["Registrator"] ]; for (const candidate of candidates) { const text = toNonEmptyString(candidate); if (text) { return text; } } return null; } function entityResolutionCandidateRef(row) { const candidates = [row["КонтрагентСсылка"], row["CounterpartyRef"], row["ref"], row["Ref"]]; for (const candidate of candidates) { const text = toNonEmptyString(candidate); if (text) { return text; } } return null; } function scoreEntityResolutionCandidate(name, requested) { const normalizedName = normalizeEntityResolutionText(name); const normalizedRequested = normalizeEntityResolutionText(requested); const requestedTokens = tokenizeEntityResolutionText(requested); if (!normalizedName || !normalizedRequested || requestedTokens.length <= 0) { return null; } let score = 0; if (normalizedName === normalizedRequested) { score += 10_000; } else if (normalizedName.includes(normalizedRequested)) { score += 5_000; } else if (normalizedRequested.includes(normalizedName) && normalizedName.length >= 4) { score += 2_000; } for (const token of requestedTokens) { if (!normalizedName.includes(token)) { return null; } score += Math.max(40, token.length * 20); } score -= Math.abs(normalizedName.length - normalizedRequested.length); return score; } function deriveEntityResolution(result, requestedEntity) { if (!result || result.error || !requestedEntity) { return null; } const checkedCandidates = uniqueCandidateStrings(result.raw_rows .map((row) => entityResolutionCandidateName(row)) .filter((value) => Boolean(value))); const scoredCandidates = checkedCandidates .map((name) => { const score = scoreEntityResolutionCandidate(name, requestedEntity); return score === null ? null : { name, score }; }) .filter((value) => Boolean(value)) .sort((left, right) => right.score - left.score || left.name.length - right.name.length || left.name.localeCompare(right.name, "ru")); if (scoredCandidates.length <= 0) { return { requested_entity: requestedEntity, resolution_status: "not_found", resolved_entity: null, resolved_reference: null, matched_rows: result.rows.length, checked_candidates: checkedCandidates.slice(0, 12), ambiguity_candidates: [], confidence: null, inference_basis: "catalog_counterparty_search_rows" }; } const bestCandidate = scoredCandidates[0]; const bestNormalized = normalizeEntityResolutionText(bestCandidate.name); const requestedNormalized = normalizeEntityResolutionText(requestedEntity); const requestedTokens = tokenizeEntityResolutionText(requestedEntity); const exactMatch = bestNormalized === requestedNormalized; const strongContains = requestedTokens.length > 1 && bestNormalized.includes(requestedNormalized); const topCandidates = scoredCandidates.filter((candidate) => candidate.score === bestCandidate.score); if (topCandidates.length > 1 && !exactMatch && !strongContains) { return { requested_entity: requestedEntity, resolution_status: "ambiguous", resolved_entity: null, resolved_reference: null, matched_rows: result.rows.length, checked_candidates: checkedCandidates.slice(0, 12), ambiguity_candidates: topCandidates.map((candidate) => candidate.name).slice(0, 6), confidence: "low", inference_basis: "catalog_counterparty_search_rows" }; } const matchedRow = result.raw_rows.find((row) => normalizeEntityResolutionText(entityResolutionCandidateName(row)) === bestNormalized) ?? null; return { requested_entity: requestedEntity, resolution_status: "resolved", resolved_entity: bestCandidate.name, resolved_reference: matchedRow ? entityResolutionCandidateRef(matchedRow) : null, matched_rows: result.rows.length, checked_candidates: checkedCandidates.slice(0, 12), ambiguity_candidates: [], confidence: exactMatch ? "high" : strongContains ? "medium" : "low", inference_basis: "catalog_counterparty_search_rows" }; } function uniqueCandidateStrings(values) { const result = []; for (const value of values) { pushUnique(result, value); } return result; } function isLifecyclePilotEligible(planner) { if (planner.selected_chain_id === "lifecycle") { return true; } const meaning = planner.discovery_plan.turn_meaning_ref; const domain = String(meaning?.asked_domain_family ?? "").toLowerCase(); const action = String(meaning?.asked_action_family ?? "").toLowerCase(); const combined = `${domain} ${action}`; return (planner.proposed_primitives.includes("query_documents") && (combined.includes("lifecycle") || combined.includes("activity") || combined.includes("duration") || combined.includes("age"))); } function isDocumentEvidencePilotEligible(planner) { if (planner.selected_chain_id === "document_evidence") { return true; } const meaning = planner.discovery_plan.turn_meaning_ref; const domain = String(meaning?.asked_domain_family ?? "").toLowerCase(); const action = String(meaning?.asked_action_family ?? "").toLowerCase(); const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase(); const combined = `${domain} ${action} ${unsupported}`; return (planner.proposed_primitives.includes("query_documents") && (combined.includes("document") || combined.includes("list_documents"))); } function isMovementEvidencePilotEligible(planner) { if (planner.selected_chain_id === "movement_evidence") { return true; } const meaning = planner.discovery_plan.turn_meaning_ref; const domain = String(meaning?.asked_domain_family ?? "").toLowerCase(); const action = String(meaning?.asked_action_family ?? "").toLowerCase(); const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase(); const semanticNeed = String(planner.semantic_data_need ?? "").toLowerCase(); const combined = `${domain} ${action} ${unsupported} ${semanticNeed}`; return (planner.proposed_primitives.includes("query_movements") && (combined.includes("movement") || combined.includes("movements") || combined.includes("bank_operations") || combined.includes("movement_evidence") || combined.includes("list_movements"))); } function isValueFlowPilotEligible(planner) { if (planner.selected_chain_id === "value_flow" || planner.selected_chain_id === "value_flow_ranking" || planner.selected_chain_id === "value_flow_comparison") { return true; } const meaning = planner.discovery_plan.turn_meaning_ref; const domain = String(meaning?.asked_domain_family ?? "").toLowerCase(); const action = String(meaning?.asked_action_family ?? "").toLowerCase(); const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase(); const combined = `${domain} ${action} ${unsupported}`; return (planner.proposed_primitives.includes("query_movements") && (combined.includes("turnover") || combined.includes("revenue") || combined.includes("payment") || combined.includes("payout") || combined.includes("value"))); } function isBusinessOverviewPilotEligible(planner) { return planner.selected_chain_id === "business_overview"; } function isInventoryPilotEligible(planner) { return (planner.selected_chain_id === "inventory_stock_snapshot" || planner.selected_chain_id === "inventory_supplier_overlap" || planner.selected_chain_id === "inventory_purchase_provenance" || planner.selected_chain_id === "inventory_sale_trace"); } function isMetadataPilotEligible(planner) { if (planner.selected_chain_id === "metadata_inspection" || planner.selected_chain_id === "metadata_lane_clarification" || planner.selected_chain_id === "catalog_drilldown") { return true; } const meaning = planner.discovery_plan.turn_meaning_ref; const domain = String(meaning?.asked_domain_family ?? "").toLowerCase(); const action = String(meaning?.asked_action_family ?? "").toLowerCase(); const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase(); const semanticNeed = String(planner.semantic_data_need ?? "").toLowerCase(); const combined = `${domain} ${action} ${unsupported} ${semanticNeed}`; return (planner.proposed_primitives.includes("inspect_1c_metadata") && (combined.includes("metadata") || combined.includes("schema") || combined.includes("catalog") || combined.includes("inspect_documents") || combined.includes("inspect_registers") || combined.includes("inspect_fields"))); } function isEntityResolutionPilotEligible(planner) { if (planner.selected_chain_id === "entity_resolution") { return true; } const meaning = planner.discovery_plan.turn_meaning_ref; const domain = String(meaning?.asked_domain_family ?? "").toLowerCase(); const action = String(meaning?.asked_action_family ?? "").toLowerCase(); const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase(); const semanticNeed = String(planner.semantic_data_need ?? "").toLowerCase(); const combined = `${domain} ${action} ${unsupported} ${semanticNeed}`; return (planner.proposed_primitives.includes("search_business_entity") && (combined.includes("entity_resolution") || combined.includes("search_business_entity") || combined.includes("entity discovery") || combined.includes("counterparty search"))); } function metadataScopeForPlanner(planner) { const entityCandidate = firstEntityCandidate(planner); if (entityCandidate) { return entityCandidate; } if (planner.selected_chain_id === "catalog_drilldown") { const surface = planner.metadata_surface_ref; const scopeCandidate = [ ...(surface?.selected_surface_objects ?? []), surface?.selected_entity_set ?? "" ] .map((value) => toNonEmptyString(value)) .filter((value) => Boolean(value)) .map((value) => { const parts = value.split(".").map((item) => item.trim()).filter((item) => item.length > 0); return parts.length > 0 ? parts[parts.length - 1] ?? value : value; }) .find((value) => value.length > 0); if (scopeCandidate) { return scopeCandidate; } } const meaning = planner.discovery_plan.turn_meaning_ref; const combined = `${meaning?.asked_domain_family ?? ""} ${meaning?.asked_action_family ?? ""} ${meaning?.unsupported_but_understood_family ?? ""}` .toLowerCase() .trim(); if (combined.includes("vat")) { return "НДС"; } if (combined.includes("inventory")) { return "склад"; } if (combined.includes("counterparty")) { return "контрагент"; } return null; } function metadataTypesForPlanner(planner) { if (planner.selected_chain_id === "catalog_drilldown") { const selectedEntitySet = toNonEmptyString(planner.metadata_surface_ref?.selected_entity_set); if (selectedEntitySet) { return [selectedEntitySet]; } } const meaning = planner.discovery_plan.turn_meaning_ref; const action = String(meaning?.asked_action_family ?? "").toLowerCase(); if (action === "inspect_registers") { return ["РегистрНакопления", "РегистрСведений"]; } if (action === "inspect_documents") { return ["Документ"]; } if (action === "inspect_catalog") { return ["Справочник"]; } return ["Документ", "РегистрНакопления", "РегистрСведений", "Справочник"]; } function metadataScopeRankingAllowedForPlanner(planner) { const action = String(planner.discovery_plan.turn_meaning_ref?.asked_action_family ?? "").toLowerCase().trim(); return action === "inspect_surface"; } function valueFlowPilotProfile(planner) { const meaning = planner.discovery_plan.turn_meaning_ref; const action = String(meaning?.asked_action_family ?? "").toLowerCase(); const unsupported = String(meaning?.unsupported_but_understood_family ?? "").toLowerCase(); const combined = `${action} ${unsupported}`; if (combined.includes("net_value_flow") || combined.includes("bidirectional") || combined.includes("netting") || combined.includes("net")) { return { scope: "counterparty_bidirectional_value_flow_query_movements_v1", recipe_intent: null, direction: "bidirectional_net_value_flow" }; } if (combined.includes("payout") || combined.includes("outflow") || combined.includes("supplier") || combined.includes("paid")) { return { scope: "counterparty_supplier_payout_query_movements_v1", recipe_intent: "supplier_payouts_profile", direction: "outgoing_supplier_payout" }; } return { scope: "counterparty_value_flow_query_movements_v1", recipe_intent: "customer_revenue_and_payments", direction: "incoming_customer_revenue" }; } function inventoryIntentForPlanner(planner) { switch (planner.selected_chain_id) { case "inventory_stock_snapshot": return "inventory_on_hand_as_of_date"; case "inventory_supplier_overlap": return "inventory_supplier_stock_overlap_as_of_date"; case "inventory_purchase_provenance": return "inventory_purchase_provenance_for_item"; case "inventory_sale_trace": return "inventory_sale_trace_for_item"; default: return null; } } function inventoryExecutablePrimitiveForPlanner(planner) { switch (planner.selected_chain_id) { case "inventory_stock_snapshot": case "inventory_supplier_overlap": return "query_movements"; case "inventory_purchase_provenance": case "inventory_sale_trace": return "query_documents"; default: return null; } } function skippedProbeResult(step, limitation) { return { primitive_id: step.primitive_id, status: "skipped", rows_received: 0, rows_matched: 0, limitation }; } function queryResultToProbeResult(primitiveId, result) { return { primitive_id: primitiveId, status: result.error ? "error" : "ok", rows_received: result.fetched_rows, rows_matched: result.matched_rows, limitation: result.error }; } function metadataResultToProbeResult(primitiveId, result) { return { primitive_id: primitiveId, status: result.error ? "error" : "ok", rows_received: result.fetched_rows, rows_matched: result.error ? 0 : result.rows.length, limitation: result.error }; } function toCoverageAwareQueryResult(result, options = {}) { if (!result) { return null; } return { ...result, coverage_limited_by_probe_limit: options.coverageLimitedByProbeLimit ?? false, coverage_recovered_by_period_chunking: options.coverageRecoveredByPeriodChunking ?? false, period_chunking_granularity: options.periodChunkingGranularity ?? null, period_chunk_count: options.periodChunkCount ?? 0 }; } function monthWindowsForYear(year) { const result = []; for (let month = 0; month < 12; month += 1) { const start = new Date(Date.UTC(Number(year), month, 1)); const end = new Date(Date.UTC(Number(year), month + 1, 0)); result.push({ period_from: `${start.getUTCFullYear()}-${String(start.getUTCMonth() + 1).padStart(2, "0")}-${String(start.getUTCDate()).padStart(2, "0")}`, period_to: `${end.getUTCFullYear()}-${String(end.getUTCMonth() + 1).padStart(2, "0")}-${String(end.getUTCDate()).padStart(2, "0")}` }); } return result; } function periodWindowsForDateScope(dateScope) { const yearMatch = dateScope?.match(/^(\d{4})$/); if (yearMatch) { return monthWindowsForYear(yearMatch[1]); } return []; } function mergeCoverageAwareQueryResults(results, options) { const rawRows = results.flatMap((item) => item.raw_rows); const rows = results.flatMap((item) => item.rows); const errors = results.map((item) => toNonEmptyString(item.error)).filter((item) => Boolean(item)); return { fetched_rows: results.reduce((sum, item) => sum + item.fetched_rows, 0), matched_rows: results.reduce((sum, item) => sum + item.matched_rows, 0), raw_rows: rawRows, rows, error: errors[0] ?? null, coverage_limited_by_probe_limit: options.coverageLimitedByProbeLimit, coverage_recovered_by_period_chunking: options.coverageRecoveredByPeriodChunking, period_chunking_granularity: options.periodChunkingGranularity, period_chunk_count: options.periodChunkCount }; } async function executeCoverageAwareValueFlowQuery(input) { const queryLimitations = []; const probeResults = []; let executedProbeCount = 0; const broadRecipePlan = input.recipePlanBuilder(input.baseFilters); const broadResult = await input.deps.executeAddressMcpQuery({ query: broadRecipePlan.query, limit: broadRecipePlan.limit, account_scope: broadRecipePlan.account_scope }); executedProbeCount += 1; probeResults.push(queryResultToProbeResult(input.primitiveId, broadResult)); const broadCoverageLimited = !broadResult.error && broadResult.matched_rows >= input.maxRowsPerProbe; if (broadResult.error) { pushUnique(queryLimitations, broadResult.error); return { result: toCoverageAwareQueryResult(broadResult, { coverageLimitedByProbeLimit: false }), probe_results: probeResults, query_limitations: queryLimitations, executed_probe_count: executedProbeCount }; } const periodWindows = periodWindowsForDateScope(input.dateScope); if (!broadCoverageLimited || periodWindows.length === 0) { return { result: toCoverageAwareQueryResult(broadResult, { coverageLimitedByProbeLimit: broadCoverageLimited }), probe_results: probeResults, query_limitations: queryLimitations, executed_probe_count: executedProbeCount }; } const requiredChunkProbeCount = periodWindows.length; if (executedProbeCount + requiredChunkProbeCount > input.maxProbeCount) { pushUnique(queryLimitations, "Requested period hit the MCP row limit, but the approved monthly recovery probe budget is smaller than the required subperiod count"); return { result: toCoverageAwareQueryResult(broadResult, { coverageLimitedByProbeLimit: true }), probe_results: probeResults, query_limitations: queryLimitations, executed_probe_count: executedProbeCount }; } const chunkResults = []; let anyChunkLimited = false; let anyChunkError = false; for (const window of periodWindows) { const chunkFilters = { ...input.baseFilters, period_from: window.period_from, period_to: window.period_to }; const chunkPlan = input.recipePlanBuilder(chunkFilters); const chunkResult = await input.deps.executeAddressMcpQuery({ query: chunkPlan.query, limit: chunkPlan.limit, account_scope: chunkPlan.account_scope }); executedProbeCount += 1; probeResults.push(queryResultToProbeResult(input.primitiveId, chunkResult)); if (chunkResult.error) { anyChunkError = true; pushUnique(queryLimitations, chunkResult.error); continue; } if (chunkResult.matched_rows >= input.maxRowsPerProbe) { anyChunkLimited = true; } chunkResults.push(chunkResult); } if (chunkResults.length === 0 && anyChunkError) { return { result: toCoverageAwareQueryResult(broadResult, { coverageLimitedByProbeLimit: true }), probe_results: probeResults, query_limitations: queryLimitations, executed_probe_count: executedProbeCount }; } return { result: mergeCoverageAwareQueryResults(chunkResults, { coverageLimitedByProbeLimit: anyChunkLimited || anyChunkError, coverageRecoveredByPeriodChunking: true, periodChunkingGranularity: "month", periodChunkCount: periodWindows.length }), probe_results: probeResults, query_limitations: queryLimitations, executed_probe_count: executedProbeCount }; } function summarizeLifecycleRows(result) { if (result.error) { return null; } if (result.fetched_rows <= 0) { return "0 MCP document rows fetched"; } return `${result.fetched_rows} MCP document rows fetched, ${result.matched_rows} matched lifecycle scope`; } function summarizeDocumentRows(result) { if (result.error) { return null; } if (result.fetched_rows <= 0) { return "0 MCP document rows fetched"; } return `${result.fetched_rows} MCP document rows fetched, ${result.matched_rows} matched document scope`; } function summarizeMovementRows(result) { if (result.error) { return null; } if (result.fetched_rows <= 0) { return "0 MCP movement rows fetched"; } return `${result.fetched_rows} MCP movement rows fetched, ${result.matched_rows} matched movement scope`; } function summarizeValueFlowRows(result) { if (result.error) { return null; } if (result.fetched_rows <= 0) { return "0 MCP value-flow rows fetched"; } if (result.coverage_recovered_by_period_chunking && result.period_chunking_granularity === "month") { return `${result.period_chunk_count} monthly MCP value-flow probes fetched ${result.fetched_rows} rows total, ${result.matched_rows} matched value-flow scope after the broad probe hit the row limit`; } return `${result.fetched_rows} MCP value-flow rows fetched, ${result.matched_rows} matched value-flow scope`; } function summarizeInventoryRows(result) { if (result.error) { return null; } if (result.fetched_rows <= 0) { return "0 MCP inventory exact rows fetched"; } return `${result.fetched_rows} MCP inventory exact rows fetched, ${result.matched_rows} matched inventory scope`; } function summarizeMetadataRows(result) { if (result.error) { return null; } if (result.fetched_rows <= 0) { return "0 MCP metadata rows fetched"; } return `${result.fetched_rows} MCP metadata rows fetched`; } function summarizeEntityResolutionRows(result) { if (result.error) { return null; } if (result.fetched_rows <= 0) { return "0 MCP catalog rows fetched"; } return `${result.fetched_rows} MCP catalog rows fetched for entity search`; } function entityResolutionFollowupStepLimitation() { return "Entity-resolution could not continue because the checked catalog search step did not return a confirmed slice"; } function buildEntityResolutionResolveProbeResult(input) { if (!input.resolution) { return { primitive_id: "resolve_entity_reference", status: "ok", rows_received: input.queryResult.fetched_rows, rows_matched: 0, limitation: null }; } if (input.resolution.resolution_status === "resolved") { return { primitive_id: "resolve_entity_reference", status: "ok", rows_received: input.queryResult.fetched_rows, rows_matched: 1, limitation: null }; } return { primitive_id: "resolve_entity_reference", status: "ok", rows_received: input.queryResult.fetched_rows, rows_matched: 0, limitation: null }; } function buildEntityResolutionCoverageProbeResult(input) { const resolved = input.resolution?.resolution_status === "resolved"; return { primitive_id: "probe_coverage", status: "ok", rows_received: 1, rows_matched: resolved ? 1 : 0, limitation: null }; } function metadataRowText(row, keys) { for (const key of keys) { const text = toNonEmptyString(row[key]); if (text) { return text; } } return null; } function metadataObjectName(row) { return metadataRowText(row, [ "ПолноеИмя", "full_name", "FullName", "Имя", "name", "Name", "presentation", "Представление", "synonym", "Synonym" ]); } function metadataEntitySet(row) { return metadataRowText(row, [ "ТипМетаданных", "type", "Type", "meta_type", "MetaType", "ВидМетаданных", "kind" ]); } function inferMetadataEntitySetFromObjectName(objectName) { const text = String(objectName ?? "").trim(); if (!text) { return null; } const dotIndex = text.indexOf("."); if (dotIndex <= 0) { return null; } const entitySet = text.slice(0, dotIndex).trim(); return entitySet.length > 0 ? entitySet : null; } function metadataChildNames(value) { if (!Array.isArray(value)) { return []; } const result = []; for (const item of value) { if (!item || typeof item !== "object" || Array.isArray(item)) { continue; } const record = item; const fieldName = metadataRowText(record, ["Имя", "name", "Name", "full_name", "FullName"]); if (fieldName) { pushUnique(result, fieldName); } } return result; } function metadataAvailableFields(rows) { const result = []; for (const row of rows) { for (const field of metadataChildNames(row["Реквизиты"])) { pushUnique(result, field); } for (const field of metadataChildNames(row["attributes"])) { pushUnique(result, field); } for (const field of metadataChildNames(row["Attributes"])) { pushUnique(result, field); } for (const field of metadataChildNames(row["Измерения"])) { pushUnique(result, field); } for (const field of metadataChildNames(row["dimensions"])) { pushUnique(result, field); } for (const field of metadataChildNames(row["Ресурсы"])) { pushUnique(result, field); } for (const field of metadataChildNames(row["resources"])) { pushUnique(result, field); } } return result; } function normalizeMetadataEntitySetToken(value) { return String(value ?? "") .toLowerCase() .replace(/[\s_.-]+/g, ""); } function metadataMatchesRequestedType(entitySet, requestedMetaType) { const entityToken = normalizeMetadataEntitySetToken(entitySet); const requestedToken = normalizeMetadataEntitySetToken(requestedMetaType); return entityToken.includes(requestedToken) || requestedToken.includes(entityToken); } function metadataRouteFamilyForEntitySet(entitySet) { const token = normalizeMetadataEntitySetToken(entitySet); if (token.includes("документ") || token.includes("document")) { return "document_evidence"; } if (token.includes("регистрнакопления") || token.includes("регистсведений") || token.includes("регистрсведений") || token.includes("accumulationregister") || token.includes("informationregister")) { return "movement_evidence"; } if (token.includes("справочник") || token.includes("catalog") || token.includes("directory")) { return "catalog_drilldown"; } return null; } function metadataRouteFamilyForEntitySetRelaxed(entitySet) { const strict = metadataRouteFamilyForEntitySet(entitySet); if (strict) { return strict; } const raw = String(entitySet ?? "").trim(); if (!raw) { return null; } if (raw.includes("Документ") || raw.includes("Документ")) { return "document_evidence"; } if (raw.includes("РегистрНакопления") || raw.includes("РегистрСведений") || raw.includes("РегистрНакопления") || raw.includes("РегистрСведений")) { return "movement_evidence"; } if (raw.includes("Справочник") || raw.includes("Справочник")) { return "catalog_drilldown"; } return null; } function metadataNextPrimitiveForRouteFamily(routeFamily) { if (routeFamily === "document_evidence") { return "query_documents"; } if (routeFamily === "movement_evidence") { return "query_movements"; } if (routeFamily === "catalog_drilldown") { return "drilldown_related_objects"; } return null; } function selectMetadataEntityGrounding(availableEntitySets, requestedMetaTypes) { const requestedMatches = availableEntitySets.filter((entitySet) => requestedMetaTypes.some((requestedMetaType) => metadataMatchesRequestedType(entitySet, requestedMetaType))); if (requestedMatches.length === 1) { return { selectedEntitySet: requestedMatches[0] ?? null, ambiguityDetected: false, ambiguityEntitySets: [] }; } if (requestedMatches.length > 1) { return { selectedEntitySet: null, ambiguityDetected: true, ambiguityEntitySets: requestedMatches }; } if (availableEntitySets.length === 1) { return { selectedEntitySet: availableEntitySets[0] ?? null, ambiguityDetected: false, ambiguityEntitySets: [] }; } return { selectedEntitySet: null, ambiguityDetected: availableEntitySets.length > 1, ambiguityEntitySets: availableEntitySets }; } function metadataObjectsForEntitySet(entitySet, matchedObjects) { if (!entitySet) { return []; } return matchedObjects.filter((item) => item.startsWith(`${entitySet}.`) || item.includes(entitySet)); } function emptyMetadataSurfaceFamilyScores() { return { document_evidence: 0, movement_evidence: 0, catalog_drilldown: 0 }; } function metadataSurfaceFamilyScores(matchedObjects) { const scores = emptyMetadataSurfaceFamilyScores(); for (const objectName of matchedObjects) { const entitySet = inferMetadataEntitySetFromObjectName(objectName); const routeFamily = entitySet ? metadataRouteFamilyForEntitySetRelaxed(entitySet) : null; if (routeFamily) { scores[routeFamily] += 1; } } return scores; } function normalizeMetadataObjectRankingToken(value) { return String(value ?? "") .toLowerCase() .replace(/[^\p{L}\p{N}]+/gu, ""); } function metadataScopeRankingTokens(metadataScope) { const scope = String(metadataScope ?? "").trim(); if (!scope) { return []; } const condensed = normalizeMetadataObjectRankingToken(scope); const result = []; if (condensed.length >= 2) { pushUnique(result, condensed); } for (const token of scope.toLowerCase().split(/[^\p{L}\p{N}]+/gu)) { const normalized = normalizeMetadataObjectRankingToken(token); if (normalized.length >= 2) { pushUnique(result, normalized); } } return result; } function metadataObjectRelevanceScore(metadataScope, objectName) { const objectToken = normalizeMetadataObjectRankingToken(objectName); if (!objectToken) { return 1; } let score = 1; for (const token of metadataScopeRankingTokens(metadataScope)) { if (objectToken.includes(token)) { score += token.length >= 6 ? 4 : 3; } } return score; } function metadataWeightedSurfaceFamilyScores(matchedObjects, metadataScope) { const scores = emptyMetadataSurfaceFamilyScores(); for (const objectName of matchedObjects) { const entitySet = inferMetadataEntitySetFromObjectName(objectName); const routeFamily = entitySet ? metadataRouteFamilyForEntitySetRelaxed(entitySet) : null; if (routeFamily) { scores[routeFamily] += metadataObjectRelevanceScore(metadataScope, objectName); } } return scores; } function sortMetadataObjectsByRelevance(matchedObjects, metadataScope) { return [...matchedObjects].sort((left, right) => { const scoreDelta = metadataObjectRelevanceScore(metadataScope, right) - metadataObjectRelevanceScore(metadataScope, left); if (scoreDelta !== 0) { return scoreDelta; } return left.localeCompare(right, "ru"); }); } function metadataObjectsForRouteFamily(routeFamily, matchedObjects, metadataScope) { if (!routeFamily) { return []; } const filtered = matchedObjects.filter((objectName) => { const entitySet = inferMetadataEntitySetFromObjectName(objectName); return entitySet ? metadataRouteFamilyForEntitySetRelaxed(entitySet) === routeFamily : false; }); return sortMetadataObjectsByRelevance(filtered, metadataScope); } function selectDominantMetadataRouteFamilyFromScores(scores) { const ranked = Object.entries(scores) .filter(([, score]) => score > 0) .sort((left, right) => right[1] - left[1]); const top = ranked[0]; const second = ranked[1]; if (!top) { return null; } if (!second) { return top[0]; } const absoluteMargin = top[1] - second[1]; const relativeRatio = second[1] > 0 ? top[1] / second[1] : Number.POSITIVE_INFINITY; const clearlyDominant = absoluteMargin >= 2 || relativeRatio >= 1.5; return clearlyDominant ? top[0] : null; } function selectMetadataRouteFamilyFromSurfaceScores(input) { const countDominant = selectDominantMetadataRouteFamilyFromScores(input.countScores); if (countDominant) { return { routeFamily: countDominant, rankingApplied: false }; } if (!input.allowScopeRanking) { return { routeFamily: null, rankingApplied: false }; } const rankedCounts = Object.entries(input.countScores) .filter(([, score]) => score > 0) .sort((left, right) => right[1] - left[1]); const topCount = rankedCounts[0]?.[1] ?? 0; const secondCount = rankedCounts[1]?.[1] ?? 0; if (topCount <= 0 || topCount !== secondCount) { return { routeFamily: null, rankingApplied: false }; } const weightedScores = metadataWeightedSurfaceFamilyScores(input.matchedObjects, input.metadataScope); const weightedDominant = selectDominantMetadataRouteFamilyFromScores(weightedScores); return { routeFamily: weightedDominant, rankingApplied: Boolean(weightedDominant) }; } function deriveMetadataSurface(result, metadataScope, requestedMetaTypes, allowScopeRanking) { if (!result || result.error || result.rows.length <= 0) { return null; } const matchedObjects = []; const availableEntitySets = []; for (const row of result.rows) { const objectName = metadataObjectName(row); if (objectName) { pushUnique(matchedObjects, objectName); } const entitySet = metadataEntitySet(row) ?? inferMetadataEntitySetFromObjectName(objectName); if (entitySet) { pushUnique(availableEntitySets, entitySet); } } const grounding = selectMetadataEntityGrounding(availableEntitySets, requestedMetaTypes); const surfaceFamilyScores = metadataSurfaceFamilyScores(matchedObjects); const selectedEntitySetRouteFamily = grounding.selectedEntitySet ? metadataRouteFamilyForEntitySetRelaxed(grounding.selectedEntitySet) : null; const scoredRouteSelection = selectedEntitySetRouteFamily === null ? selectMetadataRouteFamilyFromSurfaceScores({ matchedObjects, metadataScope, countScores: surfaceFamilyScores, allowScopeRanking }) : { routeFamily: null, rankingApplied: false }; const scoredRouteFamily = scoredRouteSelection.routeFamily; const downstreamRouteFamily = selectedEntitySetRouteFamily ?? scoredRouteFamily; const routeFamilySelectionBasis = selectedEntitySetRouteFamily ? "selected_entity_set" : scoredRouteFamily ? "dominant_surface_objects" : null; const selectedSurfaceObjects = grounding.selectedEntitySet !== null ? sortMetadataObjectsByRelevance(metadataObjectsForEntitySet(grounding.selectedEntitySet, matchedObjects), metadataScope) : metadataObjectsForRouteFamily(downstreamRouteFamily, matchedObjects, metadataScope); const knownLimitations = []; const ambiguityRemainsUnresolved = grounding.ambiguityDetected && !downstreamRouteFamily; if (ambiguityRemainsUnresolved && grounding.ambiguityEntitySets.length > 0) { knownLimitations.push(`Exact downstream metadata surface remains ambiguous across: ${grounding.ambiguityEntitySets.join(", ")}`); } if (grounding.ambiguityDetected && downstreamRouteFamily && routeFamilySelectionBasis === "dominant_surface_objects") { knownLimitations.push(`Metadata surface spans multiple object sets, but dominant confirmed objects point to ${downstreamRouteFamily}`); } return { metadata_scope: metadataScope, requested_meta_types: requestedMetaTypes, matched_rows: result.rows.length, available_entity_sets: availableEntitySets, matched_objects: matchedObjects, selected_entity_set: grounding.selectedEntitySet, selected_surface_objects: selectedSurfaceObjects, surface_family_scores: surfaceFamilyScores, downstream_route_family: downstreamRouteFamily, route_family_selection_basis: routeFamilySelectionBasis, recommended_next_primitive: metadataNextPrimitiveForRouteFamily(downstreamRouteFamily), ambiguity_detected: ambiguityRemainsUnresolved, ambiguity_entity_sets: ambiguityRemainsUnresolved ? grounding.ambiguityEntitySets : [], surface_object_ranking_applied: scoredRouteSelection.rankingApplied, available_fields: metadataAvailableFields(result.rows), known_limitations: knownLimitations, inference_basis: "confirmed_1c_metadata_surface_rows" }; } function buildMetadataConfirmedFacts(surface) { if (!surface) { return []; } const facts = []; const scopeSuffix = surface.metadata_scope ? ` for ${surface.metadata_scope}` : ""; facts.push(`Confirmed 1C metadata surface${scopeSuffix}: ${surface.matched_rows} rows and ${surface.matched_objects.length} matching objects`); if (surface.available_entity_sets.length > 0) { facts.push(`Available metadata object sets: ${surface.available_entity_sets.join(", ")}`); } if (surface.selected_entity_set) { facts.push(`Selected metadata entity set: ${surface.selected_entity_set}`); } if (surface.selected_surface_objects.length > 0) { facts.push(`Selected metadata objects: ${surface.selected_surface_objects.slice(0, 8).join(", ")}`); } if (surface.surface_family_scores.document_evidence > 0 || surface.surface_family_scores.movement_evidence > 0 || surface.surface_family_scores.catalog_drilldown > 0) { facts.push(`Metadata surface family scores: document=${surface.surface_family_scores.document_evidence}, movement=${surface.surface_family_scores.movement_evidence}, catalog=${surface.surface_family_scores.catalog_drilldown}`); } if (surface.available_fields.length > 0) { facts.push(`Available metadata fields/sections: ${surface.available_fields.slice(0, 12).join(", ")}`); } return facts; } function buildMetadataInferredFacts(surface) { if (!surface || !surface.downstream_route_family || !surface.recommended_next_primitive) { return []; } return [ `A likely next checked lane may be inferred as ${surface.downstream_route_family} from the confirmed metadata surface` ]; } function buildMetadataUnknownFacts(surface, metadataScope) { if (surface) { if (surface.ambiguity_detected && surface.ambiguity_entity_sets.length > 0) { return [...surface.known_limitations]; } if (surface.available_fields.length > 0) { return []; } return ["Detailed metadata fields were not returned by this MCP metadata probe"]; } if (metadataScope) { return [`No matching 1C metadata objects were confirmed for scope "${metadataScope}"`]; } return ["No matching 1C metadata objects were confirmed by this MCP metadata probe"]; } function buildEntityResolutionConfirmedFacts(resolution) { if (!resolution || resolution.resolution_status !== "resolved" || !resolution.resolved_entity) { return []; } if (resolution.requested_entity && normalizeEntityResolutionText(resolution.requested_entity) === normalizeEntityResolutionText(resolution.resolved_entity)) { return [`В проверенном каталожном срезе 1С найден контрагент: ${resolution.resolved_entity}`]; } return [ `В проверенном каталожном срезе 1С найден наиболее вероятный контрагент: ${resolution.resolved_entity}` ]; } function buildEntityResolutionInferredFacts(resolution) { if (!resolution) { return []; } if (resolution.resolution_status === "resolved") { const facts = ["Пока проверено только заземление сущности по каталогу 1С; документы, движения и денежные показатели еще не проверялись"]; if (resolution.requested_entity && resolution.resolved_entity) { const requestedNormalized = normalizeEntityResolutionText(resolution.requested_entity); const resolvedNormalized = normalizeEntityResolutionText(resolution.resolved_entity); if (requestedNormalized !== resolvedNormalized) { facts.push("Контрагент выбран как ближайшее подтвержденное совпадение имени в проверенном каталоге 1С"); } } return facts; } if (resolution.resolution_status === "ambiguous") { return ["В проверенном каталожном срезе осталось несколько близких кандидатов, поэтому точного контрагента в 1С еще нужно уточнить"]; } return []; } function buildEntityResolutionUnknownFacts(resolution, requestedEntity) { if (!resolution) { return ["По проверенному каталожному поиску 1С не удалось заземлить сущность контрагента"]; } const unknownFacts = ["Документы, движения и денежные показатели по этому контрагенту еще не проверялись; пока был только каталожный поиск"]; if (resolution.resolution_status === "ambiguous" && resolution.ambiguity_candidates.length > 0) { unknownFacts.unshift(`Точное заземление контрагента в 1С остается неоднозначным между вариантами: ${resolution.ambiguity_candidates.join(", ")}`); return unknownFacts; } if (resolution.resolution_status === "not_found") { unknownFacts.unshift(requestedEntity ? `В проверенном каталожном срезе 1С не подтвержден контрагент с именем "${requestedEntity}"` : "В проверенном каталожном срезе 1С не подтвержден подходящий контрагент"); } return unknownFacts; } function rowDateValue(row) { const candidates = [ row["Период"], row["Period"], row["period"], row["Дата"], row["Date"], row["date"] ]; for (const candidate of candidates) { const text = toNonEmptyString(candidate); const match = text?.match(/(\d{4})-(\d{2})-(\d{2})/); if (match) { return `${match[1]}-${match[2]}-${match[3]}`; } } return null; } function rowAmountValue(row) { const candidates = [ row["Сумма"], row["РЎСѓРјРјР°"], row["СуммаДокумента"], row["СуммаДокумента"], row["Amount"], row["amount"], row["Total"], row["total"] ]; for (const candidate of candidates) { if (typeof candidate === "number" && Number.isFinite(candidate)) { return candidate; } const text = toNonEmptyString(candidate); if (!text) { continue; } const normalized = text .replace(/\s+/g, "") .replace(/\u00a0/g, "") .replace(",", ".") .replace(/[^\d.-]/g, ""); const parsed = Number(normalized); if (Number.isFinite(parsed)) { return parsed; } } return null; } function rowNumberValue(row, keys) { for (const key of keys) { const candidate = row[key]; if (typeof candidate === "number" && Number.isFinite(candidate)) { return candidate; } const text = toNonEmptyString(candidate); if (!text) { continue; } const normalized = text .replace(/\s+/g, "") .replace(/\u00a0/g, "") .replace(",", ".") .replace(/[^\d.-]/g, ""); const parsed = Number(normalized); if (Number.isFinite(parsed)) { return parsed; } } return null; } function rowTextValue(row, keys) { for (const key of keys) { const text = toNonEmptyString(row[key]); if (text) { return text; } } return null; } function rowInventoryItemValue(row) { return rowTextValue(row, ["Номенклатура", "Item", "item", "Товар", "Product", "product"]); } function rowWarehouseValue(row) { return rowTextValue(row, ["Склад", "Warehouse", "warehouse"]); } function rowDocumentValue(row) { return rowTextValue(row, ["Регистратор", "Registrator", "registrator", "Документ", "Document", "document"]); } function rowAccountValue(row) { return rowTextValue(row, ["СчетДт", "AccountDt", "account_dt", "Счет", "Account", "account"]); } function rowDebitAccountValue(row) { return rowTextValue(row, ["СчетДт", "AccountDt", "account_dt", "DebitAccount", "debit_account"]); } function rowCreditAccountValue(row) { return rowTextValue(row, ["СчетКт", "AccountKt", "account_kt", "CreditAccount", "credit_account"]); } function accountTextMatchesPrefix(account, prefixes) { const normalized = String(account ?? "").replace(/\s+/g, ""); return prefixes.some((prefix) => normalized.startsWith(prefix)); } function rowQuantityValue(row) { return rowNumberValue(row, ["Количество", "Quantity", "quantity", "Qty", "qty", "Остаток", "Balance", "balance"]); } function rowAnalyticsTextValues(row) { const values = []; const analytics = row["analytics"]; if (Array.isArray(analytics)) { for (const item of analytics) { const text = toNonEmptyString(item); if (text && !values.includes(text)) { values.push(text); } } } for (const key of [ "СубконтоДт1", "СубконтоДт2", "СубконтоДт3", "СубконтоКт1", "СубконтоКт2", "СубконтоКт3", "SubcontoDt1", "SubcontoDt2", "SubcontoDt3", "SubcontoKt1", "SubcontoKt2", "SubcontoKt3" ]) { const text = toNonEmptyString(row[key]); if (text && !values.includes(text)) { values.push(text); } } return values; } function isEmptyAnalyticToken(value) { return /^(?:0|<пусто>|пустая ссылка)$/iu.test(value.trim()); } function isLikelyContractToken(value) { const normalized = value.trim(); if (!normalized || isEmptyAnalyticToken(normalized)) { return false; } if (/(?:договор|contract|дог\.)/iu.test(normalized)) { return true; } if (/^\d{4}-\d{2}-\d{2}/.test(normalized)) { return false; } return normalized.length >= 3 && /[\\/]/.test(normalized); } function isLikelyCounterpartyToken(value) { const normalized = value.trim(); if (!normalized || isEmptyAnalyticToken(normalized)) { return false; } if (/^\d{4}-\d{2}-\d{2}/.test(normalized)) { return false; } if (/^\d+(?:[./-]\d+)*$/.test(normalized)) { return false; } if (!/[a-zа-я]/iu.test(normalized)) { return false; } if (/(?:договор|contract|дог\.|документ|операц|счет[-\s]?фактур|накладн|акт|поступлен|списани|плат[её]ж|банк|касса|movement|invoice|payment)/iu.test(normalized)) { return false; } return true; } function rowContractValue(row) { const explicit = rowTextValue(row, ["Договор", "Contract", "contract"]); if (explicit && !isEmptyAnalyticToken(explicit)) { return explicit; } return rowAnalyticsTextValues(row).find(isLikelyContractToken) ?? null; } function rowCounterpartyValue(row) { const candidates = [row["Контрагент"], row["Counterparty"], row["counterparty"], row["Наименование"], row["name"]]; for (const candidate of candidates) { const text = toNonEmptyString(candidate); if (text) { return text; } } return rowAnalyticsTextValues(row).find(isLikelyCounterpartyToken) ?? null; } function normalizeDateParts(yearText, monthText, dayText) { const year = Number(yearText); const month = Number(monthText); const day = Number(dayText); if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) { return null; } if (year < 1900 || year > 2100 || month < 1 || month > 12 || day < 1 || day > 31) { return null; } const date = new Date(Date.UTC(year, month - 1, day)); if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) { return null; } return [ String(year).padStart(4, "0"), String(month).padStart(2, "0"), String(day).padStart(2, "0") ].join("-"); } function extractContractDateFromText(value) { const text = toNonEmptyString(value); if (!text || !/(?:договор|contract|дог\.)/iu.test(text)) { return null; } const isoLikeMatch = text.match(/(\d{4})[-./](\d{1,2})[-./](\d{1,2})/); if (isoLikeMatch) { return normalizeDateParts(isoLikeMatch[1], isoLikeMatch[2], isoLikeMatch[3]); } const ruDateMatch = text.match(/(\d{1,2})[./-](\d{1,2})[./-](\d{4})/); if (ruDateMatch) { return normalizeDateParts(ruDateMatch[3], ruDateMatch[2], ruDateMatch[1]); } return null; } function earlierIsoDate(left, right) { if (!left) { return right; } if (!right) { return left; } return right < left ? right : left; } function rowOpenSettlementContractStartDateValue(row) { const candidates = [ rowContractValue(row), rowDocumentValue(row), ...rowAnalyticsTextValues(row) ]; for (const candidate of candidates) { const contractDate = extractContractDateFromText(candidate); if (contractDate) { return contractDate; } } return null; } function monthBucketFromIsoDate(isoDate) { const match = isoDate?.match(/^(\d{4})-(\d{2})-\d{2}$/); return match ? `${match[1]}-${match[2]}` : null; } function yearBucketFromIsoDate(isoDate) { const match = isoDate?.match(/^(\d{4})-\d{2}-\d{2}$/); return match ? match[1] : null; } function netDirectionFromAmount(amount) { if (amount > 0) { return "net_incoming"; } if (amount < 0) { return "net_outgoing"; } return "balanced"; } function monthDiff(firstIsoDate, latestIsoDate) { const first = new Date(`${firstIsoDate}T00:00:00.000Z`); const latest = new Date(`${latestIsoDate}T00:00:00.000Z`); if (Number.isNaN(first.getTime()) || Number.isNaN(latest.getTime()) || latest < first) { return 0; } let months = (latest.getUTCFullYear() - first.getUTCFullYear()) * 12; months += latest.getUTCMonth() - first.getUTCMonth(); if (latest.getUTCDate() < first.getUTCDate()) { months -= 1; } return Math.max(0, months); } function formatDurationHumanRu(totalMonths) { const years = Math.floor(totalMonths / 12); const months = totalMonths % 12; const parts = []; if (years > 0) { parts.push(`${years} ${years === 1 ? "год" : years >= 2 && years <= 4 ? "года" : "лет"}`); } if (months > 0) { parts.push(`${months} ${months === 1 ? "месяц" : months >= 2 && months <= 4 ? "месяца" : "месяцев"}`); } return parts.length > 0 ? parts.join(" ") : "меньше месяца"; } function deriveActivityPeriod(result) { if (!result || result.error || result.matched_rows <= 0) { return null; } const dates = result.rows .map((row) => rowDateValue(row)) .filter((value) => Boolean(value)) .sort(); if (dates.length === 0) { return null; } const first = dates[0]; const latest = dates[dates.length - 1]; const totalMonths = monthDiff(first, latest); return { first_activity_date: first, latest_activity_date: latest, matched_rows: result.matched_rows, duration_total_months: totalMonths, duration_years: Math.floor(totalMonths / 12), duration_months_remainder: totalMonths % 12, duration_human_ru: formatDurationHumanRu(totalMonths), inference_basis: "first_and_latest_confirmed_1c_activity_rows" }; } function formatAmountHumanRu(amount) { const formatted = new Intl.NumberFormat("ru-RU", { maximumFractionDigits: 2, minimumFractionDigits: Number.isInteger(amount) ? 0 : 2 }) .format(amount) .replace(/\u00a0/g, " "); return `${formatted} руб.`; } function yearCountHumanRu(count) { const abs = Math.abs(count) % 100; const last = abs % 10; const noun = abs >= 11 && abs <= 14 ? "лет" : last === 1 ? "год" : last >= 2 && last <= 4 ? "года" : "лет"; return `${count} ${noun}`; } function deriveValueFlowMonthBreakdown(result, aggregationAxis) { if (!result || result.error || aggregationAxis !== "month") { return []; } const buckets = new Map(); for (const row of result.rows) { const isoDate = rowDateValue(row); const monthBucket = monthBucketFromIsoDate(isoDate); const amount = rowAmountValue(row); if (!monthBucket || amount === null) { continue; } const current = buckets.get(monthBucket) ?? { rows_with_amount: 0, total_amount: 0 }; current.rows_with_amount += 1; current.total_amount += amount; buckets.set(monthBucket, current); } return Array.from(buckets.entries()) .sort(([left], [right]) => left.localeCompare(right)) .map(([monthBucket, bucket]) => ({ month_bucket: monthBucket, rows_with_amount: bucket.rows_with_amount, total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount) })); } function deriveBidirectionalValueFlowMonthBreakdown(input) { if (input.aggregationAxis !== "month") { return []; } const incomingBuckets = deriveValueFlowMonthBreakdown(input.incomingResult, "month"); const outgoingBuckets = deriveValueFlowMonthBreakdown(input.outgoingResult, "month"); const allMonthBuckets = new Set(); for (const bucket of incomingBuckets) { allMonthBuckets.add(bucket.month_bucket); } for (const bucket of outgoingBuckets) { allMonthBuckets.add(bucket.month_bucket); } const incomingByMonth = new Map(incomingBuckets.map((bucket) => [bucket.month_bucket, bucket])); const outgoingByMonth = new Map(outgoingBuckets.map((bucket) => [bucket.month_bucket, bucket])); return Array.from(allMonthBuckets) .sort((left, right) => left.localeCompare(right)) .map((monthBucket) => { const incoming = incomingByMonth.get(monthBucket); const outgoing = outgoingByMonth.get(monthBucket); const incomingAmount = incoming?.total_amount ?? 0; const outgoingAmount = outgoing?.total_amount ?? 0; const netAmount = incomingAmount - outgoingAmount; return { month_bucket: monthBucket, incoming_total_amount: incomingAmount, incoming_total_amount_human_ru: formatAmountHumanRu(incomingAmount), incoming_rows_with_amount: incoming?.rows_with_amount ?? 0, outgoing_total_amount: outgoingAmount, outgoing_total_amount_human_ru: formatAmountHumanRu(outgoingAmount), outgoing_rows_with_amount: outgoing?.rows_with_amount ?? 0, net_amount: netAmount, net_amount_human_ru: formatAmountHumanRu(Math.abs(netAmount)), net_direction: netDirectionFromAmount(netAmount) }; }); } function deriveBusinessOverviewSideYearBreakdown(result) { if (!result || result.error) { return []; } const buckets = new Map(); for (const row of result.rows) { const yearBucket = yearBucketFromIsoDate(rowDateValue(row)); const amount = rowAmountValue(row); if (!yearBucket || amount === null) { continue; } const current = buckets.get(yearBucket) ?? { rows_with_amount: 0, total_amount: 0 }; current.rows_with_amount += 1; current.total_amount += amount; buckets.set(yearBucket, current); } return Array.from(buckets.entries()) .sort(([left], [right]) => left.localeCompare(right)) .map(([yearBucket, bucket]) => ({ year_bucket: yearBucket, rows_with_amount: bucket.rows_with_amount, total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount) })); } function deriveBusinessOverviewYearlyBreakdown(input) { const incomingBuckets = deriveBusinessOverviewSideYearBreakdown(input.incomingResult); const outgoingBuckets = deriveBusinessOverviewSideYearBreakdown(input.outgoingResult); const allYearBuckets = new Set(); for (const bucket of incomingBuckets) { allYearBuckets.add(bucket.year_bucket); } for (const bucket of outgoingBuckets) { allYearBuckets.add(bucket.year_bucket); } const incomingByYear = new Map(incomingBuckets.map((bucket) => [bucket.year_bucket, bucket])); const outgoingByYear = new Map(outgoingBuckets.map((bucket) => [bucket.year_bucket, bucket])); return Array.from(allYearBuckets) .sort((left, right) => left.localeCompare(right)) .map((yearBucket) => { const incoming = incomingByYear.get(yearBucket); const outgoing = outgoingByYear.get(yearBucket); const incomingAmount = incoming?.total_amount ?? 0; const outgoingAmount = outgoing?.total_amount ?? 0; const netAmount = incomingAmount - outgoingAmount; return { year_bucket: yearBucket, incoming_total_amount: incomingAmount, incoming_total_amount_human_ru: formatAmountHumanRu(incomingAmount), incoming_rows_with_amount: incoming?.rows_with_amount ?? 0, outgoing_total_amount: outgoingAmount, outgoing_total_amount_human_ru: formatAmountHumanRu(outgoingAmount), outgoing_rows_with_amount: outgoing?.rows_with_amount ?? 0, net_amount: netAmount, net_amount_human_ru: formatAmountHumanRu(Math.abs(netAmount)), net_direction: netDirectionFromAmount(netAmount) }; }); } function normalizeBusinessOverviewActivityMarker(row) { const marker = toNonEmptyString(rowDocumentValue(row)); return marker ? marker.trim().toUpperCase() : null; } function normalizeBusinessOverviewAccountSection(value) { const normalized = String(value ?? "").replace(/\s+/g, "").trim(); if (!normalized) { return null; } const sectionMatch = normalized.match(/^(\d{2})(?:[.\-_/]|$)/); return sectionMatch?.[1] ?? normalized; } function deriveBusinessOverviewDocumentActivityProfile(result, periodScope) { if (!result || result.error || result.matched_rows <= 0) { return null; } const documentTypeBuckets = new Map(); const accountSectionBuckets = new Map(); for (const row of result.rows) { const marker = normalizeBusinessOverviewActivityMarker(row); const count = rowAmountValue(row); if (!marker || count === null || count <= 0) { continue; } if (marker === "DOC_TYPE_DOCS") { const documentType = rowDebitAccountValue(row) ?? rowAccountValue(row); if (documentType) { documentTypeBuckets.set(documentType, (documentTypeBuckets.get(documentType) ?? 0) + count); } continue; } if (marker === "SECTION_DT_OPS" || marker === "SECTION_KT_OPS") { const section = normalizeBusinessOverviewAccountSection(rowDebitAccountValue(row) ?? rowAccountValue(row)); if (section) { accountSectionBuckets.set(section, (accountSectionBuckets.get(section) ?? 0) + count); } } } const totalDocumentTypeCount = Array.from(documentTypeBuckets.values()).reduce((sum, count) => sum + count, 0); const totalAccountSectionOperations = Array.from(accountSectionBuckets.values()).reduce((sum, count) => sum + count, 0); const topDocumentTypes = Array.from(documentTypeBuckets.entries()) .map(([documentType, count]) => ({ document_type: documentType, count, share_pct: percentageOfTotal(count, totalDocumentTypeCount) })) .sort((left, right) => right.count - left.count || left.document_type.localeCompare(right.document_type, "ru")) .slice(0, 5); const topAccountSections = Array.from(accountSectionBuckets.entries()) .map(([accountSection, operationCount]) => ({ account_section: accountSection, operation_count: operationCount, share_pct: percentageOfTotal(operationCount, totalAccountSectionOperations) })) .sort((left, right) => right.operation_count - left.operation_count || left.account_section.localeCompare(right.account_section, "ru")) .slice(0, 5); if (topDocumentTypes.length <= 0 && topAccountSections.length <= 0) { return null; } return { period_scope: periodScope, rows_matched: result.matched_rows, total_document_type_count: totalDocumentTypeCount, total_account_section_operations: totalAccountSectionOperations, top_document_types: topDocumentTypes, top_account_sections: topAccountSections, inference_basis: "document_type_and_account_section_profile_confirmed_1c_rows" }; } function sumBusinessOverviewMarker(result, marker) { return result.rows.reduce((sum, row) => { const currentMarker = normalizeBusinessOverviewActivityMarker(row); if (currentMarker !== marker) { return sum; } const amount = rowAmountValue(row); return amount === null ? sum : sum + amount; }, 0); } function deriveBusinessOverviewCounterpartyProfile(result, periodScope) { if (!result || result.error || result.matched_rows <= 0) { return null; } const totalCounterparties = sumBusinessOverviewMarker(result, "CP_TOTAL"); const customerActive = sumBusinessOverviewMarker(result, "CP_CUSTOMER_ACTIVE"); const supplierActive = sumBusinessOverviewMarker(result, "CP_SUPPLIER_ACTIVE"); const mixedActive = sumBusinessOverviewMarker(result, "CP_MIXED_ACTIVE"); const activeUnion = sumBusinessOverviewMarker(result, "CP_ACTIVE_UNION"); const customerOnly = Math.max(0, customerActive - mixedActive); const supplierOnly = Math.max(0, supplierActive - mixedActive); const resolvedActive = customerOnly + supplierOnly + mixedActive; const activeCounterparties = Math.max(activeUnion, resolvedActive); if (totalCounterparties <= 0 && activeCounterparties <= 0) { return null; } return { period_scope: periodScope, rows_matched: result.matched_rows, total_counterparties: totalCounterparties > 0 ? totalCounterparties : null, active_counterparties: activeCounterparties, customer_only_count: customerOnly, supplier_only_count: supplierOnly, mixed_role_count: mixedActive, other_or_inactive_count: totalCounterparties > 0 ? Math.max(0, totalCounterparties - resolvedActive) : null, inference_basis: "counterparty_population_roles_confirmed_1c_rows" }; } function deriveBusinessOverviewContractUsageProfile(result, periodScope) { if (!result || result.error || result.matched_rows <= 0) { return null; } const totalContracts = sumBusinessOverviewMarker(result, "CT_TOTAL"); const usedContracts = sumBusinessOverviewMarker(result, "CT_USED"); if (totalContracts <= 0 && usedContracts <= 0) { return null; } const cappedUsedContracts = totalContracts > 0 ? Math.min(usedContracts, totalContracts) : usedContracts; return { period_scope: periodScope, rows_matched: result.matched_rows, total_contracts: totalContracts > 0 ? totalContracts : null, used_contracts: usedContracts, unused_contracts: totalContracts > 0 ? Math.max(0, totalContracts - cappedUsedContracts) : null, used_contract_share_pct: totalContracts > 0 ? percentageOfTotal(cappedUsedContracts, totalContracts) : null, inference_basis: "contract_usage_overview_confirmed_1c_rows" }; } function deriveValueFlow(result, counterparty, periodScope, direction, aggregationAxis) { if (!result || result.error || result.matched_rows <= 0) { return null; } let totalAmount = 0; let rowsWithAmount = 0; for (const row of result.rows) { const amount = rowAmountValue(row); if (amount !== null) { totalAmount += amount; rowsWithAmount += 1; } } if (rowsWithAmount <= 0) { return null; } const dates = result.rows .map((row) => rowDateValue(row)) .filter((value) => Boolean(value)) .sort(); return { value_flow_direction: direction, counterparty, period_scope: periodScope, aggregation_axis: aggregationAxis, rows_matched: result.matched_rows, rows_with_amount: rowsWithAmount, total_amount: totalAmount, total_amount_human_ru: formatAmountHumanRu(totalAmount), first_movement_date: dates[0] ?? null, latest_movement_date: dates[dates.length - 1] ?? null, coverage_limited_by_probe_limit: result.coverage_limited_by_probe_limit, coverage_recovered_by_period_chunking: result.coverage_recovered_by_period_chunking, period_chunking_granularity: result.period_chunking_granularity, monthly_breakdown: deriveValueFlowMonthBreakdown(result, aggregationAxis), inference_basis: "sum_of_confirmed_1c_value_flow_rows" }; } function deriveRankedValueFlow(result, input) { if (!result || result.error || result.matched_rows <= 0) { return null; } const buckets = new Map(); let rowsWithAmount = 0; for (const row of result.rows) { const axisValue = rowCounterpartyValue(row); const amount = rowAmountValue(row); if (!axisValue || amount === null) { continue; } rowsWithAmount += 1; const current = buckets.get(axisValue) ?? { rows_with_amount: 0, total_amount: 0 }; current.rows_with_amount += 1; current.total_amount += amount; buckets.set(axisValue, current); } if (rowsWithAmount <= 0 || buckets.size <= 0) { return null; } const rankedValues = Array.from(buckets.entries()) .map(([axisValue, bucket]) => ({ axis_value: axisValue, rows_with_amount: bucket.rows_with_amount, total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount) })) .sort((left, right) => { const amountDelta = right.total_amount - left.total_amount; if (input.rankingNeed === "bottom_asc") { if (amountDelta !== 0) { return -amountDelta; } } else if (amountDelta !== 0) { return amountDelta; } return left.axis_value.localeCompare(right.axis_value, "ru"); }) .slice(0, 5); return { value_flow_direction: input.direction, ranking_need: input.rankingNeed, ranking_axis: "counterparty", organization_scope: input.organizationScope, period_scope: input.periodScope, rows_matched: result.matched_rows, rows_with_amount: rowsWithAmount, ranked_values: rankedValues, coverage_limited_by_probe_limit: result.coverage_limited_by_probe_limit, coverage_recovered_by_period_chunking: result.coverage_recovered_by_period_chunking, period_chunking_granularity: result.period_chunking_granularity, inference_basis: "ranked_counterparty_totals_from_confirmed_1c_value_flow_rows" }; } function deriveValueFlowSideSummary(result) { if (!result || result.error || result.matched_rows <= 0) { return { rows_matched: 0, rows_with_amount: 0, total_amount: 0, total_amount_human_ru: formatAmountHumanRu(0), first_movement_date: null, latest_movement_date: null, coverage_limited_by_probe_limit: false, coverage_recovered_by_period_chunking: false, period_chunking_granularity: null }; } let totalAmount = 0; let rowsWithAmount = 0; for (const row of result.rows) { const amount = rowAmountValue(row); if (amount !== null) { totalAmount += amount; rowsWithAmount += 1; } } const dates = result.rows .map((row) => rowDateValue(row)) .filter((value) => Boolean(value)) .sort(); return { rows_matched: result.matched_rows, rows_with_amount: rowsWithAmount, total_amount: totalAmount, total_amount_human_ru: formatAmountHumanRu(totalAmount), first_movement_date: dates[0] ?? null, latest_movement_date: dates[dates.length - 1] ?? null, coverage_limited_by_probe_limit: result.coverage_limited_by_probe_limit, coverage_recovered_by_period_chunking: result.coverage_recovered_by_period_chunking, period_chunking_granularity: result.period_chunking_granularity }; } function deriveBidirectionalValueFlow(input) { const incoming = deriveValueFlowSideSummary(input.incomingResult); const outgoing = deriveValueFlowSideSummary(input.outgoingResult); if (incoming.rows_with_amount <= 0 && outgoing.rows_with_amount <= 0) { return null; } const netAmount = incoming.total_amount - outgoing.total_amount; return { counterparty: input.counterparty, period_scope: input.periodScope, aggregation_axis: input.aggregationAxis, incoming_customer_revenue: incoming, outgoing_supplier_payout: outgoing, net_amount: netAmount, net_amount_human_ru: formatAmountHumanRu(Math.abs(netAmount)), net_direction: netDirectionFromAmount(netAmount), coverage_limited_by_probe_limit: incoming.coverage_limited_by_probe_limit || outgoing.coverage_limited_by_probe_limit, coverage_recovered_by_period_chunking: incoming.coverage_recovered_by_period_chunking || outgoing.coverage_recovered_by_period_chunking, period_chunking_granularity: incoming.period_chunking_granularity ?? outgoing.period_chunking_granularity ?? null, monthly_breakdown: deriveBidirectionalValueFlowMonthBreakdown({ incomingResult: input.incomingResult, outgoingResult: input.outgoingResult, aggregationAxis: input.aggregationAxis }), inference_basis: "incoming_minus_outgoing_confirmed_1c_value_flow_rows" }; } function summarizeBidirectionalValueFlowRows(input) { const incoming = input.incomingResult; const outgoing = input.outgoingResult; if (!incoming && !outgoing) { return null; } const incomingSummary = incoming?.error ? "incoming value-flow query failed" : incoming?.coverage_recovered_by_period_chunking && incoming.period_chunking_granularity === "month" ? `${incoming.period_chunk_count} monthly incoming value-flow probes fetched ${incoming.fetched_rows} rows total, ${incoming.matched_rows} matched` : `${incoming?.fetched_rows ?? 0} incoming value-flow rows fetched, ${incoming?.matched_rows ?? 0} matched`; const outgoingSummary = outgoing?.error ? "outgoing supplier-payout query failed" : outgoing?.coverage_recovered_by_period_chunking && outgoing.period_chunking_granularity === "month" ? `${outgoing.period_chunk_count} monthly outgoing supplier-payout probes fetched ${outgoing.fetched_rows} rows total, ${outgoing.matched_rows} matched` : `${outgoing?.fetched_rows ?? 0} outgoing supplier-payout rows fetched, ${outgoing?.matched_rows ?? 0} matched`; return `${incomingSummary}; ${outgoingSummary}`; } function deriveBusinessOverviewTaxPosition(result, periodScope) { if (!result || result.error || result.matched_rows <= 0 || !periodScope) { return null; } let salesVatAmount = 0; let purchaseVatAmount = 0; let rowsWithAmount = 0; for (const row of result.rows) { const amount = rowAmountValue(row); if (amount === null) { continue; } const marker = String(rowDocumentValue(row) ?? "").toLowerCase(); const account = String(rowAccountValue(row) ?? "").toLowerCase(); if (marker.includes("sales") || marker.includes("продаж") || account.startsWith("68")) { salesVatAmount += amount; rowsWithAmount += 1; continue; } if (marker.includes("purchase") || marker.includes("покуп") || account.startsWith("19")) { purchaseVatAmount += amount; rowsWithAmount += 1; } } if (rowsWithAmount <= 0) { return null; } const netVatAmount = salesVatAmount - purchaseVatAmount; const netVatDirection = netVatAmount > 0 ? "vat_to_pay" : netVatAmount < 0 ? "vat_to_recover_or_offset" : "balanced"; return { period_scope: periodScope, rows_matched: result.matched_rows, rows_with_amount: rowsWithAmount, sales_vat_amount: salesVatAmount, sales_vat_amount_human_ru: formatAmountHumanRu(salesVatAmount), purchase_vat_amount: purchaseVatAmount, purchase_vat_amount_human_ru: formatAmountHumanRu(purchaseVatAmount), net_vat_amount: netVatAmount, net_vat_amount_human_ru: formatAmountHumanRu(Math.abs(netVatAmount)), net_vat_direction: netVatDirection, inference_basis: "sales_book_minus_purchase_book_confirmed_1c_vat_rows" }; } function deriveBusinessOverviewTradingMarginProxy(result, periodScope) { if (!result || result.error || result.matched_rows <= 0 || !periodScope) { return null; } const itemBuckets = new Map(); let salesRowsWithAmount = 0; let purchaseRowsWithAmount = 0; let salesRevenue = 0; let purchaseCostProxy = 0; for (const row of result.rows) { const amount = rowAmountValue(row); if (amount === null || amount <= 0) { continue; } const isSale = accountTextMatchesPrefix(rowCreditAccountValue(row), ["41.01"]); const isPurchase = accountTextMatchesPrefix(rowDebitAccountValue(row), ["41.01"]); if (!isSale && !isPurchase) { continue; } const item = rowInventoryItemValue(row) ?? "unknown_item"; const quantity = rowQuantityValue(row) ?? 0; const bucket = itemBuckets.get(item) ?? { sales_revenue: 0, purchase_cost_proxy: 0, sales_quantity: 0, purchase_quantity: 0 }; if (isSale) { salesRowsWithAmount += 1; salesRevenue += amount; bucket.sales_revenue += amount; bucket.sales_quantity += quantity; } if (isPurchase) { purchaseRowsWithAmount += 1; purchaseCostProxy += amount; bucket.purchase_cost_proxy += amount; bucket.purchase_quantity += quantity; } itemBuckets.set(item, bucket); } if (salesRowsWithAmount <= 0 && purchaseRowsWithAmount <= 0) { return null; } const grossSpreadProxy = salesRevenue - purchaseCostProxy; const marginToRevenuePct = salesRevenue > 0 ? percentageOfTotal(grossSpreadProxy, salesRevenue) : null; const markupToPurchasePct = purchaseCostProxy > 0 ? percentageOfTotal(grossSpreadProxy, purchaseCostProxy) : null; const topItemsBySales = Array.from(itemBuckets.entries()) .map(([item, bucket]) => ({ item, sales_revenue: bucket.sales_revenue, sales_revenue_human_ru: formatAmountHumanRu(bucket.sales_revenue), purchase_cost_proxy: bucket.purchase_cost_proxy, purchase_cost_proxy_human_ru: formatAmountHumanRu(bucket.purchase_cost_proxy), gross_spread_proxy: bucket.sales_revenue - bucket.purchase_cost_proxy, gross_spread_proxy_human_ru: formatAmountHumanRu(bucket.sales_revenue - bucket.purchase_cost_proxy), sales_quantity: bucket.sales_quantity, purchase_quantity: bucket.purchase_quantity })) .sort((left, right) => { const salesDelta = right.sales_revenue - left.sales_revenue; return salesDelta !== 0 ? salesDelta : left.item.localeCompare(right.item, "ru"); }) .slice(0, 5); return { period_scope: periodScope, rows_matched: result.matched_rows, sales_rows_with_amount: salesRowsWithAmount, purchase_rows_with_amount: purchaseRowsWithAmount, sales_revenue: salesRevenue, sales_revenue_human_ru: formatAmountHumanRu(salesRevenue), purchase_cost_proxy: purchaseCostProxy, purchase_cost_proxy_human_ru: formatAmountHumanRu(purchaseCostProxy), gross_spread_proxy: grossSpreadProxy, gross_spread_proxy_human_ru: formatAmountHumanRu(grossSpreadProxy), margin_to_revenue_pct: marginToRevenuePct, markup_to_purchase_pct: markupToPurchasePct, top_items_by_sales: topItemsBySales, inference_basis: "sales_documents_minus_purchase_documents_confirmed_1c_rows" }; } function deriveBusinessOverviewDebtSide(result) { if (!result || result.error || result.matched_rows <= 0) { return { rows_matched: 0, rows_with_amount: 0, total_amount: 0, total_amount_human_ru: formatAmountHumanRu(0), top_counterparties: [] }; } const buckets = new Map(); let rowsWithAmount = 0; let totalAmount = 0; for (const row of result.rows) { const amount = rowAmountValue(row); if (amount === null) { continue; } rowsWithAmount += 1; totalAmount += amount; const counterparty = rowCounterpartyValue(row) ?? "unknown_counterparty"; const current = buckets.get(counterparty) ?? { rows_with_amount: 0, total_amount: 0 }; current.rows_with_amount += 1; current.total_amount += amount; buckets.set(counterparty, current); } const topCounterparties = Array.from(buckets.entries()) .map(([axisValue, bucket]) => ({ axis_value: axisValue, rows_with_amount: bucket.rows_with_amount, total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount) })) .sort((left, right) => { const amountDelta = right.total_amount - left.total_amount; return amountDelta !== 0 ? amountDelta : left.axis_value.localeCompare(right.axis_value, "ru"); }) .slice(0, 5); return { rows_matched: result.matched_rows, rows_with_amount: rowsWithAmount, total_amount: totalAmount, total_amount_human_ru: formatAmountHumanRu(totalAmount), top_counterparties: topCounterparties }; } function deriveBusinessOverviewDebtPosition(input) { if (!input.debtAsOfDate) { return null; } const receivables = deriveBusinessOverviewDebtSide(input.receivablesResult); const payables = deriveBusinessOverviewDebtSide(input.payablesResult); if (receivables.rows_with_amount <= 0 && payables.rows_with_amount <= 0) { return null; } const netDebtPositionAmount = receivables.total_amount - payables.total_amount; const netDebtPositionDirection = netDebtPositionAmount > 0 ? "net_receivable" : netDebtPositionAmount < 0 ? "net_payable" : "balanced"; return { as_of_date: input.debtAsOfDate, receivables, payables, net_debt_position_amount: netDebtPositionAmount, net_debt_position_amount_human_ru: formatAmountHumanRu(Math.abs(netDebtPositionAmount)), net_debt_position_direction: netDebtPositionDirection, inference_basis: "receivables_minus_payables_confirmed_1c_balance_rows" }; } function percentageOfTotal(part, total) { if (!Number.isFinite(part) || !Number.isFinite(total) || total <= 0) { return null; } return Math.round((part / total) * 10_000) / 100; } function ratioOfTotal(part, total) { if (!Number.isFinite(part) || !Number.isFinite(total) || total <= 0) { return null; } return Math.round((part / total) * 100) / 100; } function deriveBusinessOverviewDebtOpenSettlementQuality(input) { if (!input.debtAsOfDate || !input.openContractsResult || input.openContractsResult.error || input.openContractsResult.matched_rows <= 0) { return null; } const debtAsOfDate = input.debtAsOfDate; const counterpartyBuckets = new Map(); const contractBuckets = new Map(); const counterparties = new Set(); const contracts = new Set(); let rowsWithAmount = 0; let grossOpenAmount = 0; let rowsWithoutCounterparty = 0; let rowsWithoutContract = 0; for (const row of input.openContractsResult.rows) { const amount = rowAmountValue(row); if (amount === null) { continue; } const absAmount = Math.abs(amount); if (absAmount <= 0) { continue; } rowsWithAmount += 1; grossOpenAmount += absAmount; const counterparty = rowCounterpartyValue(row); const contract = rowContractValue(row); if (counterparty) { counterparties.add(counterparty); const current = counterpartyBuckets.get(counterparty) ?? { rows_with_amount: 0, total_amount: 0 }; current.rows_with_amount += 1; current.total_amount += absAmount; counterpartyBuckets.set(counterparty, current); } else { rowsWithoutCounterparty += 1; } if (contract) { const contractStartDate = rowOpenSettlementContractStartDateValue(row); contracts.add(contract); const current = contractBuckets.get(contract) ?? { counterparty, contract_start_date: contractStartDate, rows_with_amount: 0, total_amount: 0 }; if (!current.counterparty && counterparty) { current.counterparty = counterparty; } current.contract_start_date = earlierIsoDate(current.contract_start_date, contractStartDate); current.rows_with_amount += 1; current.total_amount += absAmount; contractBuckets.set(contract, current); } else { rowsWithoutContract += 1; } } if (rowsWithAmount <= 0) { return null; } const topCounterparties = Array.from(counterpartyBuckets.entries()) .map(([axisValue, bucket]) => ({ axis_value: axisValue, rows_with_amount: bucket.rows_with_amount, total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount) })) .sort((left, right) => { const amountDelta = right.total_amount - left.total_amount; return amountDelta !== 0 ? amountDelta : left.axis_value.localeCompare(right.axis_value, "ru"); }) .slice(0, 5); const topContracts = Array.from(contractBuckets.entries()) .map(([contract, bucket]) => ({ contract, counterparty: bucket.counterparty, contract_start_date: bucket.contract_start_date, rows_with_amount: bucket.rows_with_amount, total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount), share_of_gross_open_amount_pct: percentageOfTotal(bucket.total_amount, grossOpenAmount) })) .sort((left, right) => { const amountDelta = right.total_amount - left.total_amount; return amountDelta !== 0 ? amountDelta : left.contract.localeCompare(right.contract, "ru"); }) .slice(0, 5); const agedContractBuckets = Array.from(contractBuckets.entries()) .map(([contract, bucket]) => { if (!bucket.contract_start_date) { return null; } return { contract, counterparty: bucket.counterparty, start_date: bucket.contract_start_date, age_days: daysBetweenIsoDates(bucket.contract_start_date, debtAsOfDate), total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount), share_of_gross_open_amount_pct: percentageOfTotal(bucket.total_amount, grossOpenAmount) }; }) .filter((item) => Boolean(item)) .sort((left, right) => { const leftAge = left.age_days ?? -1; const rightAge = right.age_days ?? -1; const ageDelta = rightAge - leftAge; if (ageDelta !== 0) { return ageDelta; } const amountDelta = right.total_amount - left.total_amount; return amountDelta !== 0 ? amountDelta : left.contract.localeCompare(right.contract, "ru"); }); const debtAgeDates = agedContractBuckets.map((bucket) => bucket.start_date).sort(); const maxAgeDays = agedContractBuckets.reduce((max, bucket) => { if (bucket.age_days === null) { return max; } return max === null ? bucket.age_days : Math.max(max, bucket.age_days); }, null); const ageSignal = agedContractBuckets.length > 0 ? { contracts_with_start_date: agedContractBuckets.length, oldest_start_date: debtAgeDates[0] ?? null, latest_start_date: debtAgeDates[debtAgeDates.length - 1] ?? null, max_age_days: maxAgeDays, top_aged_contracts: agedContractBuckets.slice(0, 5), inference_basis: "contract_dates_from_open_settlement_rows" } : null; return { as_of_date: debtAsOfDate, rows_matched: input.openContractsResult.matched_rows, rows_with_amount: rowsWithAmount, gross_open_amount: grossOpenAmount, gross_open_amount_human_ru: formatAmountHumanRu(grossOpenAmount), unique_counterparties: counterparties.size, unique_contracts: contracts.size, rows_without_counterparty: rowsWithoutCounterparty, rows_without_contract: rowsWithoutContract, top_counterparties: topCounterparties, top_contracts: topContracts, concentration_top_counterparty_pct: percentageOfTotal(topCounterparties[0]?.total_amount ?? 0, grossOpenAmount), concentration_top_contract_pct: percentageOfTotal(topContracts[0]?.total_amount ?? 0, grossOpenAmount), age_signal: ageSignal, inference_basis: "open_contracts_confirmed_1c_balance_rows" }; } function debtStalenessRiskBand(input) { if (input.maxContractAgeDays >= 365 && input.topContractSharePct >= 50) { return "high"; } if (input.maxContractAgeDays >= 365 || input.topContractSharePct >= 50) { return "elevated"; } if (input.maxContractAgeDays >= 180 || input.topContractSharePct >= 35) { return "watch"; } return "lower_visible_risk"; } function deriveBusinessOverviewDebtStalenessRiskProxy(quality) { const ageSignal = quality?.age_signal; const topAgedContract = ageSignal?.top_aged_contracts[0]; const topContractSharePct = topAgedContract?.share_of_gross_open_amount_pct; if (!quality || !ageSignal?.oldest_start_date || ageSignal.max_age_days === null || ageSignal.max_age_days === undefined || !topAgedContract || topContractSharePct === null || topContractSharePct === undefined) { return null; } return { as_of_date: quality.as_of_date, gross_open_amount: quality.gross_open_amount, gross_open_amount_human_ru: quality.gross_open_amount_human_ru, oldest_contract_start_date: ageSignal.oldest_start_date, max_contract_age_days: ageSignal.max_age_days, top_contract: topAgedContract.contract, top_contract_counterparty: topAgedContract.counterparty, top_contract_amount: topAgedContract.total_amount, top_contract_amount_human_ru: topAgedContract.total_amount_human_ru, top_contract_share_pct: topContractSharePct, risk_band: debtStalenessRiskBand({ maxContractAgeDays: ageSignal.max_age_days, topContractSharePct }), inference_basis: "contract_date_age_and_open_balance_concentration_confirmed_1c_rows" }; } function debtStalenessRiskBandRu(riskBand) { if (riskBand === "high") { return "высокая зона внимания"; } if (riskBand === "elevated") { return "повышенная зона внимания"; } if (riskBand === "watch") { return "зона наблюдения"; } return "низкий видимый риск"; } function daysBetweenIsoDates(leftIsoDate, rightIsoDate) { const leftMatch = leftIsoDate.match(/^(\d{4})-(\d{2})-(\d{2})$/); const rightMatch = rightIsoDate.match(/^(\d{4})-(\d{2})-(\d{2})$/); if (!leftMatch || !rightMatch) { return null; } const left = Date.UTC(Number(leftMatch[1]), Number(leftMatch[2]) - 1, Number(leftMatch[3])); const right = Date.UTC(Number(rightMatch[1]), Number(rightMatch[2]) - 1, Number(rightMatch[3])); if (!Number.isFinite(left) || !Number.isFinite(right)) { return null; } return Math.max(0, Math.floor((right - left) / 86_400_000)); } function deriveBusinessOverviewInventoryAgingSignal(result, inventoryAsOfDate) { if (!result || result.error || result.matched_rows <= 0) { return null; } const dates = result.rows .map((row) => rowDateValue(row)) .filter((value) => Boolean(value)) .sort((left, right) => left.localeCompare(right)); if (dates.length <= 0) { return null; } const oldestPurchaseDate = dates[0] ?? null; const latestPurchaseDate = dates[dates.length - 1] ?? null; return { rows_matched: result.matched_rows, rows_with_purchase_date: dates.length, oldest_purchase_date: oldestPurchaseDate, latest_purchase_date: latestPurchaseDate, max_age_days: oldestPurchaseDate ? daysBetweenIsoDates(oldestPurchaseDate, inventoryAsOfDate) : null, inference_basis: "inventory_purchase_dates_from_confirmed_1c_rows" }; } function deriveBusinessOverviewInventoryPosition(input) { const { inventoryAsOfDate, inventoryOnHandResult } = input; if (!inventoryAsOfDate || !inventoryOnHandResult || inventoryOnHandResult.error || inventoryOnHandResult.matched_rows <= 0) { return null; } const buckets = new Map(); let rowsWithAmount = 0; let rowsWithQuantity = 0; let totalAmount = 0; let totalQuantity = 0; for (const row of inventoryOnHandResult.rows) { const amount = rowAmountValue(row); const quantity = rowQuantityValue(row); if (amount === null && quantity === null) { continue; } const item = rowInventoryItemValue(row) ?? "unknown_item"; const current = buckets.get(item) ?? { rows_with_amount: 0, rows_with_quantity: 0, total_amount: 0, total_quantity: 0 }; if (amount !== null) { rowsWithAmount += 1; totalAmount += amount; current.rows_with_amount += 1; current.total_amount += amount; } if (quantity !== null) { rowsWithQuantity += 1; totalQuantity += quantity; current.rows_with_quantity += 1; current.total_quantity += quantity; } buckets.set(item, current); } if (rowsWithAmount <= 0 && rowsWithQuantity <= 0) { return null; } const topItems = Array.from(buckets.entries()) .map(([item, bucket]) => ({ item, rows_with_amount: bucket.rows_with_amount, rows_with_quantity: bucket.rows_with_quantity, total_amount: bucket.total_amount, total_amount_human_ru: formatAmountHumanRu(bucket.total_amount), total_quantity: bucket.total_quantity })) .sort((left, right) => { const amountDelta = right.total_amount - left.total_amount; if (amountDelta !== 0) { return amountDelta; } const quantityDelta = right.total_quantity - left.total_quantity; return quantityDelta !== 0 ? quantityDelta : left.item.localeCompare(right.item, "ru"); }) .slice(0, 5); return { as_of_date: inventoryAsOfDate, rows_matched: inventoryOnHandResult.matched_rows, rows_with_amount: rowsWithAmount, rows_with_quantity: rowsWithQuantity, total_amount: totalAmount, total_amount_human_ru: formatAmountHumanRu(totalAmount), total_quantity: totalQuantity, top_items: topItems, aging_signal: deriveBusinessOverviewInventoryAgingSignal(input.inventoryAgingResult, inventoryAsOfDate), inference_basis: "inventory_on_hand_confirmed_1c_balance_rows" }; } function deriveBusinessOverviewInventoryTurnoverProxy(input) { const { inventoryPosition, tradingMarginProxy } = input; if (!inventoryPosition || !tradingMarginProxy) { return null; } if (inventoryPosition.total_amount <= 0 || tradingMarginProxy.sales_revenue <= 0) { return null; } return { period_scope: tradingMarginProxy.period_scope, as_of_date: inventoryPosition.as_of_date, sales_revenue: tradingMarginProxy.sales_revenue, sales_revenue_human_ru: tradingMarginProxy.sales_revenue_human_ru, inventory_amount: inventoryPosition.total_amount, inventory_amount_human_ru: inventoryPosition.total_amount_human_ru, sales_to_stock_amount_ratio: ratioOfTotal(tradingMarginProxy.sales_revenue, inventoryPosition.total_amount), stock_to_sales_revenue_pct: percentageOfTotal(inventoryPosition.total_amount, tradingMarginProxy.sales_revenue), inference_basis: "sales_document_revenue_vs_inventory_balance_confirmed_1c_rows" }; } function inventoryStalenessRiskBand(input) { if (input.maxPurchaseAgeDays >= 365 && input.salesToStockAmountRatio < 1) { return "high"; } if (input.maxPurchaseAgeDays >= 365 || input.salesToStockAmountRatio < 1) { return "elevated"; } if (input.maxPurchaseAgeDays >= 180 || input.salesToStockAmountRatio < 2) { return "watch"; } return "lower_visible_risk"; } function deriveBusinessOverviewInventoryStalenessRiskProxy(input) { const { inventoryPosition, inventoryTurnoverProxy } = input; const maxPurchaseAgeDays = inventoryPosition?.aging_signal?.max_age_days; const oldestPurchaseDate = inventoryPosition?.aging_signal?.oldest_purchase_date; const salesToStockAmountRatio = inventoryTurnoverProxy?.sales_to_stock_amount_ratio; if (!inventoryPosition || !inventoryTurnoverProxy || !oldestPurchaseDate || maxPurchaseAgeDays === null || maxPurchaseAgeDays === undefined || salesToStockAmountRatio === null || salesToStockAmountRatio === undefined) { return null; } return { as_of_date: inventoryPosition.as_of_date, period_scope: inventoryTurnoverProxy.period_scope, oldest_purchase_date: oldestPurchaseDate, max_purchase_age_days: maxPurchaseAgeDays, sales_to_stock_amount_ratio: salesToStockAmountRatio, risk_band: inventoryStalenessRiskBand({ maxPurchaseAgeDays, salesToStockAmountRatio }), inference_basis: "purchase_date_age_and_sales_to_stock_proxy_confirmed_1c_rows" }; } function inventoryStalenessRiskBandRu(riskBand) { if (riskBand === "high") { return "высокая зона внимания"; } if (riskBand === "elevated") { return "повышенная зона внимания"; } if (riskBand === "watch") { return "зона наблюдения"; } return "низкий видимый риск"; } function deriveBusinessOverview(input) { const incoming = deriveValueFlowSideSummary(input.incomingResult); const outgoing = deriveValueFlowSideSummary(input.outgoingResult); const rankedIncoming = deriveRankedValueFlow(input.incomingResult, { organizationScope: input.organizationScope, periodScope: input.periodScope, direction: "incoming_customer_revenue", rankingNeed: "top_desc" }); const rankedOutgoing = deriveRankedValueFlow(input.outgoingResult, { organizationScope: input.organizationScope, periodScope: input.periodScope, direction: "outgoing_supplier_payout", rankingNeed: "top_desc" }); const yearlyBreakdown = deriveBusinessOverviewYearlyBreakdown({ incomingResult: input.incomingResult, outgoingResult: input.outgoingResult }); const activityPeriod = deriveActivityPeriod(input.lifecycleResult); const taxPosition = deriveBusinessOverviewTaxPosition(input.taxResult, input.periodScope); const tradingMarginProxy = deriveBusinessOverviewTradingMarginProxy(input.tradingMarginResult, input.periodScope); const debtPosition = deriveBusinessOverviewDebtPosition({ receivablesResult: input.receivablesResult, payablesResult: input.payablesResult, debtAsOfDate: input.debtAsOfDate }); const debtOpenSettlementQuality = deriveBusinessOverviewDebtOpenSettlementQuality({ openContractsResult: input.openContractsResult, debtAsOfDate: input.debtAsOfDate }); const documentActivityProfile = deriveBusinessOverviewDocumentActivityProfile(input.documentActivityProfileResult, input.periodScope); const counterpartyProfile = deriveBusinessOverviewCounterpartyProfile(input.counterpartyProfileResult, input.periodScope); const contractUsageProfile = deriveBusinessOverviewContractUsageProfile(input.contractUsageProfileResult, input.periodScope); const debtStalenessRiskProxy = deriveBusinessOverviewDebtStalenessRiskProxy(debtOpenSettlementQuality); const inventoryPosition = deriveBusinessOverviewInventoryPosition({ inventoryOnHandResult: input.inventoryOnHandResult, inventoryAgingResult: input.inventoryAgingResult, inventoryAsOfDate: input.inventoryAsOfDate }); const inventoryTurnoverProxy = deriveBusinessOverviewInventoryTurnoverProxy({ inventoryPosition, tradingMarginProxy }); const inventoryStalenessRiskProxy = deriveBusinessOverviewInventoryStalenessRiskProxy({ inventoryPosition, inventoryTurnoverProxy }); const checkedSignalCount = [ incoming.rows_with_amount > 0, outgoing.rows_with_amount > 0, Boolean(activityPeriod), Boolean(taxPosition), Boolean(tradingMarginProxy), Boolean(debtPosition), Boolean(debtOpenSettlementQuality), Boolean(debtStalenessRiskProxy), Boolean(documentActivityProfile), Boolean(counterpartyProfile), Boolean(contractUsageProfile), Boolean(inventoryPosition), Boolean(inventoryTurnoverProxy), Boolean(inventoryStalenessRiskProxy) ].filter(Boolean).length; if (checkedSignalCount <= 0) { return null; } const netAmount = incoming.total_amount - outgoing.total_amount; const hasBusinessOverviewProfileSignal = Boolean(documentActivityProfile || counterpartyProfile || contractUsageProfile); return { organization_scope: input.organizationScope, period_scope: input.periodScope, incoming_customer_revenue: incoming, outgoing_supplier_payout: outgoing, net_amount: netAmount, net_amount_human_ru: formatAmountHumanRu(Math.abs(netAmount)), net_direction: netDirectionFromAmount(netAmount), top_customers: rankedIncoming?.ranked_values ?? [], top_suppliers: rankedOutgoing?.ranked_values ?? [], yearly_breakdown: yearlyBreakdown, activity_period: activityPeriod, tax_position: taxPosition, trading_margin_proxy: tradingMarginProxy, debt_position: debtPosition, debt_open_settlement_quality: debtOpenSettlementQuality, debt_staleness_risk_proxy: debtStalenessRiskProxy, inventory_position: inventoryPosition, inventory_turnover_proxy: inventoryTurnoverProxy, inventory_staleness_risk_proxy: inventoryStalenessRiskProxy, document_activity_profile: documentActivityProfile, counterparty_profile: counterpartyProfile, contract_usage_profile: contractUsageProfile, coverage_limited_by_probe_limit: incoming.coverage_limited_by_probe_limit || outgoing.coverage_limited_by_probe_limit, checked_signal_count: checkedSignalCount, missing_signal_families: [ tradingMarginProxy ? "accounting_profit_margin" : "profit_margin", debtPosition ? null : "debt_position", debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality", taxPosition ? null : "tax_position", inventoryPosition ? inventoryStalenessRiskProxy ? "inventory_reserve_liquidation_quality" : inventoryTurnoverProxy ? "inventory_liquidity_quality" : "inventory_turnover_quality" : "inventory_position", inventoryPosition?.aging_signal ? null : "inventory_aging_quality" ].filter((item) => Boolean(item)), inference_basis: hasBusinessOverviewProfileSignal || inventoryPosition ? "business_overview_from_confirmed_1c_multi_family_rows" : debtOpenSettlementQuality ? "business_overview_from_confirmed_1c_multi_family_rows" : taxPosition && debtPosition ? "business_overview_from_confirmed_1c_money_activity_tax_and_debt_rows" : taxPosition ? "business_overview_from_confirmed_1c_money_activity_and_tax_rows" : debtPosition ? "business_overview_from_confirmed_1c_money_activity_and_debt_rows" : "business_overview_from_confirmed_1c_money_and_activity_rows" }; } function summarizeBusinessOverviewRows(input) { const parts = []; if (input.incomingResult && !input.incomingResult.error) { parts.push(`${input.incomingResult.fetched_rows} incoming rows fetched, ${input.incomingResult.matched_rows} matched`); } if (input.outgoingResult && !input.outgoingResult.error) { parts.push(`${input.outgoingResult.fetched_rows} outgoing rows fetched, ${input.outgoingResult.matched_rows} matched`); } if (input.lifecycleResult && !input.lifecycleResult.error) { parts.push(`${input.lifecycleResult.fetched_rows} activity/document rows fetched, ${input.lifecycleResult.matched_rows} matched`); } if (input.taxResult && !input.taxResult.error) { parts.push(`${input.taxResult.fetched_rows} VAT/tax rows fetched, ${input.taxResult.matched_rows} matched`); } if (input.tradingMarginResult && !input.tradingMarginResult.error) { parts.push(`${input.tradingMarginResult.fetched_rows} trading-margin document rows fetched, ${input.tradingMarginResult.matched_rows} matched`); } if (input.receivablesResult && !input.receivablesResult.error) { parts.push(`${input.receivablesResult.fetched_rows} receivables rows fetched, ${input.receivablesResult.matched_rows} matched`); } if (input.payablesResult && !input.payablesResult.error) { parts.push(`${input.payablesResult.fetched_rows} payables rows fetched, ${input.payablesResult.matched_rows} matched`); } if (input.openContractsResult && !input.openContractsResult.error) { parts.push(`${input.openContractsResult.fetched_rows} open-contract rows fetched, ${input.openContractsResult.matched_rows} matched`); } if (input.documentActivityProfileResult && !input.documentActivityProfileResult.error) { parts.push(`${input.documentActivityProfileResult.fetched_rows} document/account-section profile rows fetched, ${input.documentActivityProfileResult.matched_rows} matched`); } if (input.counterpartyProfileResult && !input.counterpartyProfileResult.error) { parts.push(`${input.counterpartyProfileResult.fetched_rows} counterparty role-profile rows fetched, ${input.counterpartyProfileResult.matched_rows} matched`); } if (input.contractUsageProfileResult && !input.contractUsageProfileResult.error) { parts.push(`${input.contractUsageProfileResult.fetched_rows} contract-usage profile rows fetched, ${input.contractUsageProfileResult.matched_rows} matched`); } if (input.inventoryOnHandResult && !input.inventoryOnHandResult.error) { parts.push(`${input.inventoryOnHandResult.fetched_rows} inventory on-hand rows fetched, ${input.inventoryOnHandResult.matched_rows} matched`); } if (input.inventoryAgingResult && !input.inventoryAgingResult.error) { parts.push(`${input.inventoryAgingResult.fetched_rows} inventory aging rows fetched, ${input.inventoryAgingResult.matched_rows} matched`); } return parts.length > 0 ? parts.join("; ") : null; } function buildBusinessOverviewConfirmedFacts(derived) { if (!derived) { return []; } const facts = []; const organization = derived.organization_scope ? ` по организации ${derived.organization_scope}` : ""; const period = derived.period_scope ? ` за ${derived.period_scope}` : " за все доступное проверенное окно"; if (derived.incoming_customer_revenue.rows_with_amount > 0) { facts.push(`В 1С подтверждены входящие поступления${organization}${period}: ${derived.incoming_customer_revenue.total_amount_human_ru} по ${derived.incoming_customer_revenue.rows_with_amount} строкам с суммой.`); } if (derived.outgoing_supplier_payout.rows_with_amount > 0) { facts.push(`В 1С подтверждены исходящие платежи/списания${organization}${period}: ${derived.outgoing_supplier_payout.total_amount_human_ru} по ${derived.outgoing_supplier_payout.rows_with_amount} строкам с суммой.`); } if (derived.top_customers.length > 0) { const leader = derived.top_customers[0]; facts.push(`Самый крупный подтвержденный клиент в проверенном срезе: ${leader.axis_value} — ${leader.total_amount_human_ru}.`); } if (derived.top_suppliers.length > 0) { const leader = derived.top_suppliers[0]; facts.push(`Самый крупный подтвержденный поставщик/получатель исходящих платежей в проверенном срезе: ${leader.axis_value} — ${leader.total_amount_human_ru}.`); } if (derived.yearly_breakdown.length > 0) { facts.push(`Годовая раскладка операционного денежного потока построена по подтвержденным строкам 1С за ${yearCountHumanRu(derived.yearly_breakdown.length)}.`); } if (derived.activity_period) { facts.push(`Подтвержденное окно активности в 1С: ${derived.activity_period.first_activity_date} — ${derived.activity_period.latest_activity_date}.`); } if (derived.document_activity_profile) { const profile = derived.document_activity_profile; const topDocument = profile.top_document_types[0]; const topSection = profile.top_account_sections[0]; const parts = []; if (topDocument) { const shareText = topDocument.share_pct === null ? "" : ` (${topDocument.share_pct}%)`; parts.push(`ведущий тип документов ${topDocument.document_type} — ${topDocument.count} документов${shareText}`); } if (topSection) { const shareText = topSection.share_pct === null ? "" : ` (${topSection.share_pct}%)`; parts.push(`ведущий раздел учета ${topSection.account_section} — ${topSection.operation_count} операций${shareText}`); } if (parts.length > 0) { facts.push(`Профиль операционной активности${organization}${period} подтвержден по типам документов и разделам учета 1С: ${parts.join("; ")}. Это activity mix, а не аудит качества учета или полноты бизнес-процессов.`); } } if (derived.counterparty_profile) { const profile = derived.counterparty_profile; const totalText = profile.total_counterparties === null ? `${profile.active_counterparties} активных контрагентов` : `${profile.total_counterparties} контрагентов в базе, ${profile.active_counterparties} активных по документальной активности`; facts.push(`Профиль контрагентской базы${organization}${period} подтвержден по 1С: ${totalText}; заказчики ${profile.customer_only_count}, поставщики ${profile.supplier_only_count}, смешанная роль ${profile.mixed_role_count}. Это не CRM-аудит, не юридическая проверка контрагентов и не оценка качества клиентской базы.`); } if (derived.contract_usage_profile) { const profile = derived.contract_usage_profile; const totalText = profile.total_contracts === null ? `${profile.used_contracts} договоров с подтвержденной связью с операциями` : `${profile.used_contracts} из ${profile.total_contracts} договоров используются${profile.used_contract_share_pct === null ? "" : ` (${profile.used_contract_share_pct}%)`}`; const unusedText = profile.unused_contracts === null ? "" : `, неиспользуемых ${profile.unused_contracts}`; facts.push(`Договорной профиль${organization}${period} подтвержден по 1С: ${totalText}${unusedText}. Это не contract-risk аудит, не проверка актуальности условий и не доказательство качества договорной базы.`); } if (derived.tax_position) { const taxDirection = derived.tax_position.net_vat_direction === "vat_to_pay" ? "к уплате" : derived.tax_position.net_vat_direction === "vat_to_recover_or_offset" ? "к вычету/зачету" : "сбалансирован"; facts.push(`НДС-позиция за ${derived.tax_position.period_scope} подтверждена по книгам продаж/покупок: продажи ${derived.tax_position.sales_vat_amount_human_ru}, покупки/вычеты ${derived.tax_position.purchase_vat_amount_human_ru}, нетто ${taxDirection} ${derived.tax_position.net_vat_amount_human_ru}.`); } if (derived.trading_margin_proxy) { const proxy = derived.trading_margin_proxy; const marginText = proxy.margin_to_revenue_pct === null ? "не рассчитана" : `${proxy.margin_to_revenue_pct}%`; facts.push(`Торговый margin proxy за ${proxy.period_scope} подтвержден по товарным документам продаж/поступлений: выручка продаж ${proxy.sales_revenue_human_ru}, закупочный документный след ${proxy.purchase_cost_proxy_human_ru}, валовый спред proxy ${proxy.gross_spread_proxy_human_ru}, маржинальность к выручке ${marginText}. Это не чистая прибыль и не бухгалтерский финрезультат.`); } if (derived.debt_position) { const debtDirection = derived.debt_position.net_debt_position_direction === "net_receivable" ? "в пользу дебиторки" : derived.debt_position.net_debt_position_direction === "net_payable" ? "в сторону кредиторки" : "сбалансировано"; facts.push(`Долговая позиция на ${derived.debt_position.as_of_date} подтверждена по срезам дебиторки/кредиторки 1С: дебиторка ${derived.debt_position.receivables.total_amount_human_ru}, кредиторка ${derived.debt_position.payables.total_amount_human_ru}, нетто ${debtDirection} ${derived.debt_position.net_debt_position_amount_human_ru}.`); } if (derived.debt_open_settlement_quality) { const quality = derived.debt_open_settlement_quality; const leader = quality.top_contracts[0]; const leaderShareText = leader?.share_of_gross_open_amount_pct === null || leader?.share_of_gross_open_amount_pct === undefined ? "" : ` (${leader.share_of_gross_open_amount_pct}%)`; const leaderText = leader ? ` Крупнейший открытый договор: ${leader.contract}${leader.counterparty ? ` / ${leader.counterparty}` : ""} — ${leader.total_amount_human_ru}${leaderShareText}.` : ""; facts.push(`Качество открытых расчетов на ${quality.as_of_date} проверено по договорным остаткам 60/62/76: брутто ${quality.gross_open_amount_human_ru}, договоров ${quality.unique_contracts}, контрагентов ${quality.unique_counterparties}.${leaderText}`); if (quality.age_signal?.oldest_start_date) { const ageText = quality.age_signal.max_age_days === null ? "" : `, максимальный возраст сигнала ${quality.age_signal.max_age_days} дн.`; facts.push(`Возрастной сигнал открытых расчетов подтвержден по датам договоров: самая ранняя дата договора ${quality.age_signal.oldest_start_date}${ageText}. Это не договорная просрочка и не due-date анализ.`); } } if (derived.debt_staleness_risk_proxy) { const proxy = derived.debt_staleness_risk_proxy; const counterpartyText = proxy.top_contract_counterparty ? ` / ${proxy.top_contract_counterparty}` : ""; facts.push(`Staleness risk proxy открытых расчетов на ${proxy.as_of_date}: самый старый договорный сигнал ${proxy.oldest_contract_start_date}, возраст ${proxy.max_contract_age_days} дн.; старейший крупный договор ${proxy.top_contract}${counterpartyText} держит ${proxy.top_contract_amount_human_ru} (${proxy.top_contract_share_pct}% брутто открытых остатков); оценка ${debtStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная просрочка, не кредитный риск и не due-date aging.`); } if (derived.inventory_position) { const leader = derived.inventory_position.top_items[0]; const leaderText = leader ? ` Крупнейшая подтвержденная позиция: ${leader.item} — ${leader.total_amount_human_ru}.` : ""; facts.push(`Складской срез на ${derived.inventory_position.as_of_date} подтвержден по 1С: остаток ${derived.inventory_position.total_amount_human_ru} по ${derived.inventory_position.rows_with_amount} строкам с суммой и ${derived.inventory_position.rows_with_quantity} строкам с количеством.${leaderText}`); if (derived.inventory_position.aging_signal?.oldest_purchase_date) { const ageText = derived.inventory_position.aging_signal.max_age_days === null ? "" : `, максимальный возраст сигнала ${derived.inventory_position.aging_signal.max_age_days} дн.`; facts.push(`Возрастной сигнал склада подтвержден по найденным строкам закупок: самая ранняя дата ${derived.inventory_position.aging_signal.oldest_purchase_date}${ageText}.`); } } if (derived.inventory_turnover_proxy) { const proxy = derived.inventory_turnover_proxy; const ratioText = proxy.sales_to_stock_amount_ratio === null ? "не рассчитано" : `${proxy.sales_to_stock_amount_ratio}x`; const stockShareText = proxy.stock_to_sales_revenue_pct === null ? "не рассчитана" : `${proxy.stock_to_sales_revenue_pct}%`; facts.push(`Оборотный proxy склада за ${proxy.period_scope} подтвержден по продажным документам и складскому остатку: продажи ${proxy.sales_revenue_human_ru}, остаток на ${proxy.as_of_date} ${proxy.inventory_amount_human_ru}, sales-to-stock ratio ${ratioText}, остаток к продажам ${stockShareText}. Это не полноценная складская ликвидность, не FIFO-оборачиваемость и не анализ устаревания.`); } if (derived.inventory_staleness_risk_proxy) { const proxy = derived.inventory_staleness_risk_proxy; facts.push(`Staleness risk proxy склада на ${proxy.as_of_date}: самая ранняя дата закупочного сигнала ${proxy.oldest_purchase_date}, возраст ${proxy.max_purchase_age_days} дн., sales-to-stock ${proxy.sales_to_stock_amount_ratio}x, оценка ${inventoryStalenessRiskBandRu(proxy.risk_band)}. Это не подтвержденная неликвидность, не резерв и не ликвидационная стоимость.`); } return facts; } function buildBusinessOverviewInferredFacts(derived) { if (!derived) { return []; } if (derived.incoming_customer_revenue.rows_with_amount <= 0 && derived.outgoing_supplier_payout.rows_with_amount <= 0) { return []; } const direction = derived.net_direction === "net_incoming" ? "денежный поток в проверенном срезе больше входящий, чем исходящий" : derived.net_direction === "net_outgoing" ? "денежный поток в проверенном срезе больше исходящий, чем входящий" : "входящий и исходящий денежный поток в проверенном срезе примерно сбалансированы"; const supplierLeader = derived.top_suppliers[0]; const supplierSharePct = supplierLeader ? percentageOfTotal(supplierLeader.total_amount, derived.outgoing_supplier_payout.total_amount) : null; const strongestIncomingYear = [...derived.yearly_breakdown] .filter((bucket) => bucket.incoming_total_amount > 0) .sort((left, right) => right.incoming_total_amount - left.incoming_total_amount || left.year_bucket.localeCompare(right.year_bucket))[0]; const strongestNetYear = [...derived.yearly_breakdown] .filter((bucket) => bucket.net_amount !== 0) .sort((left, right) => right.net_amount - left.net_amount || left.year_bucket.localeCompare(right.year_bucket))[0]; return [ `Расчетное нетто по найденным строкам: ${derived.net_amount_human_ru}; ${direction}.`, supplierLeader ? supplierSharePct !== null ? `Крупнейший подтвержденный поставщик/получатель исходящих платежей ${supplierLeader.axis_value} держит около ${supplierSharePct}% проверенного исходящего потока (${supplierLeader.total_amount_human_ru}). Это procurement concentration proxy по найденным строкам, а не полный vendor-risk аудит.` : `Крупнейший подтвержденный поставщик/получатель исходящих платежей в проверенном срезе: ${supplierLeader.axis_value} — ${supplierLeader.total_amount_human_ru}.` : null, strongestIncomingYear ? `Самый сильный год по подтвержденным входящим поступлениям: ${strongestIncomingYear.year_bucket} (${strongestIncomingYear.incoming_total_amount_human_ru}).` : null, strongestNetYear ? `Лучший год по расчетному операционному нетто найденных строк: ${strongestNetYear.year_bucket} (${netDirectionFromAmount(strongestNetYear.net_amount) === "net_outgoing" ? "нетто исходящее" : "нетто в плюс"} ${strongestNetYear.net_amount_human_ru}). Это не бухгалтерская прибыль.` : null, "Это операционный денежный сигнал по найденным строкам 1С, а не прибыль, маржа или бухгалтерское заключение о здоровье бизнеса." ].filter((fact) => Boolean(fact)); } function buildBusinessOverviewUnknownFacts(derived) { const missing = new Set(derived?.missing_signal_families ?? [ "profit_margin", "debt_position", "tax_position", "inventory_position" ]); const unknowns = [ missing.has("profit_margin") ? "Прибыль и маржа этим бизнес-обзором не подтверждены: нужны себестоимость, расходы и закрывающие документы." : null, missing.has("accounting_profit_margin") ? "Чистая прибыль, бухгалтерская маржа и финрезультат этим бизнес-обзором не подтверждены: торговый proxy показывает только документную разницу продаж и поступлений без расходов, закрытия периода и точной себестоимости продаж." : null, missing.has("debt_quality") ? "Качество дебиторки/кредиторки этим бизнес-обзором не подтверждено: нужен отдельный долговой срез." : null, missing.has("debt_position") ? "Дебиторка/кредиторка этим бизнес-обзором не подтверждены: нужен отдельный долговой срез на явную дату." : null, missing.has("debt_aging_quality") ? "Качество долга и просрочка этим бизнес-обзором не подтверждены: текущий долговой срез показывает только суммы на дату, без aging/due-date анализа." : null, missing.has("debt_open_settlement_quality") ? "Качество открытых расчетов этим бизнес-обзором не подтверждено: нужен срез открытых договоров на явную дату." : null, missing.has("debt_due_date_aging_quality") ? "Просрочка и due-date aging этим бизнес-обзором не подтверждены: открытые договоры показывают концентрацию остатков, но не договорные сроки оплаты." : null, missing.has("tax_position") ? "Налоговая/VAT-позиция этим бизнес-обзором не подтверждена: нужен отдельный налоговый контур или явный проверяемый период." : null, missing.has("inventory_health") ? "Складская ликвидность и товарные остатки этим бизнес-обзором не подтверждены: нужен отдельный inventory-срез." : null, missing.has("inventory_position") ? "Складской остаток этим бизнес-обзором не подтвержден: нужен отдельный inventory-срез на явную дату." : null, missing.has("inventory_aging_quality") ? "Возраст, залежалость и ликвидность склада этим бизнес-обзором не подтверждены: текущий складской срез показывает только остаток на дату без полноценной оборачиваемости." : null, missing.has("inventory_turnover_quality") ? "Скорость продаж, оборачиваемость и ликвидность склада этим бизнес-обзором не подтверждены: нужен отдельный inventory/продажный анализ, а не только остаток на дату." : null, missing.has("inventory_liquidity_quality") ? "Полная складская ликвидность этим бизнес-обзором не подтверждена: sales-to-stock proxy показывает только соотношение продажных документов и остатка на дату, без FIFO-оборачиваемости, устаревания, резервов и ликвидационной стоимости." : null, missing.has("inventory_reserve_liquidation_quality") ? "Резервы, списания, подтвержденная неликвидность и ликвидационная стоимость склада этим бизнес-обзором не подтверждены: staleness proxy показывает только возраст закупочного сигнала и sales-to-stock, без управленческого решения о запасах." : null ].filter((item) => Boolean(item)); if (derived?.coverage_limited_by_probe_limit) { unknowns.unshift("Полное покрытие бизнес-обзора не подтверждено: хотя бы один денежный probe достиг лимита строк."); } return unknowns; } function buildLifecycleConfirmedFacts(result, counterparty) { if (result.error || result.matched_rows <= 0) { return []; } return [ counterparty ? `1C activity rows were found for counterparty ${counterparty}; matched_rows=${result.matched_rows}` : `1C activity rows were found for the requested counterparty scope; matched_rows=${result.matched_rows}` ]; } function checkedCounterpartySuffixRu(counterparty) { return counterparty ? ` по контрагенту ${counterparty}` : ""; } function checkedPeriodSuffixRu(periodScope) { return periodScope ? ` за ${periodScope}` : " в проверенном окне"; } function uncheckedPeriodBoundaryRu(periodScope) { return periodScope ? ` вне периода ${periodScope}` : " без явно проверенного периода"; } function buildDocumentConfirmedFacts(result, counterparty, periodScope) { if (result.error || result.matched_rows <= 0) { return []; } return [`В 1С найдены строки документов${checkedCounterpartySuffixRu(counterparty)}${checkedPeriodSuffixRu(periodScope)}.`]; } function buildMovementConfirmedFacts(result, counterparty, periodScope) { if (result.error || result.matched_rows <= 0) { return []; } return [`В 1С найдены строки движений${checkedCounterpartySuffixRu(counterparty)}${checkedPeriodSuffixRu(periodScope)}.`]; } function buildValueFlowConfirmedFacts(result, counterparty, direction) { if (result.error || result.matched_rows <= 0) { return []; } if (direction === "outgoing_supplier_payout") { return [ counterparty ? `1C supplier-payout rows were found for counterparty ${counterparty}` : "1C supplier-payout rows were found for the requested counterparty scope" ]; } return [ counterparty ? `1C value-flow rows were found for counterparty ${counterparty}` : "1C value-flow rows were found for the requested counterparty scope" ]; } function buildRankedValueFlowConfirmedFacts(derived) { if (!derived || derived.ranked_values.length <= 0) { return []; } const leader = derived.ranked_values[0]; const directionLabel = derived.value_flow_direction === "outgoing_supplier_payout" ? "supplier-payout" : "incoming value-flow"; return [ `1C ${directionLabel} rows were ranked by counterparty for the checked scope; leader=${leader.axis_value}, rows_with_amount=${leader.rows_with_amount}` ]; } function buildBidirectionalValueFlowConfirmedFacts(derived) { if (!derived) { return []; } const hasIncoming = derived.incoming_customer_revenue.rows_matched > 0; const hasOutgoing = derived.outgoing_supplier_payout.rows_matched > 0; if (derived.counterparty) { return [ `1C bidirectional value-flow rows were checked for counterparty ${derived.counterparty}: incoming=${hasIncoming ? "found" : "not_found"}, outgoing=${hasOutgoing ? "found" : "not_found"}` ]; } return [ `1C bidirectional value-flow rows were checked for the requested counterparty scope: incoming=${hasIncoming ? "found" : "not_found"}, outgoing=${hasOutgoing ? "found" : "not_found"}` ]; } function inventoryLabelRu(intent) { if (intent === "inventory_supplier_stock_overlap_as_of_date") { return "связи поставщиков с товарным остатком"; } if (intent === "inventory_purchase_provenance_for_item") { return "закупочной истории позиции"; } if (intent === "inventory_sale_trace_for_item") { return "продаж по позиции"; } return "складского среза"; } function inventoryScopeSuffixRu(input) { const parts = []; if (input.organization) { parts.push(`по организации ${input.organization}`); } if (input.item) { parts.push(`по позиции ${input.item}`); } if (input.intent === "inventory_supplier_stock_overlap_as_of_date" && input.counterparty) { parts.push(`по поставщику/контрагенту ${input.counterparty}`); } if (input.asOfDate) { parts.push(`на ${input.asOfDate}`); } else if (input.dateScope) { parts.push(`за ${input.dateScope}`); } return parts.length > 0 ? ` ${parts.join(", ")}` : ""; } function inventoryRowSample(row) { const item = rowInventoryItemValue(row); const quantity = rowQuantityValue(row); const warehouse = rowWarehouseValue(row); const counterparty = rowCounterpartyValue(row); const document = rowDocumentValue(row); const parts = []; if (item) { parts.push(item); } if (quantity !== null) { parts.push(`${quantity} шт.`); } if (warehouse) { parts.push(`склад ${warehouse}`); } if (counterparty) { parts.push(`контрагент ${counterparty}`); } if (document) { parts.push(`документ ${document}`); } return parts.length > 0 ? parts.join(", ") : null; } function buildInventoryConfirmedFacts(result, planner, intent) { if (result.error || result.matched_rows <= 0) { return []; } const dateScope = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.explicit_date_scope); const item = intent === "inventory_purchase_provenance_for_item" || intent === "inventory_sale_trace_for_item" ? firstEntityCandidate(planner) : null; const counterparty = intent === "inventory_supplier_stock_overlap_as_of_date" ? firstEntityCandidate(planner) : null; const scope = inventoryScopeSuffixRu({ intent, item, counterparty, organization: organizationScopeForPlanner(planner), asOfDate: asOfDateFromDateScope(dateScope), dateScope }); const samples = result.rows .slice(0, 3) .map((row) => inventoryRowSample(row)) .filter((value) => Boolean(value)); const sampleSuffix = samples.length > 0 ? ` Примеры строк: ${samples.join("; ")}.` : ""; return [`В 1С найдены подтвержденные строки ${inventoryLabelRu(intent)}${scope}: ${result.matched_rows}.${sampleSuffix}`]; } function buildInventoryInferredFacts(result, intent) { if (result.error || result.fetched_rows <= 0) { return []; } if (result.matched_rows <= 0) { return [ `По ${inventoryLabelRu(intent)} удалось проверить только ограниченный срез 1С; подтвержденных строк этим поиском не найдено.` ]; } return [ `Вывод по ${inventoryLabelRu(intent)} ограничен найденными строками 1С и указанными датой, организацией, позицией или поставщиком.` ]; } function buildInventoryUnknownFacts(result, intent, dateScope) { const facts = [ dateScope ? `Полный товарный контур вне проверенного среза ${dateScope} не подтвержден.` : "Полный товарный контур без явного проверенного периода или даты не подтвержден." ]; if (!result || result.error || result.matched_rows <= 0) { facts.unshift(`Подтвержденный факт по ${inventoryLabelRu(intent)} в проверенных строках 1С не найден.`); } return facts; } function buildLifecycleInferredFacts(result) { if (result.error || result.fetched_rows <= 0) { return []; } const period = deriveActivityPeriod(result); if (!period) { return ["Business activity duration may be inferred only when confirmed 1C activity row dates are available"]; } return [ "Business activity duration may be inferred from first and latest confirmed 1C activity rows", `Activity window is bounded by first=${period.first_activity_date}, latest=${period.latest_activity_date}, matched_rows=${period.matched_rows}`, "Activity-window inference is not legal registration age" ]; } function buildDocumentInferredFacts(result, counterparty, periodScope) { if (result.error || result.fetched_rows <= 0) { return []; } if (result.matched_rows <= 0) { return [ `По документам${checkedCounterpartySuffixRu(counterparty)}${checkedPeriodSuffixRu(periodScope)} удалось проверить только ограниченный срез 1С; подтвержденных строк документов этим поиском не найдено.` ]; } return [ `Срез документов${checkedCounterpartySuffixRu(counterparty)}${checkedPeriodSuffixRu(periodScope)} ограничен только подтвержденными строками документов, найденными этим поиском.` ]; } function buildMovementInferredFacts(result, counterparty, periodScope) { if (result.error || result.fetched_rows <= 0) { return []; } if (result.matched_rows <= 0) { return [ `По движениям${checkedCounterpartySuffixRu(counterparty)}${checkedPeriodSuffixRu(periodScope)} удалось проверить только ограниченный срез 1С; подтвержденных строк движений этим поиском не найдено.` ]; } return [ `Срез движений${checkedCounterpartySuffixRu(counterparty)}${checkedPeriodSuffixRu(periodScope)} ограничен только подтвержденными строками движений, найденными этим поиском.` ]; } function buildValueFlowInferredFacts(derived) { if (!derived) { return []; } const facts = []; if (derived.value_flow_direction === "outgoing_supplier_payout") { facts.push("Counterparty supplier-payout total was calculated from confirmed 1C outgoing payment rows"); } else { facts.push("Counterparty value-flow total was calculated from confirmed 1C movement rows"); } if (derived.coverage_recovered_by_period_chunking && derived.period_chunking_granularity === "month") { facts.push("Requested period coverage was recovered through monthly 1C value-flow probes"); } if (derived.aggregation_axis === "month" && derived.monthly_breakdown.length > 0) { facts.push("Counterparty monthly value-flow breakdown was grouped by month over confirmed 1C movement rows"); } return facts; } function buildRankedValueFlowInferredFacts(derived) { if (!derived) { return []; } const facts = ["Counterparty ranking was calculated from confirmed 1C movement rows grouped by counterparty"]; if (derived.coverage_recovered_by_period_chunking && derived.period_chunking_granularity === "month") { facts.push("Requested period coverage for counterparty ranking was recovered through monthly 1C probes"); } return facts; } function buildBidirectionalValueFlowInferredFacts(derived) { if (!derived) { return []; } const facts = ["Counterparty net value-flow was calculated as incoming confirmed 1C rows minus outgoing confirmed 1C rows"]; if (derived.coverage_recovered_by_period_chunking && derived.period_chunking_granularity === "month") { facts.push("Requested period coverage for bidirectional value-flow was recovered through monthly 1C side probes"); } if (derived.aggregation_axis === "month" && derived.monthly_breakdown.length > 0) { facts.push("Counterparty monthly net value-flow breakdown was grouped by month over confirmed incoming and outgoing 1C rows"); } return facts; } function buildLifecycleUnknownFacts() { return [ "Legal registration date is not proven by this MCP discovery pilot", "Business activity before the first confirmed 1C activity row is not proven by this MCP discovery pilot" ]; } function buildDocumentUnknownFacts(periodScope, counterparty) { return [ `Полный исторический срез документов${checkedCounterpartySuffixRu(counterparty)}${uncheckedPeriodBoundaryRu(periodScope)} этим поиском не подтвержден.` ]; } function buildMovementUnknownFacts(periodScope, counterparty) { return [ `Полный исторический срез движений${checkedCounterpartySuffixRu(counterparty)}${uncheckedPeriodBoundaryRu(periodScope)} этим поиском не подтвержден.` ]; } function buildValueFlowUnknownFacts(periodScope, direction, derived) { const unknownFacts = []; if (derived?.coverage_limited_by_probe_limit) { unknownFacts.push("Complete requested-period coverage is not proven by the available checked rows"); } if (direction === "outgoing_supplier_payout") { unknownFacts.push(periodScope ? "Full supplier-payout amount outside the checked period is not proven by this MCP discovery pilot" : "Full all-time supplier-payout amount is not proven without an explicit checked period"); return unknownFacts; } unknownFacts.push(periodScope ? "Full turnover outside the checked period is not proven by this MCP discovery pilot" : "Full all-time turnover is not proven without an explicit checked period"); return unknownFacts; } function buildRankedValueFlowUnknownFacts(periodScope, derived) { const unknownFacts = []; if (derived?.coverage_limited_by_probe_limit) { unknownFacts.push("Complete requested-period ranking coverage is not proven by the available checked rows"); } unknownFacts.push(periodScope ? "Full ranking outside the checked period is not proven by this MCP discovery pilot" : "Full all-time counterparty ranking is not proven without an explicit checked period"); return unknownFacts; } function buildBidirectionalValueFlowUnknownFacts(periodScope, derived) { const unknownFacts = []; if (derived?.coverage_limited_by_probe_limit) { unknownFacts.push("Complete requested-period coverage for bidirectional value-flow is not proven by the available checked rows"); } unknownFacts.push(periodScope ? "Full bidirectional value-flow outside the checked period is not proven by this MCP discovery pilot" : "Full all-time bidirectional value-flow is not proven without an explicit checked period"); return unknownFacts; } function buildEmptyEvidence(planner, dryRun, probeResults, reason) { return (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, unknownFacts: [reason], queryLimitations: [reason], recommendedNextProbe: dryRun.user_facing_fallback }); } function pilotScopeForPlanner(planner) { switch (planner.selected_chain_id) { case "catalog_drilldown": case "metadata_lane_clarification": case "metadata_inspection": return "metadata_inspection_v1"; case "inventory_stock_snapshot": case "inventory_supplier_overlap": case "inventory_purchase_provenance": case "inventory_sale_trace": return "inventory_route_template_v1"; case "movement_evidence": return "counterparty_movement_evidence_query_movements_v1"; case "value_flow_comparison": case "value_flow_ranking": case "value_flow": return valueFlowPilotProfile(planner).scope; case "business_overview": return "business_overview_route_template_v1"; case "document_evidence": return "counterparty_document_evidence_query_documents_v1"; case "lifecycle": return "counterparty_lifecycle_query_documents_v1"; case "entity_resolution": return "entity_resolution_search_v1"; } } async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) { const runtimeDeps = { ...DEFAULT_DEPS, ...deps }; const dryRun = (0, assistantMcpDiscoveryRuntimeAdapter_1.buildAssistantMcpDiscoveryRuntimeDryRun)(planner); const reasonCodes = [...dryRun.reason_codes]; const executedPrimitives = []; const skippedPrimitives = []; const probeResults = []; const queryLimitations = []; const pilotScope = pilotScopeForPlanner(planner); if (dryRun.adapter_status === "blocked") { pushReason(reasonCodes, "pilot_blocked_before_mcp_execution"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "MCP discovery pilot was blocked before execution"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "blocked", pilot_scope: pilotScope, dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["MCP discovery pilot was blocked before execution"], reason_codes: reasonCodes }; } if (dryRun.adapter_status !== "dry_run_ready") { pushReason(reasonCodes, "pilot_needs_clarification_before_mcp_execution"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "MCP discovery pilot needs more scope before execution"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "skipped_needs_clarification", pilot_scope: pilotScope, dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["MCP discovery pilot needs more scope before execution"], reason_codes: reasonCodes }; } const metadataPilotEligible = isMetadataPilotEligible(planner); const documentPilotEligible = isDocumentEvidencePilotEligible(planner); const movementPilotEligible = isMovementEvidencePilotEligible(planner); const lifecyclePilotEligible = isLifecyclePilotEligible(planner); const valueFlowPilotEligible = isValueFlowPilotEligible(planner); const businessOverviewPilotEligible = isBusinessOverviewPilotEligible(planner); const entityResolutionPilotEligible = isEntityResolutionPilotEligible(planner); const inventoryPilotEligible = isInventoryPilotEligible(planner); if (!metadataPilotEligible && !documentPilotEligible && !movementPilotEligible && !lifecyclePilotEligible && !valueFlowPilotEligible && !businessOverviewPilotEligible && !entityResolutionPilotEligible && !inventoryPilotEligible) { pushReason(reasonCodes, "pilot_scope_unsupported_for_live_execution"); for (const step of dryRun.execution_steps) { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_scope_unsupported_for_live_execution")); } const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "MCP discovery pilot scope is not implemented yet"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: pilotScope, dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["MCP discovery pilot scope is not implemented yet"], reason_codes: reasonCodes }; } const counterparty = firstEntityCandidate(planner); const dateScope = toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.explicit_date_scope); const organizationScope = organizationScopeForPlanner(planner); const aggregationAxis = aggregationAxisForPlanner(planner); const rankingNeed = rankingNeedForPlanner(planner); if (inventoryPilotEligible) { let queryResult = null; const inventoryIntent = inventoryIntentForPlanner(planner); const executablePrimitive = inventoryExecutablePrimitiveForPlanner(planner); if (!inventoryIntent || !executablePrimitive) { pushReason(reasonCodes, "pilot_inventory_exact_recipe_not_mapped"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Inventory exact recipe is not mapped"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: "inventory_route_template_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Inventory exact recipe is not mapped"], reason_codes: reasonCodes }; } const filters = buildInventoryExactFilters(planner); const selection = (0, addressRecipeCatalog_1.selectAddressRecipe)(inventoryIntent, filters); if (selection.missing_required_filters.length > 0) { pushReason(reasonCodes, "pilot_inventory_exact_recipe_needs_required_filters"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, `Inventory exact recipe needs required filters: ${selection.missing_required_filters.join(", ")}`); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "skipped_needs_clarification", pilot_scope: "inventory_route_template_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: [`Inventory exact recipe needs required filters: ${selection.missing_required_filters.join(", ")}`], reason_codes: reasonCodes }; } if (!selection.selected_recipe) { pushReason(reasonCodes, "pilot_inventory_exact_recipe_not_available"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Inventory exact recipe is not available"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: "inventory_route_template_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Inventory exact recipe is not available"], reason_codes: reasonCodes }; } pushReason(reasonCodes, "pilot_inventory_exact_recipe_selected"); const recipePlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(selection.selected_recipe, filters); for (const step of dryRun.execution_steps) { if (step.primitive_id !== executablePrimitive) { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, `pilot_inventory_exact_bridge_executes_${executablePrimitive}`)); continue; } queryResult = await runtimeDeps.executeAddressMcpQuery({ query: recipePlan.query, limit: recipePlan.limit, account_scope: recipePlan.account_scope }); pushUnique(executedPrimitives, step.primitive_id); probeResults.push(queryResultToProbeResult(step.primitive_id, queryResult)); if (queryResult.error) { pushUnique(queryLimitations, queryResult.error); pushReason(reasonCodes, "pilot_inventory_exact_mcp_error"); } else { pushReason(reasonCodes, "pilot_inventory_exact_mcp_executed"); } } const sourceRowsSummary = queryResult ? summarizeInventoryRows(queryResult) : null; const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: queryResult ? buildInventoryConfirmedFacts(queryResult, planner, inventoryIntent) : [], inferredFacts: queryResult ? buildInventoryInferredFacts(queryResult, inventoryIntent) : [], unknownFacts: buildInventoryUnknownFacts(queryResult, inventoryIntent, toNonEmptyString(planner.discovery_plan.turn_meaning_ref?.explicit_date_scope)), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: "inventory_route_template_v1", dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; } if (businessOverviewPilotEligible) { let incomingResult = null; let outgoingResult = null; let lifecycleResult = null; let taxResult = null; let tradingMarginResult = null; let receivablesResult = null; let payablesResult = null; let openContractsResult = null; let documentActivityProfileResult = null; let counterpartyProfileResult = null; let contractUsageProfileResult = null; let inventoryOnHandResult = null; let inventoryAgingResult = null; const valueFilters = buildValueFlowFilters(planner); const lifecycleFilters = buildLifecycleFilters(planner); const profileFilters = buildBusinessOverviewProfileFilters(planner); const taxFilters = buildBusinessOverviewTaxFilters(planner); const tradingMarginFilters = buildBusinessOverviewTradingMarginFilters(planner); const debtFilters = buildBusinessOverviewDebtFilters(planner); const inventoryFilters = buildBusinessOverviewInventoryFilters(planner); const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date); const inventoryAsOfDate = toNonEmptyString(inventoryFilters?.as_of_date); const incomingSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("customer_revenue_and_payments", valueFilters); const outgoingSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("supplier_payouts_profile", valueFilters); const lifecycleSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("counterparty_activity_lifecycle", lifecycleFilters); const documentActivitySelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("document_type_and_account_section_profile", profileFilters); const counterpartyProfileSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("counterparty_population_and_roles", profileFilters); const contractUsageSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("contract_usage_overview", profileFilters); const taxSelection = taxFilters ? (0, addressRecipeCatalog_1.selectAddressRecipe)("vat_liability_confirmed_for_tax_period", taxFilters) : null; const tradingMarginSelection = tradingMarginFilters ? (0, addressRecipeCatalog_1.selectAddressRecipe)("inventory_trading_margin_proxy_for_organization", tradingMarginFilters) : null; const receivablesSelection = debtFilters ? (0, addressRecipeCatalog_1.selectAddressRecipe)("receivables_confirmed_as_of_date", debtFilters) : null; const payablesSelection = debtFilters ? (0, addressRecipeCatalog_1.selectAddressRecipe)("payables_confirmed_as_of_date", debtFilters) : null; const openContractsSelection = debtFilters ? (0, addressRecipeCatalog_1.selectAddressRecipe)("open_contracts_confirmed_as_of_date", debtFilters) : null; const inventoryOnHandSelection = inventoryFilters ? (0, addressRecipeCatalog_1.selectAddressRecipe)("inventory_on_hand_as_of_date", inventoryFilters) : null; const inventoryAgingSelection = inventoryFilters ? (0, addressRecipeCatalog_1.selectAddressRecipe)("inventory_aging_by_purchase_date", inventoryFilters) : null; if (!incomingSelection.selected_recipe || !outgoingSelection.selected_recipe || !lifecycleSelection.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_recipe_not_available"); const missing = [ incomingSelection.selected_recipe ? null : "customer_revenue_and_payments", outgoingSelection.selected_recipe ? null : "supplier_payouts_profile", lifecycleSelection.selected_recipe ? null : "counterparty_activity_lifecycle" ].filter((item) => Boolean(item)); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Business overview recipe is not available"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: "business_overview_route_template_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: [`Business overview recipe is not available: ${missing.join(", ")}`], reason_codes: reasonCodes }; } pushReason(reasonCodes, "pilot_business_overview_recipes_selected"); if (documentActivitySelection.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_document_activity_profile_recipe_selected"); } else { pushReason(reasonCodes, "pilot_business_overview_document_activity_profile_recipe_not_available"); pushUnique(queryLimitations, "Business overview document/account-section profile requires an executable document-section profile recipe"); } if (counterpartyProfileSelection.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_counterparty_profile_recipe_selected"); } else { pushReason(reasonCodes, "pilot_business_overview_counterparty_profile_recipe_not_available"); pushUnique(queryLimitations, "Business overview counterparty profile requires an executable counterparty population/roles recipe"); } if (contractUsageSelection.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_recipe_selected"); } else { pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_recipe_not_available"); pushUnique(queryLimitations, "Business overview contract usage profile requires an executable contract usage recipe"); } if (taxSelection?.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_tax_recipe_selected"); } else if (!taxFilters) { pushReason(reasonCodes, "pilot_business_overview_tax_probe_skipped_without_explicit_period"); } else { pushReason(reasonCodes, "pilot_business_overview_tax_recipe_not_available"); pushUnique(queryLimitations, "Business overview VAT/tax probe requires an executable tax-period recipe"); } if (tradingMarginSelection?.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_trading_margin_recipe_selected"); } else if (!tradingMarginFilters) { pushReason(reasonCodes, "pilot_business_overview_trading_margin_probe_skipped_without_explicit_period"); } else { pushReason(reasonCodes, "pilot_business_overview_trading_margin_recipe_not_available"); pushUnique(queryLimitations, "Business overview trading-margin proxy requires an executable explicit-period purchase/sale document recipe"); } if (receivablesSelection?.selected_recipe && payablesSelection?.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_debt_recipes_selected"); } else if (!debtFilters) { pushReason(reasonCodes, "pilot_business_overview_debt_probe_skipped_without_explicit_as_of_date"); } else { pushReason(reasonCodes, "pilot_business_overview_debt_recipe_not_available"); pushUnique(queryLimitations, "Business overview debt-position probe requires executable receivables/payables as-of-date recipes"); } if (openContractsSelection?.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_open_contracts_recipe_selected"); } else if (!debtFilters) { pushReason(reasonCodes, "pilot_business_overview_open_contracts_probe_skipped_without_explicit_as_of_date"); } else { pushReason(reasonCodes, "pilot_business_overview_open_contracts_recipe_not_available"); pushUnique(queryLimitations, "Business overview open-settlement quality probe requires executable open-contracts as-of-date recipe"); } if (inventoryOnHandSelection?.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_inventory_on_hand_recipe_selected"); if (inventoryAgingSelection?.selected_recipe) { pushReason(reasonCodes, "pilot_business_overview_inventory_aging_recipe_selected"); } } else if (!inventoryFilters) { pushReason(reasonCodes, "pilot_business_overview_inventory_probe_skipped_without_explicit_as_of_date"); } else { pushReason(reasonCodes, "pilot_business_overview_inventory_recipe_not_available"); pushUnique(queryLimitations, "Business overview inventory-position probe requires an executable inventory on-hand as-of-date recipe"); } for (const step of dryRun.execution_steps) { if (step.primitive_id === "query_movements") { const incomingExecution = await executeCoverageAwareValueFlowQuery({ primitiveId: step.primitive_id, recipePlanBuilder: (scopedFilters) => (0, addressRecipeCatalog_1.buildAddressRecipePlan)(incomingSelection.selected_recipe, scopedFilters), baseFilters: valueFilters, dateScope, maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count, maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe, deps: runtimeDeps }); const outgoingExecution = await executeCoverageAwareValueFlowQuery({ primitiveId: step.primitive_id, recipePlanBuilder: (scopedFilters) => (0, addressRecipeCatalog_1.buildAddressRecipePlan)(outgoingSelection.selected_recipe, scopedFilters), baseFilters: valueFilters, dateScope, maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count, maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe, deps: runtimeDeps }); incomingResult = incomingExecution.result; outgoingResult = outgoingExecution.result; if (taxSelection?.selected_recipe) { const taxPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(taxSelection.selected_recipe, taxFilters); taxResult = await runtimeDeps.executeAddressMcpQuery({ query: taxPlan.query, limit: taxPlan.limit, account_scope: taxPlan.account_scope }); } if (receivablesSelection?.selected_recipe && payablesSelection?.selected_recipe) { const receivablesPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(receivablesSelection.selected_recipe, debtFilters); receivablesResult = await runtimeDeps.executeAddressMcpQuery({ query: receivablesPlan.query, limit: receivablesPlan.limit, account_scope: receivablesPlan.account_scope }); const payablesPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(payablesSelection.selected_recipe, debtFilters); payablesResult = await runtimeDeps.executeAddressMcpQuery({ query: payablesPlan.query, limit: payablesPlan.limit, account_scope: payablesPlan.account_scope }); } if (openContractsSelection?.selected_recipe) { const openContractsPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(openContractsSelection.selected_recipe, debtFilters); openContractsResult = await runtimeDeps.executeAddressMcpQuery({ query: openContractsPlan.query, limit: openContractsPlan.limit, account_scope: openContractsPlan.account_scope }); } if (inventoryOnHandSelection?.selected_recipe) { const inventoryOnHandPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(inventoryOnHandSelection.selected_recipe, inventoryFilters); inventoryOnHandResult = await runtimeDeps.executeAddressMcpQuery({ query: inventoryOnHandPlan.query, limit: inventoryOnHandPlan.limit, account_scope: inventoryOnHandPlan.account_scope }); if (inventoryAgingSelection?.selected_recipe) { const inventoryAgingPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(inventoryAgingSelection.selected_recipe, inventoryFilters); inventoryAgingResult = await runtimeDeps.executeAddressMcpQuery({ query: inventoryAgingPlan.query, limit: inventoryAgingPlan.limit, account_scope: inventoryAgingPlan.account_scope }); } } pushUnique(executedPrimitives, step.primitive_id); probeResults.push(...incomingExecution.probe_results, ...outgoingExecution.probe_results); if (taxResult) { probeResults.push(queryResultToProbeResult(step.primitive_id, taxResult)); } if (receivablesResult) { probeResults.push(queryResultToProbeResult(step.primitive_id, receivablesResult)); } if (payablesResult) { probeResults.push(queryResultToProbeResult(step.primitive_id, payablesResult)); } if (openContractsResult) { probeResults.push(queryResultToProbeResult(step.primitive_id, openContractsResult)); } if (inventoryOnHandResult) { probeResults.push(queryResultToProbeResult(step.primitive_id, inventoryOnHandResult)); } if (inventoryAgingResult) { probeResults.push(queryResultToProbeResult(step.primitive_id, inventoryAgingResult)); } for (const limitation of [...incomingExecution.query_limitations, ...outgoingExecution.query_limitations]) { pushUnique(queryLimitations, limitation); } if (incomingResult?.error) { pushReason(reasonCodes, "pilot_business_overview_incoming_query_mcp_error"); } if (outgoingResult?.error) { pushReason(reasonCodes, "pilot_business_overview_outgoing_query_mcp_error"); } if (!incomingResult?.error || !outgoingResult?.error) { pushReason(reasonCodes, "pilot_business_overview_query_movements_mcp_executed"); } if (taxResult?.error) { pushUnique(queryLimitations, taxResult.error); pushReason(reasonCodes, "pilot_business_overview_tax_query_mcp_error"); } else if (taxResult) { pushReason(reasonCodes, "pilot_business_overview_tax_query_mcp_executed"); } if (receivablesResult?.error) { pushUnique(queryLimitations, receivablesResult.error); pushReason(reasonCodes, "pilot_business_overview_receivables_query_mcp_error"); } else if (receivablesResult) { pushReason(reasonCodes, "pilot_business_overview_receivables_query_mcp_executed"); } if (payablesResult?.error) { pushUnique(queryLimitations, payablesResult.error); pushReason(reasonCodes, "pilot_business_overview_payables_query_mcp_error"); } else if (payablesResult) { pushReason(reasonCodes, "pilot_business_overview_payables_query_mcp_executed"); } if ((receivablesResult && !receivablesResult.error) || (payablesResult && !payablesResult.error)) { pushReason(reasonCodes, "pilot_business_overview_debt_query_mcp_executed"); } if (openContractsResult?.error) { pushUnique(queryLimitations, openContractsResult.error); pushReason(reasonCodes, "pilot_business_overview_open_contracts_query_mcp_error"); } else if (openContractsResult) { pushReason(reasonCodes, "pilot_business_overview_open_contracts_query_mcp_executed"); } if (inventoryOnHandResult?.error) { pushUnique(queryLimitations, inventoryOnHandResult.error); pushReason(reasonCodes, "pilot_business_overview_inventory_on_hand_query_mcp_error"); } else if (inventoryOnHandResult) { pushReason(reasonCodes, "pilot_business_overview_inventory_on_hand_query_mcp_executed"); } if (inventoryAgingResult?.error) { pushUnique(queryLimitations, inventoryAgingResult.error); pushReason(reasonCodes, "pilot_business_overview_inventory_aging_query_mcp_error"); } else if (inventoryAgingResult) { pushReason(reasonCodes, "pilot_business_overview_inventory_aging_query_mcp_executed"); } if ((inventoryOnHandResult && !inventoryOnHandResult.error) || (inventoryAgingResult && !inventoryAgingResult.error)) { pushReason(reasonCodes, "pilot_business_overview_inventory_query_mcp_executed"); } continue; } if (step.primitive_id === "query_documents") { const lifecyclePlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(lifecycleSelection.selected_recipe, lifecycleFilters); lifecycleResult = await runtimeDeps.executeAddressMcpQuery({ query: lifecyclePlan.query, limit: lifecyclePlan.limit, account_scope: lifecyclePlan.account_scope }); pushUnique(executedPrimitives, step.primitive_id); probeResults.push(queryResultToProbeResult(step.primitive_id, lifecycleResult)); if (tradingMarginSelection?.selected_recipe) { const tradingMarginPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(tradingMarginSelection.selected_recipe, tradingMarginFilters); tradingMarginResult = await runtimeDeps.executeAddressMcpQuery({ query: tradingMarginPlan.query, limit: tradingMarginPlan.limit, account_scope: tradingMarginPlan.account_scope }); probeResults.push(queryResultToProbeResult(step.primitive_id, tradingMarginResult)); } if (documentActivitySelection.selected_recipe) { const documentActivityPlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(documentActivitySelection.selected_recipe, profileFilters); documentActivityProfileResult = await runtimeDeps.executeAddressMcpQuery({ query: documentActivityPlan.query, limit: documentActivityPlan.limit, account_scope: documentActivityPlan.account_scope }); probeResults.push(queryResultToProbeResult(step.primitive_id, documentActivityProfileResult)); } if (counterpartyProfileSelection.selected_recipe) { const counterpartyProfilePlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(counterpartyProfileSelection.selected_recipe, profileFilters); counterpartyProfileResult = await runtimeDeps.executeAddressMcpQuery({ query: counterpartyProfilePlan.query, limit: counterpartyProfilePlan.limit, account_scope: counterpartyProfilePlan.account_scope }); probeResults.push(queryResultToProbeResult(step.primitive_id, counterpartyProfileResult)); } if (contractUsageSelection.selected_recipe) { const contractUsagePlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(contractUsageSelection.selected_recipe, profileFilters); contractUsageProfileResult = await runtimeDeps.executeAddressMcpQuery({ query: contractUsagePlan.query, limit: contractUsagePlan.limit, account_scope: contractUsagePlan.account_scope }); probeResults.push(queryResultToProbeResult(step.primitive_id, contractUsageProfileResult)); } if (lifecycleResult.error) { pushUnique(queryLimitations, lifecycleResult.error); pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error"); } else { pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_executed"); } if (tradingMarginResult?.error) { pushUnique(queryLimitations, tradingMarginResult.error); pushReason(reasonCodes, "pilot_business_overview_trading_margin_query_mcp_error"); } else if (tradingMarginResult) { pushReason(reasonCodes, "pilot_business_overview_trading_margin_query_mcp_executed"); } if (documentActivityProfileResult?.error) { pushUnique(queryLimitations, documentActivityProfileResult.error); pushReason(reasonCodes, "pilot_business_overview_document_activity_profile_query_mcp_error"); } else if (documentActivityProfileResult) { pushReason(reasonCodes, "pilot_business_overview_document_activity_profile_query_mcp_executed"); } if (counterpartyProfileResult?.error) { pushUnique(queryLimitations, counterpartyProfileResult.error); pushReason(reasonCodes, "pilot_business_overview_counterparty_profile_query_mcp_error"); } else if (counterpartyProfileResult) { pushReason(reasonCodes, "pilot_business_overview_counterparty_profile_query_mcp_executed"); } if (contractUsageProfileResult?.error) { pushUnique(queryLimitations, contractUsageProfileResult.error); pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_query_mcp_error"); } else if (contractUsageProfileResult) { pushReason(reasonCodes, "pilot_business_overview_contract_usage_profile_query_mcp_executed"); } continue; } skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_business_overview_derives_aggregate_coverage_and_explanation")); } const derivedBusinessOverview = deriveBusinessOverview({ incomingResult, outgoingResult, lifecycleResult, taxResult, tradingMarginResult, receivablesResult, payablesResult, openContractsResult, documentActivityProfileResult, counterpartyProfileResult, contractUsageProfileResult, debtAsOfDate, inventoryOnHandResult, inventoryAgingResult, inventoryAsOfDate, organizationScope, periodScope: dateScope }); if (derivedBusinessOverview) { pushReason(reasonCodes, "pilot_derived_business_overview_from_confirmed_rows"); if (derivedBusinessOverview.top_customers.length > 0) { pushReason(reasonCodes, "pilot_derived_business_overview_top_customers_from_confirmed_rows"); } if (derivedBusinessOverview.top_suppliers.length > 0) { pushReason(reasonCodes, "pilot_derived_business_overview_top_suppliers_from_confirmed_rows"); } if (derivedBusinessOverview.yearly_breakdown.length > 0) { pushReason(reasonCodes, "pilot_derived_business_overview_yearly_operating_breakdown_from_confirmed_rows"); } if (derivedBusinessOverview.activity_period) { pushReason(reasonCodes, "pilot_derived_business_overview_activity_window_from_confirmed_rows"); } if (derivedBusinessOverview.document_activity_profile) { pushReason(reasonCodes, "pilot_derived_business_overview_document_activity_profile_from_confirmed_rows"); } if (derivedBusinessOverview.counterparty_profile) { pushReason(reasonCodes, "pilot_derived_business_overview_counterparty_profile_from_confirmed_rows"); } if (derivedBusinessOverview.contract_usage_profile) { pushReason(reasonCodes, "pilot_derived_business_overview_contract_usage_profile_from_confirmed_rows"); } if (derivedBusinessOverview.tax_position) { pushReason(reasonCodes, "pilot_derived_business_overview_tax_position_from_confirmed_rows"); } if (derivedBusinessOverview.trading_margin_proxy) { pushReason(reasonCodes, "pilot_derived_business_overview_trading_margin_proxy_from_confirmed_rows"); } if (derivedBusinessOverview.debt_position) { pushReason(reasonCodes, "pilot_derived_business_overview_debt_position_from_confirmed_rows"); } if (derivedBusinessOverview.debt_open_settlement_quality) { pushReason(reasonCodes, "pilot_derived_business_overview_open_settlement_quality_from_confirmed_rows"); if (derivedBusinessOverview.debt_open_settlement_quality.age_signal) { pushReason(reasonCodes, "pilot_derived_business_overview_debt_age_signal_from_contract_dates"); } } if (derivedBusinessOverview.debt_staleness_risk_proxy) { pushReason(reasonCodes, "pilot_derived_business_overview_debt_staleness_risk_proxy_from_confirmed_rows"); } if (derivedBusinessOverview.inventory_position) { pushReason(reasonCodes, "pilot_derived_business_overview_inventory_position_from_confirmed_rows"); } if (derivedBusinessOverview.inventory_turnover_proxy) { pushReason(reasonCodes, "pilot_derived_business_overview_inventory_turnover_proxy_from_confirmed_rows"); } if (derivedBusinessOverview.inventory_staleness_risk_proxy) { pushReason(reasonCodes, "pilot_derived_business_overview_inventory_staleness_risk_proxy_from_confirmed_rows"); } } const sourceRowsSummary = summarizeBusinessOverviewRows({ incomingResult, outgoingResult, lifecycleResult, taxResult, tradingMarginResult, receivablesResult, payablesResult, openContractsResult, documentActivityProfileResult, counterpartyProfileResult, contractUsageProfileResult, inventoryOnHandResult, inventoryAgingResult }); const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: buildBusinessOverviewConfirmedFacts(derivedBusinessOverview), inferredFacts: buildBusinessOverviewInferredFacts(derivedBusinessOverview), unknownFacts: buildBusinessOverviewUnknownFacts(derivedBusinessOverview), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: "business_overview_route_template_v1", dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, derived_business_overview: derivedBusinessOverview, query_limitations: queryLimitations, reason_codes: reasonCodes }; } if (metadataPilotEligible) { let metadataResult = null; const metadataScope = metadataScopeForPlanner(planner); const requestedMetaTypes = metadataTypesForPlanner(planner); if (planner.selected_chain_id === "catalog_drilldown" && metadataScope) { pushReason(reasonCodes, "pilot_catalog_drilldown_metadata_scope_seeded_from_surface_ref"); } for (const step of dryRun.execution_steps) { if (step.primitive_id !== "inspect_1c_metadata") { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_metadata_uses_only_inspect_1c_metadata")); continue; } metadataResult = await runtimeDeps.executeAddressMcpMetadata({ meta_type: requestedMetaTypes, name_mask: metadataScope ?? undefined, limit: planner.discovery_plan.execution_budget.max_rows_per_probe }); pushUnique(executedPrimitives, step.primitive_id); probeResults.push(metadataResultToProbeResult(step.primitive_id, metadataResult)); if (metadataResult.error) { pushUnique(queryLimitations, metadataResult.error); pushReason(reasonCodes, "pilot_inspect_1c_metadata_mcp_error"); } else { pushReason(reasonCodes, "pilot_inspect_1c_metadata_mcp_executed"); } } const sourceRowsSummary = metadataResult ? summarizeMetadataRows(metadataResult) : null; const derivedMetadataSurface = deriveMetadataSurface(metadataResult, metadataScope, requestedMetaTypes, metadataScopeRankingAllowedForPlanner(planner)); if (derivedMetadataSurface) { pushReason(reasonCodes, "pilot_derived_metadata_surface_from_confirmed_rows"); if (derivedMetadataSurface.route_family_selection_basis === "dominant_surface_objects") { pushReason(reasonCodes, "pilot_selected_metadata_route_family_from_dominant_surface_objects"); } if (derivedMetadataSurface.surface_object_ranking_applied) { pushReason(reasonCodes, "pilot_selected_metadata_route_family_from_surface_object_ranking"); } } const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: buildMetadataConfirmedFacts(derivedMetadataSurface), inferredFacts: buildMetadataInferredFacts(derivedMetadataSurface), unknownFacts: buildMetadataUnknownFacts(derivedMetadataSurface, metadataScope), sourceRowsSummary, queryLimitations, recommendedNextProbe: "inspect_1c_metadata" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: "metadata_inspection_v1", dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: derivedMetadataSurface, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; } if (entityResolutionPilotEligible) { let queryResult = null; const requestedEntity = counterparty; if (isLowQualityEntityResolutionAnchor(requestedEntity)) { pushReason(reasonCodes, "pilot_entity_resolution_anchor_missing_or_low_quality"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Entity-resolution needs a clearer counterparty name"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "skipped_needs_clarification", pilot_scope: "entity_resolution_search_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Entity-resolution needs a clearer counterparty name"], reason_codes: reasonCodes }; } let derivedEntityResolution = null; for (const step of dryRun.execution_steps) { if (step.primitive_id === "search_business_entity") { queryResult = await runtimeDeps.executeAddressMcpQuery({ query: ENTITY_RESOLUTION_COUNTERPARTY_QUERY_TEMPLATE.replaceAll("__LIMIT__", String(ENTITY_RESOLUTION_COUNTERPARTY_LOOKUP_LIMIT)), limit: ENTITY_RESOLUTION_COUNTERPARTY_LOOKUP_LIMIT }); pushUnique(executedPrimitives, step.primitive_id); probeResults.push(queryResultToProbeResult(step.primitive_id, queryResult)); if (queryResult.error) { pushUnique(queryLimitations, queryResult.error); pushReason(reasonCodes, "pilot_search_business_entity_mcp_error"); } else { pushReason(reasonCodes, "pilot_search_business_entity_mcp_executed"); derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity); } continue; } if (step.primitive_id === "resolve_entity_reference") { if (!queryResult || queryResult.error) { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, entityResolutionFollowupStepLimitation())); continue; } if (!derivedEntityResolution) { derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity); } pushUnique(executedPrimitives, step.primitive_id); probeResults.push(buildEntityResolutionResolveProbeResult({ queryResult, resolution: derivedEntityResolution })); if (derivedEntityResolution?.resolution_status === "resolved") { pushReason(reasonCodes, "pilot_resolve_entity_reference_from_catalog_rows"); } else if (derivedEntityResolution?.resolution_status === "ambiguous") { pushReason(reasonCodes, "pilot_resolve_entity_reference_requires_clarification"); } else { pushReason(reasonCodes, "pilot_resolve_entity_reference_not_confirmed"); } continue; } if (step.primitive_id === "probe_coverage") { if (!queryResult || queryResult.error) { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, entityResolutionFollowupStepLimitation())); continue; } if (!derivedEntityResolution) { derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity); } pushUnique(executedPrimitives, step.primitive_id); probeResults.push(buildEntityResolutionCoverageProbeResult({ resolution: derivedEntityResolution })); pushReason(reasonCodes, "pilot_probe_coverage_executed_for_entity_resolution"); if (derivedEntityResolution?.resolution_status === "resolved") { pushReason(reasonCodes, "pilot_entity_resolution_grounding_stable_for_downstream_probe"); } else if (derivedEntityResolution?.resolution_status === "ambiguous") { pushReason(reasonCodes, "pilot_entity_resolution_coverage_requires_clarification"); } else { pushReason(reasonCodes, "pilot_entity_resolution_coverage_not_confirmed"); } continue; } skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_entity_resolution_step_not_implemented")); } const sourceRowsSummary = queryResult ? summarizeEntityResolutionRows(queryResult) : null; if (!derivedEntityResolution && queryResult && !queryResult.error) { derivedEntityResolution = deriveEntityResolution(queryResult, requestedEntity); } if (derivedEntityResolution?.resolution_status === "resolved") { pushReason(reasonCodes, "pilot_derived_entity_resolution_from_catalog_rows"); } if (derivedEntityResolution?.resolution_status === "ambiguous") { pushReason(reasonCodes, "pilot_entity_resolution_ambiguity_requires_clarification"); } if (derivedEntityResolution?.resolution_status === "not_found") { pushReason(reasonCodes, "pilot_entity_resolution_not_found_in_checked_catalog"); } const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: buildEntityResolutionConfirmedFacts(derivedEntityResolution), inferredFacts: buildEntityResolutionInferredFacts(derivedEntityResolution), unknownFacts: buildEntityResolutionUnknownFacts(derivedEntityResolution, requestedEntity), sourceRowsSummary, queryLimitations, recommendedNextProbe: null }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: "entity_resolution_search_v1", dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: derivedEntityResolution, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; } if (documentPilotEligible) { let queryResult = null; const filters = buildLifecycleFilters(planner); const selection = (0, addressRecipeCatalog_1.selectAddressRecipe)("list_documents_by_counterparty", filters); if (!selection.selected_recipe) { pushReason(reasonCodes, "pilot_document_recipe_not_available"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Document-evidence recipe is not available"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: "counterparty_document_evidence_query_documents_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Document-evidence recipe is not available"], reason_codes: reasonCodes }; } const recipePlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(selection.selected_recipe, filters); for (const step of dryRun.execution_steps) { if (step.primitive_id !== "query_documents") { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_only_executes_query_documents")); continue; } queryResult = await runtimeDeps.executeAddressMcpQuery({ query: recipePlan.query, limit: recipePlan.limit, account_scope: recipePlan.account_scope }); executedPrimitives.push(step.primitive_id); probeResults.push(queryResultToProbeResult(step.primitive_id, queryResult)); if (queryResult.error) { pushUnique(queryLimitations, queryResult.error); pushReason(reasonCodes, "pilot_query_documents_mcp_error"); } else { pushReason(reasonCodes, "pilot_query_documents_mcp_executed"); } } const sourceRowsSummary = queryResult ? summarizeDocumentRows(queryResult) : null; const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: queryResult ? buildDocumentConfirmedFacts(queryResult, counterparty, dateScope) : [], inferredFacts: queryResult ? buildDocumentInferredFacts(queryResult, counterparty, dateScope) : [], unknownFacts: buildDocumentUnknownFacts(dateScope, counterparty), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: "counterparty_document_evidence_query_documents_v1", dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; } if (movementPilotEligible) { let queryResult = null; const filters = buildValueFlowFilters(planner); const selection = (0, addressRecipeCatalog_1.selectAddressRecipe)("bank_operations_by_counterparty", filters); if (!selection.selected_recipe) { pushReason(reasonCodes, "pilot_movement_recipe_not_available"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Movement-evidence recipe is not available"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: "counterparty_movement_evidence_query_movements_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Movement-evidence recipe is not available"], reason_codes: reasonCodes }; } const recipePlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(selection.selected_recipe, filters); for (const step of dryRun.execution_steps) { if (step.primitive_id !== "query_movements") { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_only_executes_query_movements")); continue; } queryResult = await runtimeDeps.executeAddressMcpQuery({ query: recipePlan.query, limit: recipePlan.limit, account_scope: recipePlan.account_scope }); executedPrimitives.push(step.primitive_id); probeResults.push(queryResultToProbeResult(step.primitive_id, queryResult)); if (queryResult.error) { pushUnique(queryLimitations, queryResult.error); pushReason(reasonCodes, "pilot_query_movements_mcp_error"); } else { pushReason(reasonCodes, "pilot_query_movements_mcp_executed"); } } const sourceRowsSummary = queryResult ? summarizeMovementRows(queryResult) : null; const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: queryResult ? buildMovementConfirmedFacts(queryResult, counterparty, dateScope) : [], inferredFacts: queryResult ? buildMovementInferredFacts(queryResult, counterparty, dateScope) : [], unknownFacts: buildMovementUnknownFacts(dateScope, counterparty), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: "counterparty_movement_evidence_query_movements_v1", dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; } if (valueFlowPilotEligible) { let queryResult = null; const filters = buildValueFlowFilters(planner); const valueFlowProfile = valueFlowPilotProfile(planner); if (valueFlowProfile.direction === "bidirectional_net_value_flow") { let incomingResult = null; let outgoingResult = null; const incomingSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("customer_revenue_and_payments", filters); const outgoingSelection = (0, addressRecipeCatalog_1.selectAddressRecipe)("supplier_payouts_profile", filters); if (!incomingSelection.selected_recipe || !outgoingSelection.selected_recipe) { pushReason(reasonCodes, "pilot_bidirectional_value_flow_recipe_not_available"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Bidirectional value-flow recipes are not available"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: valueFlowProfile.scope, dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Bidirectional value-flow recipes are not available"], reason_codes: reasonCodes }; } pushReason(reasonCodes, "pilot_bidirectional_value_flow_recipes_selected"); for (const step of dryRun.execution_steps) { if (step.primitive_id !== "query_movements") { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_bidirectional_value_flow_uses_two_query_movements_and_derives_net")); continue; } const incomingExecution = await executeCoverageAwareValueFlowQuery({ primitiveId: step.primitive_id, recipePlanBuilder: (scopedFilters) => (0, addressRecipeCatalog_1.buildAddressRecipePlan)(incomingSelection.selected_recipe, scopedFilters), baseFilters: filters, dateScope, maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count, maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe, deps: runtimeDeps }); const outgoingExecution = await executeCoverageAwareValueFlowQuery({ primitiveId: step.primitive_id, recipePlanBuilder: (scopedFilters) => (0, addressRecipeCatalog_1.buildAddressRecipePlan)(outgoingSelection.selected_recipe, scopedFilters), baseFilters: filters, dateScope, maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count, maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe, deps: runtimeDeps }); incomingResult = incomingExecution.result; outgoingResult = outgoingExecution.result; pushUnique(executedPrimitives, step.primitive_id); probeResults.push(...incomingExecution.probe_results, ...outgoingExecution.probe_results); for (const limitation of [...incomingExecution.query_limitations, ...outgoingExecution.query_limitations]) { pushUnique(queryLimitations, limitation); } if (incomingResult?.error) { pushReason(reasonCodes, "pilot_bidirectional_incoming_query_movements_mcp_error"); } if (outgoingResult?.error) { pushReason(reasonCodes, "pilot_bidirectional_outgoing_query_movements_mcp_error"); } if (incomingResult?.coverage_recovered_by_period_chunking) { pushReason(reasonCodes, "pilot_bidirectional_incoming_monthly_period_chunking_recovered_coverage"); } if (outgoingResult?.coverage_recovered_by_period_chunking) { pushReason(reasonCodes, "pilot_bidirectional_outgoing_monthly_period_chunking_recovered_coverage"); } if (!incomingResult?.error || !outgoingResult?.error) { pushReason(reasonCodes, "pilot_bidirectional_query_movements_mcp_executed"); } } const sourceRowsSummary = summarizeBidirectionalValueFlowRows({ incomingResult, outgoingResult }); const derivedBidirectionalValueFlow = deriveBidirectionalValueFlow({ incomingResult, outgoingResult, counterparty, periodScope: dateScope, aggregationAxis }); if (derivedBidirectionalValueFlow) { pushReason(reasonCodes, "pilot_derived_bidirectional_value_flow_from_confirmed_rows"); if (aggregationAxis === "month" && derivedBidirectionalValueFlow.monthly_breakdown.length > 0) { pushReason(reasonCodes, "pilot_derived_bidirectional_monthly_breakdown_from_confirmed_rows"); } } const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: buildBidirectionalValueFlowConfirmedFacts(derivedBidirectionalValueFlow), inferredFacts: buildBidirectionalValueFlowInferredFacts(derivedBidirectionalValueFlow), unknownFacts: buildBidirectionalValueFlowUnknownFacts(dateScope, derivedBidirectionalValueFlow), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: valueFlowProfile.scope, dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: derivedBidirectionalValueFlow, query_limitations: queryLimitations, reason_codes: reasonCodes }; } const recipeIntent = valueFlowProfile.recipe_intent; const selection = recipeIntent ? (0, addressRecipeCatalog_1.selectAddressRecipe)(recipeIntent, filters) : { selected_recipe: null }; if (!selection.selected_recipe) { pushReason(reasonCodes, "pilot_value_flow_recipe_not_available"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Value-flow recipe is not available"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: valueFlowProfile.scope, dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Value-flow recipe is not available"], reason_codes: reasonCodes }; } pushReason(reasonCodes, valueFlowProfile.direction === "outgoing_supplier_payout" ? "pilot_supplier_payout_recipe_selected" : "pilot_customer_revenue_recipe_selected"); for (const step of dryRun.execution_steps) { if (step.primitive_id !== "query_movements") { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_value_flow_uses_query_movements_and_derives_aggregate")); continue; } const execution = await executeCoverageAwareValueFlowQuery({ primitiveId: step.primitive_id, recipePlanBuilder: (scopedFilters) => (0, addressRecipeCatalog_1.buildAddressRecipePlan)(selection.selected_recipe, scopedFilters), baseFilters: filters, dateScope, maxProbeCount: planner.discovery_plan.execution_budget.max_probe_count, maxRowsPerProbe: planner.discovery_plan.execution_budget.max_rows_per_probe, deps: runtimeDeps }); queryResult = execution.result; pushUnique(executedPrimitives, step.primitive_id); probeResults.push(...execution.probe_results); for (const limitation of execution.query_limitations) { pushUnique(queryLimitations, limitation); } if (queryResult?.error) { pushReason(reasonCodes, "pilot_query_movements_mcp_error"); } else { pushReason(reasonCodes, "pilot_query_movements_mcp_executed"); } if (queryResult?.coverage_recovered_by_period_chunking) { pushReason(reasonCodes, "pilot_monthly_period_chunking_recovered_coverage"); } } const sourceRowsSummary = queryResult ? summarizeValueFlowRows(queryResult) : null; if (planner.selected_chain_id === "value_flow_ranking" && rankingNeed) { const derivedRankedValueFlow = deriveRankedValueFlow(queryResult, { organizationScope, periodScope: dateScope, direction: valueFlowProfile.direction, rankingNeed }); if (derivedRankedValueFlow) { pushReason(reasonCodes, "pilot_derived_ranked_value_flow_from_confirmed_rows"); } const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: buildRankedValueFlowConfirmedFacts(derivedRankedValueFlow), inferredFacts: buildRankedValueFlowInferredFacts(derivedRankedValueFlow), unknownFacts: buildRankedValueFlowUnknownFacts(dateScope, derivedRankedValueFlow), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: valueFlowProfile.scope, dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_ranked_value_flow: derivedRankedValueFlow, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; } const derivedValueFlow = deriveValueFlow(queryResult, counterparty, dateScope, valueFlowProfile.direction, aggregationAxis); if (derivedValueFlow) { pushReason(reasonCodes, "pilot_derived_value_flow_from_confirmed_rows"); if (aggregationAxis === "month" && derivedValueFlow.monthly_breakdown.length > 0) { pushReason(reasonCodes, "pilot_derived_value_flow_monthly_breakdown_from_confirmed_rows"); } } const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: queryResult ? buildValueFlowConfirmedFacts(queryResult, counterparty, valueFlowProfile.direction) : [], inferredFacts: buildValueFlowInferredFacts(derivedValueFlow), unknownFacts: buildValueFlowUnknownFacts(dateScope, valueFlowProfile.direction, derivedValueFlow), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: valueFlowProfile.scope, dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_ranked_value_flow: null, derived_value_flow: derivedValueFlow, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; } let queryResult = null; const filters = buildLifecycleFilters(planner); const selection = (0, addressRecipeCatalog_1.selectAddressRecipe)("counterparty_activity_lifecycle", filters); if (!selection.selected_recipe) { pushReason(reasonCodes, "pilot_lifecycle_recipe_not_available"); const evidence = buildEmptyEvidence(planner, dryRun, probeResults, "Lifecycle recipe is not available"); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "unsupported", pilot_scope: "counterparty_lifecycle_query_documents_v1", dry_run: dryRun, mcp_execution_performed: false, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: null, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: null, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: ["Lifecycle recipe is not available"], reason_codes: reasonCodes }; } const recipePlan = (0, addressRecipeCatalog_1.buildAddressRecipePlan)(selection.selected_recipe, filters); for (const step of dryRun.execution_steps) { if (step.primitive_id !== "query_documents") { skippedPrimitives.push(step.primitive_id); probeResults.push(skippedProbeResult(step, "pilot_only_executes_query_documents")); continue; } queryResult = await runtimeDeps.executeAddressMcpQuery({ query: recipePlan.query, limit: recipePlan.limit, account_scope: recipePlan.account_scope }); executedPrimitives.push(step.primitive_id); probeResults.push(queryResultToProbeResult(step.primitive_id, queryResult)); if (queryResult.error) { pushUnique(queryLimitations, queryResult.error); pushReason(reasonCodes, "pilot_query_documents_mcp_error"); } else { pushReason(reasonCodes, "pilot_query_documents_mcp_executed"); } } const sourceRowsSummary = queryResult ? summarizeLifecycleRows(queryResult) : null; const derivedActivityPeriod = deriveActivityPeriod(queryResult); if (derivedActivityPeriod) { pushReason(reasonCodes, "pilot_derived_activity_period_from_confirmed_rows"); } const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({ plan: planner.discovery_plan, probeResults, confirmedFacts: queryResult ? buildLifecycleConfirmedFacts(queryResult, counterparty) : [], inferredFacts: queryResult ? buildLifecycleInferredFacts(queryResult) : [], unknownFacts: buildLifecycleUnknownFacts(), sourceRowsSummary, queryLimitations, recommendedNextProbe: "explain_evidence_basis" }); return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryPilotExecutor", pilot_status: "executed", pilot_scope: "counterparty_lifecycle_query_documents_v1", dry_run: dryRun, mcp_execution_performed: executedPrimitives.length > 0, executed_primitives: executedPrimitives, skipped_primitives: skippedPrimitives, probe_results: probeResults, evidence, source_rows_summary: sourceRowsSummary, derived_metadata_surface: null, derived_entity_resolution: null, derived_activity_period: derivedActivityPeriod, derived_value_flow: null, derived_bidirectional_value_flow: null, query_limitations: queryLimitations, reason_codes: reasonCodes }; }