Open-World: закрепить реестр недостающих доказательств бизнес-обзора

This commit is contained in:
dctouch 2026-05-05 13:41:49 +03:00
parent 42283a6ac2
commit c0a89ccece
9 changed files with 307 additions and 32 deletions

View File

@ -38,8 +38,9 @@ If another document says `78%`, `87%`, `92%`, or `85%` for a module that is now
- Completed active slice: `Business Overview Supplier/Procurement Quality Boundary Bridge`: organization-level supplier concentration, vendor-risk, dependency, and procurement-quality wording now routes to `business_overview`, while supplier payment/open-settlement/doc questions stay in exact supplier/payables routes with a vendor-risk proof boundary.
- Completed active slice: `Business Overview Document/Account Activity Profile Bridge`: business overview now executes the reviewed `document_type_and_account_section_profile` recipe and surfaces confirmed operational activity mix without claiming process quality, accounting correctness, or complete 1C activity coverage.
- Completed active slice: `Business Overview Counterparty/Contract Profile Bridge`: business overview now executes reviewed `counterparty_population_and_roles` and `contract_usage_overview` recipes, surfacing active counterparty role split and contract usage without claiming CRM quality, counterparty due diligence, legal completeness, or contract-risk.
- Completed active slice: `Business Overview Missing Proof Ledger`: business overview now records machine-readable hard proof gaps for accounting profit/margin, due-date debt aging, inventory reserve/liquidation quality, and vendor/procurement quality, distinguishing proxy-only evidence from reviewed routes that are not wired yet.
- Next active slice: continue breadth into exact company-wide accounting profit/margin, real due-date debt aging, confirmed inventory reserve/write-off/liquidation evidence, and broader unfamiliar 1C route families only where reviewed evidence routes exist.
- Active module progress: `~98% (Open-World Bounded Autonomy Breadth)`.
- Active module progress: `~99% (Open-World Bounded Autonomy Breadth)`.
## Reporting Rule
@ -76,7 +77,7 @@ The project is not yet a universal arbitrary-1C agent.
Remaining work belongs to the next breadth module:
- extend `business_overview` beyond money-flow/activity, customer and supplier concentration, document/account-section activity mix, counterparty role split, contract usage, yearly operating-flow dynamics, explicit profit/margin wording boundaries, explicit debt due-date wording boundaries, explicit inventory reserve/liquidation wording boundaries, explicit supplier/procurement-quality wording boundaries, explicit-period VAT/tax, as-of-date debt position, open-settlement concentration, contract-date debt age, debt staleness-risk proxy, as-of-date inventory position, trading-margin proxy, sales-to-stock inventory proxy, and warehouse staleness-risk proxy into separately proven exact accounting profit/margin, due-date debt aging/overdue, confirmed vendor-risk/procurement-quality analysis, and confirmed reserve/write-off/liquidation inventory evidence families;
- extend `business_overview` beyond money-flow/activity, customer and supplier concentration, document/account-section activity mix, counterparty role split, contract usage, yearly operating-flow dynamics, explicit profit/margin wording boundaries, explicit debt due-date wording boundaries, explicit inventory reserve/liquidation wording boundaries, explicit supplier/procurement-quality wording boundaries, explicit-period VAT/tax, as-of-date debt position, open-settlement concentration, contract-date debt age, debt staleness-risk proxy, as-of-date inventory position, trading-margin proxy, sales-to-stock inventory proxy, warehouse staleness-risk proxy, and the missing-proof ledger into separately proven exact accounting profit/margin, due-date debt aging/overdue, confirmed vendor-risk/procurement-quality analysis, and confirmed reserve/write-off/liquidation inventory evidence families;
- broader dynamic schema traversal for unfamiliar 1C asks;
- more primitive descriptors where live evidence proves a real gap;
- more replay-backed domain packs that start from user business meaning, not from route convenience;

View File

@ -697,3 +697,34 @@ Local validation is accepted for this slice:
- `npm.cmd run build`: passed.
Graphify rebuild after Slice 24 code/doc sync: `6069 nodes`, `13230 edges`, `140 communities`.
## Slice 25 - Business Overview Missing Proof Ledger
This slice hardens the last high-risk semantic edge before the module can be treated as nearly closed: broad company analysis now carries a machine-readable ledger of the proof families that are still missing, instead of relying only on prose boundaries.
The important distinction is not "can we say something useful?" because the current overview already can. The distinction is whether downstream answer drafting and future route expansion can reliably tell:
- what was actually checked in the current turn;
- what is only a bounded proxy;
- what still has no reviewed route wired into runtime;
- what must never be promoted into a confirmed business-audit conclusion.
Implemented now:
- `derived_business_overview.missing_proof_families` records the remaining hard proof families for accounting profit/margin, due-date debt aging, inventory reserve/liquidation quality, and vendor-risk/procurement quality;
- each missing proof family exposes `current_status`, `current_supported_evidence`, `next_required_evidence`, and `must_not_claim`;
- trading-margin evidence is explicitly recorded as `proxy_only_currently` for accounting profit/margin, not as clean profit or P&L;
- open-settlement/debt-staleness evidence is explicitly recorded as proxy-only for due-date aging, not as contractual overdue debt;
- inventory stock/turnover/staleness evidence is explicitly recorded as proxy-only for reserves, write-offs, obsolescence, and liquidation value;
- supplier concentration is explicitly recorded as proxy-only for vendor/procurement quality, not as supplier reliability or full expense-structure proof;
- the answer adapter adds a guard reason code and a `must_not_claim` rule so the proof ledger itself is not mistaken for an executed route.
This is not a new exact P&L, payment-term, reserve/write-off, or vendor-risk engine. It is a semantic safety ledger for the remaining exact-route work: future slices can either wire a reviewed evidence route or keep the family honestly unproved.
Local validation is accepted for this slice:
- `npm.cmd test -- assistantMcpDiscoveryPilotExecutor.test.ts assistantMcpDiscoveryAnswerAdapter.test.ts`: passed `66` with `1` skipped.
- `npm.cmd test -- addressQueryRuntimeM23.test.ts`: passed `416`.
- `npm.cmd run build`: passed.
Graphify rebuild after Slice 25 code/doc sync: `6070 nodes`, `13233 edges`, `135 communities`.

View File

@ -73,6 +73,7 @@ Status canon for planning:
- The current completed breadth slice is `Business Overview Supplier/Procurement Quality Boundary Bridge`: organization-level supplier concentration, vendor-risk, dependency, and procurement-quality wording now reaches `business_overview`, while supplier payment/open-settlement/doc questions stay in exact supplier/payables routes with a vendor-risk proof boundary.
- The current completed breadth slice is `Business Overview Document/Account Activity Profile Bridge`: business overview now executes the reviewed document-type/account-section profile and can surface confirmed operational activity mix without claiming process quality, accounting correctness, or full 1C coverage.
- The current completed breadth slice is `Business Overview Counterparty/Contract Profile Bridge`: business overview now executes reviewed counterparty population/roles and contract usage profiles, while CRM quality, counterparty due diligence, legal completeness, and contract-risk remain unclaimed.
- The current completed breadth slice is `Business Overview Missing Proof Ledger`: business overview now records hard remaining proof gaps as machine-readable `missing_proof_families`, separating proxy-only evidence from reviewed routes that are not wired yet.
- The next active breadth slice continues breadth into exact company-wide accounting profit/margin, real due-date debt aging, confirmed reserve/write-off/liquidation inventory evidence, and broader unfamiliar 1C route families without relaxing truth boundaries.
- The short source of truth for status wording is [21 - current_status_canon_2026-05-01.md](./21%20-%20current_status_canon_2026-05-01.md).
@ -138,11 +139,11 @@ Current honest status:
- pre-multidomain readiness: `~90%`
- bounded-autonomy foundation readiness: `~89%`
- open-world bounded-autonomy readiness: `~87%`
- active Open-World Bounded Autonomy Breadth progress: `~98%`, with business-overview evidence fusion, the reviewed `business_overview` catalog/data-need/planner route-fabric slice, the fresh multi-probe runtime bridge, the explicit-period VAT/tax fact-family bridge, the explicit-period debt-position bridge, the explicit-date inventory-position bridge, the open-settlement quality bridge accepted by live semantic replay, selected-item profitability bridged by local semantic/runtime regression tests, contract-date debt age bridged locally, debt staleness-risk proxy bridged locally, debt due-date boundary arbitration bridged locally, inventory reserve/liquidation boundary arbitration bridged locally, supplier/procurement-quality boundary arbitration bridged locally, supplier concentration proxy bridged locally, document/account-section activity profile bridged locally, counterparty population/roles and contract usage profiles bridged locally, yearly operating-flow proxy bridged locally, earnings/best-year wording arbitration bridged locally, profit/margin wording boundary arbitration bridged locally, analyst synthesis added to business-overview answer drafting, company-period trading margin proxy bridged locally, inventory sales-to-stock proxy bridged locally, inventory staleness-risk proxy bridged locally, and gap-specific answer shaping bridged locally; exact accounting profit/margin, true due-date debt aging/overdue, confirmed vendor-risk/procurement-quality analysis, and confirmed reserve/write-off/liquidation inventory evidence are still pending
- active Open-World Bounded Autonomy Breadth progress: `~99%`, with business-overview evidence fusion, the reviewed `business_overview` catalog/data-need/planner route-fabric slice, the fresh multi-probe runtime bridge, the explicit-period VAT/tax fact-family bridge, the explicit-period debt-position bridge, the explicit-date inventory-position bridge, the open-settlement quality bridge accepted by live semantic replay, selected-item profitability bridged by local semantic/runtime regression tests, contract-date debt age bridged locally, debt staleness-risk proxy bridged locally, debt due-date boundary arbitration bridged locally, inventory reserve/liquidation boundary arbitration bridged locally, supplier/procurement-quality boundary arbitration bridged locally, supplier concentration proxy bridged locally, document/account-section activity profile bridged locally, counterparty population/roles and contract usage profiles bridged locally, yearly operating-flow proxy bridged locally, earnings/best-year wording arbitration bridged locally, profit/margin wording boundary arbitration bridged locally, analyst synthesis added to business-overview answer drafting, company-period trading margin proxy bridged locally, inventory sales-to-stock proxy bridged locally, inventory staleness-risk proxy bridged locally, gap-specific answer shaping bridged locally, and missing proof families recorded as runtime evidence ledger; exact accounting profit/margin, true due-date debt aging/overdue, confirmed vendor-risk/procurement-quality analysis, and confirmed reserve/write-off/liquidation inventory evidence are still pending
- Post-F semantic integrity module progress: `~99%` operationally closed, with remaining risk now treated as next-slice discovery rather than an open blocker inside the closed slice
- active inventory-stock breadth slice progress: `100%` for the declared scenario pack, not for arbitrary inventory questions
- Planner Autonomy Consolidation progress: `100%` for the declared module, with catalog-fabric, value-flow arbitration, lifecycle bounded inference, broad-evaluation bridge, inventory catalog templates, inventory runtime-boundary honesty, exact inventory recipe bridging, unambiguous metadata-surface lane inference, catalog chain-template scoring, structured chain-match contract exposure, runtime/debug propagation, subject-aware bidirectional comparison arbitration, structured catalog-alignment verdicts, representative alignment regression guard, catalog-alignment reason-code telemetry, explicit `alignment_status` propagation, truth-harness/acceptance-matrix surfacing, soft divergence warning, `catalog_alignment_ok` acceptance invariant, step-level expected catalog-alignment assertions, phase66 and phase32 spec alignment expectations, AGENT source-catalog surfacing, generated phase83 mixed planner-brain replay spec, checked-source user-facing error sanitation, surface-grounded catalog promotion, and guarded live phase83 acceptance validated. Broader unfamiliar 1C asks are now next-module breadth work rather than an open blocker inside this declared slice
- graph snapshot after latest rebuild: `6069 nodes`, `13230 edges`, `140 communities`
- graph snapshot after latest rebuild: `6070 nodes`, `13233 edges`, `135 communities`
- current regression-gate breakpoint:
- the validated hot paths are no longer structurally broken;
- flagship continuity collapse is no longer the primary risk;
@ -196,6 +197,7 @@ Latest live proof now includes:
- business-overview debt staleness-risk proxy accepted locally: targeted executor/answer-adapter slice passed `66/66` with `1` skipped; M23 route/runtime regression passed `412/412`; build passed; graphify rebuilt to `6040 nodes`, `13158 edges`, `135 communities`; the proxy combines contract-date age and open-balance concentration while confirmed overdue debt, contractual delinquency, credit risk, and due-date aging remain unclaimed
- business-overview supplier concentration proxy accepted locally: targeted executor/answer-adapter slice passed `66/66` with `1` skipped; M23 route/runtime regression passed `412/412`; build passed; graphify rebuilt to `6041 nodes`, `13162 edges`, `136 communities`; the proxy ranks confirmed outgoing payment counterparties while vendor risk, procurement quality, and full expense structure remain unclaimed
- business-overview yearly operating-flow proxy accepted locally: targeted executor/answer-adapter slice passed `66/66` with `1` skipped; M23 route/runtime regression passed `412/412`; build passed; graphify rebuilt to `6047 nodes`, `13177 edges`, `139 communities`; the proxy builds annual incoming/outgoing/net buckets from confirmed money-flow rows while profit, финрезультат, and full P&L remain unclaimed
- business-overview missing proof ledger accepted locally: targeted executor/answer-adapter slice passed `66/66` with `1` skipped; M23 route/runtime regression passed `416/416`; build passed; graphify count is recorded in the current graph snapshot; hard remaining proof gaps are now visible as machine-readable `missing_proof_families` rather than only prose warnings
- business-overview earnings wording arbitration accepted locally: turn-meaning/turn-input slice passed `85/85` with `6` skipped; M23 route/runtime regression passed `412/412`; runtime-entry/pilot/answer slice passed `85/85` with `3` skipped; build passed; graphify rebuilt to `6052 nodes`, `13187 edges`, `138 communities`; organization-level earnings/best-year wording now reaches `business_overview` while explicit customer/counterparty ranking remains in exact customer value routes
- inventory template lift accepted locally: catalog/data-need/planner/turn-input slice passed `139/139` with `6` skipped; full MCP-discovery slice passed `276/276` with `9` skipped; build passed; graphify stayed at `5912 nodes`, `12833 edges`, `138 communities`
- inventory runtime-boundary hardening accepted locally: runtime-bridge/answer-adapter/pilot-executor slice passed `68/68` with `1` skipped; full MCP-discovery slice passed `277/277` with `9` skipped; build passed; graphify rebuilt to `5913 nodes`, `12837 edges`, `138 communities`

View File

@ -639,6 +639,9 @@ function buildMustNotClaim(pilot) {
claims.push("Do not present an inventory snapshot or purchase-date aging signal as turnover, obsolescence, liquidation value, or full inventory health.");
claims.push("Do not present business overview inventory turnover proxy as full inventory liquidity, FIFO turnover, obsolescence analysis, or liquidation value.");
claims.push("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
if (pilot.derived_business_overview?.missing_proof_families?.length) {
claims.push("Do not present business overview missing proof families as checked, executed, or confirmed routes.");
}
claims.push("Do not expose business_overview_route_template_v1 or MCP primitive names in the user answer.");
}
if (pilot.derived_ranked_value_flow) {
@ -1352,6 +1355,9 @@ function buildAssistantMcpDiscoveryAnswerDraft(pilot) {
if (pilot.derived_business_overview?.inventory_staleness_risk_proxy) {
pushReason(reasonCodes, "answer_contains_business_overview_inventory_staleness_risk_proxy");
}
if (pilot.derived_business_overview?.missing_proof_families?.length) {
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
}
const confirmedLines = businessOverviewLines.length > 0
? businessOverviewLines
: pilot.derived_ranked_value_flow && derivedValueLine

View File

@ -2740,6 +2740,75 @@ function inventoryStalenessRiskBandRu(riskBand) {
}
return "низкий видимый риск";
}
function buildBusinessOverviewMissingProofFamilies(input) {
const missing = new Set(input.missingSignalFamilies);
const items = [];
const pushUnique = (item) => {
if (!items.some((existing) => existing.family === item.family)) {
items.push(item);
}
};
if (missing.has("profit_margin") || missing.has("accounting_profit_margin")) {
pushUnique({
family: "accounting_profit_margin",
current_status: input.tradingMarginProxy ? "proxy_only_currently" : "reviewed_route_not_wired",
current_supported_evidence: input.tradingMarginProxy
? "trading_margin_proxy_from_sales_and_purchase_document_rows"
: null,
next_required_evidence: "reviewed_pnl_route_with_cost_of_sales_expenses_period_close_and_financial_result",
must_not_claim: "clean_profit_accounting_margin_or_full_pnl"
});
}
if (missing.has("debt_due_date_aging_quality") || missing.has("debt_open_settlement_quality")) {
pushUnique({
family: "debt_due_date_aging_quality",
current_status: input.debtStalenessRiskProxy
? "proxy_only_currently"
: input.debtOpenSettlementQuality
? "proxy_only_currently"
: "not_checked_in_current_turn",
current_supported_evidence: input.debtStalenessRiskProxy
? "debt_staleness_risk_proxy_from_contract_dates_and_open_balance_concentration"
: input.debtOpenSettlementQuality
? "open_settlement_quality_from_60_62_76_balances_without_payment_terms"
: null,
next_required_evidence: "reviewed_payment_term_or_due_date_route_with_contractual_due_dates_and_settlement_status",
must_not_claim: "confirmed_overdue_debt_credit_risk_or_due_date_aging"
});
}
if (missing.has("inventory_position") ||
missing.has("inventory_turnover_quality") ||
missing.has("inventory_liquidity_quality") ||
missing.has("inventory_reserve_liquidation_quality")) {
pushUnique({
family: "inventory_reserve_liquidation_quality",
current_status: input.inventoryStalenessRiskProxy
? "proxy_only_currently"
: input.inventoryTurnoverProxy || input.inventoryPosition
? "proxy_only_currently"
: "not_checked_in_current_turn",
current_supported_evidence: input.inventoryStalenessRiskProxy
? "inventory_staleness_risk_proxy_from_purchase_age_and_sales_to_stock"
: input.inventoryTurnoverProxy
? "inventory_turnover_proxy_from_sales_documents_and_stock_balance"
: input.inventoryPosition
? "inventory_on_hand_snapshot_without_reserve_writeoff_or_liquidation_evidence"
: null,
next_required_evidence: "reviewed_inventory_quality_route_with_reserves_writeoffs_obsolescence_and_liquidation_value",
must_not_claim: "confirmed_obsolete_stock_reserve_writeoff_or_liquidation_value"
});
}
if (input.hasSupplierConcentrationSignal) {
pushUnique({
family: "vendor_risk_procurement_quality",
current_status: "proxy_only_currently",
current_supported_evidence: "supplier_concentration_proxy_from_confirmed_outgoing_payment_rows",
next_required_evidence: "reviewed_vendor_risk_route_with_supplier_reliability_terms_quality_and_full_expense_structure",
must_not_claim: "vendor_risk_procurement_quality_supplier_reliability_or_full_expense_structure"
});
}
return items;
}
function deriveBusinessOverview(input) {
const incoming = deriveValueFlowSideSummary(input.incomingResult);
const outgoing = deriveValueFlowSideSummary(input.outgoingResult);
@ -2809,6 +2878,30 @@ function deriveBusinessOverview(input) {
}
const netAmount = incoming.total_amount - outgoing.total_amount;
const hasBusinessOverviewProfileSignal = Boolean(documentActivityProfile || counterpartyProfile || contractUsageProfile);
const missingSignalFamilies = [
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));
const missingProofFamilies = buildBusinessOverviewMissingProofFamilies({
missingSignalFamilies,
tradingMarginProxy,
debtOpenSettlementQuality,
debtStalenessRiskProxy,
inventoryPosition,
inventoryTurnoverProxy,
inventoryStalenessRiskProxy,
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
});
return {
organization_scope: input.organizationScope,
period_scope: input.periodScope,
@ -2834,20 +2927,8 @@ function deriveBusinessOverview(input) {
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)),
missing_signal_families: missingSignalFamilies,
missing_proof_families: missingProofFamilies,
inference_basis: hasBusinessOverviewProfileSignal || inventoryPosition
? "business_overview_from_confirmed_1c_multi_family_rows"
: debtOpenSettlementQuality
@ -4177,6 +4258,9 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_staleness_risk_proxy_from_confirmed_rows");
}
if (derivedBusinessOverview.missing_proof_families.length > 0) {
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
}
}
const sourceRowsSummary = summarizeBusinessOverviewRows({
incomingResult,

View File

@ -748,6 +748,9 @@ function buildMustNotClaim(pilot: AssistantMcpDiscoveryPilotExecutionContract):
claims.push("Do not present an inventory snapshot or purchase-date aging signal as turnover, obsolescence, liquidation value, or full inventory health.");
claims.push("Do not present business overview inventory turnover proxy as full inventory liquidity, FIFO turnover, obsolescence analysis, or liquidation value.");
claims.push("Do not present business overview inventory staleness risk proxy as confirmed obsolete stock, reserve, write-off, or liquidation value.");
if (pilot.derived_business_overview?.missing_proof_families?.length) {
claims.push("Do not present business overview missing proof families as checked, executed, or confirmed routes.");
}
claims.push("Do not expose business_overview_route_template_v1 or MCP primitive names in the user answer.");
}
if (pilot.derived_ranked_value_flow) {
@ -1569,6 +1572,9 @@ export function buildAssistantMcpDiscoveryAnswerDraft(
if (pilot.derived_business_overview?.inventory_staleness_risk_proxy) {
pushReason(reasonCodes, "answer_contains_business_overview_inventory_staleness_risk_proxy");
}
if (pilot.derived_business_overview?.missing_proof_families?.length) {
pushReason(reasonCodes, "answer_contains_business_overview_missing_proof_ledger");
}
const confirmedLines = businessOverviewLines.length > 0
? businessOverviewLines
: pilot.derived_ranked_value_flow && derivedValueLine

View File

@ -182,6 +182,23 @@ export interface AssistantMcpDiscoveryDerivedBusinessOverviewContractUsageProfil
inference_basis: "contract_usage_overview_confirmed_1c_rows";
}
export type AssistantMcpDiscoveryBusinessOverviewMissingProofFamilyId =
| "accounting_profit_margin"
| "debt_due_date_aging_quality"
| "inventory_reserve_liquidation_quality"
| "vendor_risk_procurement_quality";
export interface AssistantMcpDiscoveryBusinessOverviewMissingProofFamily {
family: AssistantMcpDiscoveryBusinessOverviewMissingProofFamilyId;
current_status:
| "not_checked_in_current_turn"
| "proxy_only_currently"
| "reviewed_route_not_wired";
current_supported_evidence: string | null;
next_required_evidence: string;
must_not_claim: string;
}
export interface AssistantMcpDiscoveryDerivedBidirectionalValueFlow {
counterparty: string | null;
period_scope: string | null;
@ -224,6 +241,7 @@ export interface AssistantMcpDiscoveryDerivedBusinessOverview {
coverage_limited_by_probe_limit: boolean;
checked_signal_count: number;
missing_signal_families: string[];
missing_proof_families: AssistantMcpDiscoveryBusinessOverviewMissingProofFamily[];
inference_basis:
| "business_overview_from_confirmed_1c_money_and_activity_rows"
| "business_overview_from_confirmed_1c_money_activity_and_tax_rows"
@ -3717,6 +3735,92 @@ function inventoryStalenessRiskBandRu(
return "низкий видимый риск";
}
function buildBusinessOverviewMissingProofFamilies(input: {
missingSignalFamilies: string[];
tradingMarginProxy: AssistantMcpDiscoveryDerivedBusinessOverviewTradingMarginProxy | null;
debtOpenSettlementQuality: AssistantMcpDiscoveryDerivedBusinessOverviewDebtOpenSettlementQuality | null;
debtStalenessRiskProxy: AssistantMcpDiscoveryDerivedBusinessOverviewDebtStalenessRiskProxy | null;
inventoryPosition: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
inventoryTurnoverProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryTurnoverProxy | null;
inventoryStalenessRiskProxy: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryStalenessRiskProxy | null;
hasSupplierConcentrationSignal: boolean;
}): AssistantMcpDiscoveryBusinessOverviewMissingProofFamily[] {
const missing = new Set(input.missingSignalFamilies);
const items: AssistantMcpDiscoveryBusinessOverviewMissingProofFamily[] = [];
const pushUnique = (item: AssistantMcpDiscoveryBusinessOverviewMissingProofFamily) => {
if (!items.some((existing) => existing.family === item.family)) {
items.push(item);
}
};
if (missing.has("profit_margin") || missing.has("accounting_profit_margin")) {
pushUnique({
family: "accounting_profit_margin",
current_status: input.tradingMarginProxy ? "proxy_only_currently" : "reviewed_route_not_wired",
current_supported_evidence: input.tradingMarginProxy
? "trading_margin_proxy_from_sales_and_purchase_document_rows"
: null,
next_required_evidence: "reviewed_pnl_route_with_cost_of_sales_expenses_period_close_and_financial_result",
must_not_claim: "clean_profit_accounting_margin_or_full_pnl"
});
}
if (missing.has("debt_due_date_aging_quality") || missing.has("debt_open_settlement_quality")) {
pushUnique({
family: "debt_due_date_aging_quality",
current_status: input.debtStalenessRiskProxy
? "proxy_only_currently"
: input.debtOpenSettlementQuality
? "proxy_only_currently"
: "not_checked_in_current_turn",
current_supported_evidence: input.debtStalenessRiskProxy
? "debt_staleness_risk_proxy_from_contract_dates_and_open_balance_concentration"
: input.debtOpenSettlementQuality
? "open_settlement_quality_from_60_62_76_balances_without_payment_terms"
: null,
next_required_evidence: "reviewed_payment_term_or_due_date_route_with_contractual_due_dates_and_settlement_status",
must_not_claim: "confirmed_overdue_debt_credit_risk_or_due_date_aging"
});
}
if (
missing.has("inventory_position") ||
missing.has("inventory_turnover_quality") ||
missing.has("inventory_liquidity_quality") ||
missing.has("inventory_reserve_liquidation_quality")
) {
pushUnique({
family: "inventory_reserve_liquidation_quality",
current_status: input.inventoryStalenessRiskProxy
? "proxy_only_currently"
: input.inventoryTurnoverProxy || input.inventoryPosition
? "proxy_only_currently"
: "not_checked_in_current_turn",
current_supported_evidence: input.inventoryStalenessRiskProxy
? "inventory_staleness_risk_proxy_from_purchase_age_and_sales_to_stock"
: input.inventoryTurnoverProxy
? "inventory_turnover_proxy_from_sales_documents_and_stock_balance"
: input.inventoryPosition
? "inventory_on_hand_snapshot_without_reserve_writeoff_or_liquidation_evidence"
: null,
next_required_evidence: "reviewed_inventory_quality_route_with_reserves_writeoffs_obsolescence_and_liquidation_value",
must_not_claim: "confirmed_obsolete_stock_reserve_writeoff_or_liquidation_value"
});
}
if (input.hasSupplierConcentrationSignal) {
pushUnique({
family: "vendor_risk_procurement_quality",
current_status: "proxy_only_currently",
current_supported_evidence: "supplier_concentration_proxy_from_confirmed_outgoing_payment_rows",
next_required_evidence: "reviewed_vendor_risk_route_with_supplier_reliability_terms_quality_and_full_expense_structure",
must_not_claim: "vendor_risk_procurement_quality_supplier_reliability_or_full_expense_structure"
});
}
return items;
}
function deriveBusinessOverview(input: {
incomingResult: AssistantMcpDiscoveryCoverageAwareQueryResult | null;
outgoingResult: AssistantMcpDiscoveryCoverageAwareQueryResult | null;
@ -3816,6 +3920,30 @@ function deriveBusinessOverview(input: {
const hasBusinessOverviewProfileSignal = Boolean(
documentActivityProfile || counterpartyProfile || contractUsageProfile
);
const missingSignalFamilies = [
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): item is string => Boolean(item));
const missingProofFamilies = buildBusinessOverviewMissingProofFamilies({
missingSignalFamilies,
tradingMarginProxy,
debtOpenSettlementQuality,
debtStalenessRiskProxy,
inventoryPosition,
inventoryTurnoverProxy,
inventoryStalenessRiskProxy,
hasSupplierConcentrationSignal: (rankedOutgoing?.ranked_values.length ?? 0) > 0
});
return {
organization_scope: input.organizationScope,
period_scope: input.periodScope,
@ -3842,20 +3970,8 @@ function deriveBusinessOverview(input: {
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): item is string => Boolean(item)),
missing_signal_families: missingSignalFamilies,
missing_proof_families: missingProofFamilies,
inference_basis:
hasBusinessOverviewProfileSignal || inventoryPosition
? "business_overview_from_confirmed_1c_multi_family_rows"
@ -5359,6 +5475,9 @@ export async function executeAssistantMcpDiscoveryPilot(
if (derivedBusinessOverview.inventory_staleness_risk_proxy) {
pushReason(reasonCodes, "pilot_derived_business_overview_inventory_staleness_risk_proxy_from_confirmed_rows");
}
if (derivedBusinessOverview.missing_proof_families.length > 0) {
pushReason(reasonCodes, "pilot_business_overview_missing_proof_families_recorded");
}
}
const sourceRowsSummary = summarizeBusinessOverviewRows({
incomingResult,

View File

@ -290,12 +290,14 @@ describe("assistant MCP discovery answer adapter", () => {
expect(draft.must_not_claim).toContain("Do not present business overview supplier concentration as vendor-risk audit, procurement quality, or full expense structure.");
expect(draft.must_not_claim).toContain("Do not present business overview document/account-section activity profile as process quality, accounting correctness, or completeness of all 1C activity.");
expect(draft.must_not_claim).toContain("Do not present business overview counterparty or contract profile as CRM quality, counterparty due diligence, contract-risk audit, or legal completeness.");
expect(draft.must_not_claim).toContain("Do not present business overview missing proof families as checked, executed, or confirmed routes.");
expect(draft.reason_codes).toContain("answer_contains_business_overview");
expect(draft.reason_codes).toContain("answer_contains_business_overview_supplier_concentration");
expect(draft.reason_codes).toContain("answer_contains_business_overview_yearly_operating_breakdown");
expect(draft.reason_codes).toContain("answer_contains_business_overview_document_activity_profile");
expect(draft.reason_codes).toContain("answer_contains_business_overview_counterparty_profile");
expect(draft.reason_codes).toContain("answer_contains_business_overview_contract_usage_profile");
expect(draft.reason_codes).toContain("answer_contains_business_overview_missing_proof_ledger");
expect(draft.reason_codes).toContain("answer_contains_business_overview_analyst_synthesis");
});

View File

@ -258,6 +258,20 @@ describe("assistant MCP discovery pilot executor", () => {
unused_contracts: 372,
used_contract_share_pct: 28.46
});
expect(result.derived_business_overview?.missing_proof_families).toEqual(
expect.arrayContaining([
expect.objectContaining({
family: "accounting_profit_margin",
current_status: "reviewed_route_not_wired",
current_supported_evidence: null
}),
expect.objectContaining({
family: "vendor_risk_procurement_quality",
current_status: "proxy_only_currently",
current_supported_evidence: "supplier_concentration_proxy_from_confirmed_outgoing_payment_rows"
})
])
);
expect(result.evidence.confirmed_facts.join("\n")).toContain("В 1С подтверждены входящие поступления");
expect(result.evidence.confirmed_facts.join("\n")).toContain("Самый крупный подтвержденный поставщик");
expect(result.evidence.confirmed_facts.join("\n")).toContain("Годовая раскладка операционного денежного потока");
@ -275,6 +289,7 @@ describe("assistant MCP discovery pilot executor", () => {
expect(result.reason_codes).toContain("pilot_derived_business_overview_document_activity_profile_from_confirmed_rows");
expect(result.reason_codes).toContain("pilot_derived_business_overview_counterparty_profile_from_confirmed_rows");
expect(result.reason_codes).toContain("pilot_derived_business_overview_contract_usage_profile_from_confirmed_rows");
expect(result.reason_codes).toContain("pilot_business_overview_missing_proof_families_recorded");
expect(deps.executeAddressMcpQuery).toHaveBeenCalledTimes(6);
});
@ -370,6 +385,15 @@ describe("assistant MCP discovery pilot executor", () => {
expect(result.derived_business_overview?.missing_signal_families).not.toContain("tax_position");
expect(result.derived_business_overview?.missing_signal_families).not.toContain("profit_margin");
expect(result.derived_business_overview?.missing_signal_families).toContain("accounting_profit_margin");
expect(result.derived_business_overview?.missing_proof_families).toEqual(
expect.arrayContaining([
expect.objectContaining({
family: "accounting_profit_margin",
current_status: "proxy_only_currently",
current_supported_evidence: "trading_margin_proxy_from_sales_and_purchase_document_rows"
})
])
);
expect(result.evidence.confirmed_facts.join("\n")).toContain("НДС-позиция за 2020 подтверждена");
expect(result.evidence.confirmed_facts.join("\n")).toContain("Торговый margin proxy за 2020");
expect(result.evidence.unknown_facts.join("\n")).toContain("Чистая прибыль");