704 lines
32 KiB
TypeScript
704 lines
32 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
import { applyAssistantMcpDiscoveryResponsePolicy } from "../src/services/assistantMcpDiscoveryResponsePolicy";
|
||
|
||
function entryPoint(overrides: Record<string, unknown> = {}) {
|
||
return {
|
||
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint",
|
||
entry_status: "bridge_executed",
|
||
hot_runtime_wired: false,
|
||
discovery_attempted: true,
|
||
turn_input: { adapter_status: "ready" },
|
||
bridge: {
|
||
bridge_status: "answer_draft_ready",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: true,
|
||
requires_user_clarification: false,
|
||
answer_draft: {
|
||
answer_mode: "confirmed_with_bounded_inference",
|
||
headline: "Confirmed scoped answer.",
|
||
confirmed_lines: ["Confirmed fact"],
|
||
inference_lines: ["Bounded inference"],
|
||
unknown_lines: ["Unconfirmed fact"],
|
||
limitation_lines: ["Limited source window"],
|
||
next_step_line: null
|
||
}
|
||
},
|
||
reason_codes: ["runtime_entry_point_bridge_executed"],
|
||
...overrides
|
||
} as any;
|
||
}
|
||
|
||
describe("assistant MCP discovery response policy", () => {
|
||
it("applies a guarded candidate only for unsupported current-turn boundary replies", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "route is not wired",
|
||
currentReplySource: "deterministic_unsupported_current_turn_boundary",
|
||
modeDecisionReason: "unsupported_current_turn_meaning_boundary",
|
||
addressRuntimeMeta: {
|
||
mcpDiscoveryRuntimeEntryPoint: entryPoint()
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.decision).toBe("apply_candidate");
|
||
expect(result.reply_source).toBe("mcp_discovery_response_candidate_guarded");
|
||
expect(result.reply_text).toContain("Confirmed fact");
|
||
expect(result.reply_text).not.toContain("query_documents");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_candidate_applied");
|
||
});
|
||
|
||
it("keeps the current reply when the turn is not an unsupported boundary", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "regular chat",
|
||
currentReplySource: "llm_chat",
|
||
modeDecisionReason: "living_chat_signal_detected",
|
||
addressRuntimeMeta: {
|
||
mcpDiscoveryRuntimeEntryPoint: entryPoint()
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reply_text).toBe("regular chat");
|
||
expect(result.reply_source).toBe("llm_chat");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_not_unsupported_boundary");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_not_discovery_ready_chat_candidate");
|
||
});
|
||
|
||
it("applies a guarded candidate for discovery-ready llm chat business answers", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "stale llm business answer",
|
||
currentReplySource: "llm_chat",
|
||
modeDecisionReason: "non_domain_query_indexed",
|
||
addressRuntimeMeta: {
|
||
mcpDiscoveryRuntimeEntryPoint: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.decision).toBe("apply_candidate");
|
||
expect(result.reply_source).toBe("mcp_discovery_response_candidate_guarded");
|
||
expect(result.reply_text).toContain("Confirmed fact");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_not_unsupported_boundary");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_not_discovery_ready_chat_candidate");
|
||
});
|
||
|
||
it("applies a guarded candidate for discovery-ready deep partial answers", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "wrong deep partial answer",
|
||
currentReplySource: "deep_analysis",
|
||
addressRuntimeMeta: {
|
||
mcpDiscoveryRuntimeEntryPoint: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.reply_source).toBe("mcp_discovery_response_candidate_guarded");
|
||
expect(result.reply_text).toContain("Confirmed fact");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_not_discovery_ready_deep_candidate");
|
||
});
|
||
|
||
it("applies a guarded candidate for discovery-ready address lane answers", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "stale exact route answer",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "list_documents_by_counterparty",
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "payout"
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.reply_source).toBe("mcp_discovery_response_candidate_guarded");
|
||
expect(result.reply_text).toContain("Confirmed fact");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_not_discovery_ready_address_candidate");
|
||
});
|
||
|
||
it("keeps exact matched inventory address replies over stale metadata discovery candidates", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "По товару Шкаф картотечный 1000*400*2100 цепочка поставки и продажи подтверждена.",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "inventory_purchase_to_sale_chain",
|
||
selected_recipe: "address_inventory_purchase_to_sale_chain_v1",
|
||
mcp_call_status: "matched_non_empty",
|
||
truth_mode: "confirmed",
|
||
capability_binding_status: "bound",
|
||
capability_binding_violations: [],
|
||
answer_shape_contract: {
|
||
reply_type: "factual",
|
||
capability_contract_id: "inventory_inventory_purchase_to_sale_chain"
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "metadata",
|
||
asked_action_family: "inspect_documents",
|
||
metadata_scope_hint: "склад"
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reply_text).toContain("цепочка поставки и продажи подтверждена");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_keep_exact_matched_factual_address_reply");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_semantic_conflict_allows_candidate_override");
|
||
});
|
||
|
||
it("keeps aligned factual address lane answers when the exact lane already matched the same semantic intent", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "ИП Калинин Н.М. | сумма: 216600 | операций: 2",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "customer_revenue_and_payments",
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "turnover"
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reply_text).toBe("ИП Калинин Н.М. | сумма: 216600 | операций: 2");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_keep_aligned_factual_address_reply");
|
||
});
|
||
|
||
it("does not treat an open-scope value-flow total as aligned with exact top-counterparty carryover", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "\u0421\u0430\u043c\u044b\u0439 \u0434\u043e\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442: \u0413\u0440\u0443\u043f\u043f\u0430 \u0421\u0412\u041a.",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "customer_revenue_and_payments",
|
||
selected_recipe: "address_customer_revenue_and_payments_v1",
|
||
mcp_call_status: "matched_non_empty",
|
||
truth_mode: "confirmed",
|
||
capability_binding_status: "bound",
|
||
capability_binding_violations: [],
|
||
dialogContinuationContract: {
|
||
target_intent: "customer_revenue_and_payments"
|
||
},
|
||
truth_gate_contract_status: "full_confirmed",
|
||
assistant_truth_answer_policy_v1: {
|
||
truth_gate: {
|
||
coverage_status: "full",
|
||
grounding_status: "grounded",
|
||
source_truth_gate_status: "full_confirmed"
|
||
}
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
data_need_graph: {
|
||
business_fact_family: "value_flow",
|
||
subject_candidates: [],
|
||
reason_codes: ["data_need_graph_open_scope_total_without_subject"]
|
||
},
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "turnover",
|
||
explicit_organization_scope: "\u041e\u041e\u041e \u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u041f\u043b\u044e\u0441",
|
||
explicit_date_scope: "2020"
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.decision).toBe("apply_candidate");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_semantic_conflict_allows_candidate_override");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_aligned_factual_address_reply");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_factual_address_continuation_target");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_full_confirmed_factual_address_reply");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_exact_matched_factual_address_reply");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_open_scope_value_flow_candidate_priority");
|
||
});
|
||
|
||
it("keeps factual address follow-up replies when they already match the continuation target intent", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "ИП Калинин Н.М. | сумма: 216600 | операций: 2",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "customer_revenue_and_payments",
|
||
selected_recipe: "address_customer_revenue_and_payments_v1",
|
||
mcp_call_status: "matched_non_empty",
|
||
truth_mode: "confirmed",
|
||
capability_binding_status: "bound",
|
||
capability_binding_violations: [],
|
||
dialogContinuationContract: {
|
||
target_intent: "customer_revenue_and_payments"
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "turnover"
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_keep_factual_address_continuation_target");
|
||
});
|
||
|
||
it("keeps factual suggested-intent pivot replies over discovery clarification candidates", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "Найдены банковские операции по контрагенту Жуковка 51.",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "bank_operations_by_counterparty",
|
||
dialog_continuation_contract_v2: {
|
||
decision: "switch_to_suggested",
|
||
target_intent: "bank_operations_by_counterparty",
|
||
intent_selection_mode: "switch_to_suggested_intent",
|
||
suggested_intent_pivot_signal: true
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "turnover",
|
||
explicit_entity_candidates: ["ТСЖ \\Жуковка 51\\"],
|
||
unsupported_but_understood_family: "counterparty_value_or_turnover"
|
||
}
|
||
},
|
||
bridge: {
|
||
bridge_status: "answer_draft_ready",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: false,
|
||
requires_user_clarification: true,
|
||
answer_draft: {
|
||
answer_mode: "needs_clarification",
|
||
headline: "Нужно уточнить контекст перед поиском в 1С.",
|
||
confirmed_lines: [],
|
||
inference_lines: [],
|
||
unknown_lines: [],
|
||
limitation_lines: [],
|
||
next_step_line: "Уточните контрагента, период или организацию."
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reply_text).toBe("Найдены банковские операции по контрагенту Жуковка 51.");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_keep_factual_suggested_intent_pivot_target");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_candidate_applied");
|
||
});
|
||
|
||
it("overrides an exact ranking-shaped address reply when open-scope ranking still needs organization", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply:
|
||
"Самый доходный год по подтвержденным поступлениям: 2020 (15 744 052,48 ₽ по 20 операциям).",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "customer_revenue_and_payments",
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
data_need_graph: {
|
||
business_fact_family: "value_flow",
|
||
subject_candidates: [],
|
||
ranking_need: "top_desc",
|
||
clarification_gaps: ["organization"],
|
||
reason_codes: ["data_need_graph_built", "data_need_graph_ranking_top_desc"]
|
||
},
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "turnover",
|
||
explicit_date_scope: "2020",
|
||
seeded_ranking_need: "top_desc"
|
||
}
|
||
},
|
||
bridge: {
|
||
bridge_status: "answer_draft_ready",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: false,
|
||
requires_user_clarification: true,
|
||
answer_draft: {
|
||
answer_mode: "needs_clarification",
|
||
headline: "Нужно уточнить организацию.",
|
||
confirmed_lines: [],
|
||
inference_lines: [],
|
||
unknown_lines: ["Без организации поиск по контрагентам не запустить."],
|
||
limitation_lines: [],
|
||
next_step_line: "Уточните организацию, и я продолжу поиск по контрагентам."
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.decision).toBe("apply_candidate");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_semantic_conflict_allows_candidate_override");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_aligned_factual_address_reply");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_factual_address_continuation_target");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_full_confirmed_factual_address_reply");
|
||
});
|
||
|
||
it("overrides an exact ranking-shaped address reply when bounded open-scope ranking already has organization and period", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply:
|
||
"Самый доходный клиент за доступное время по подтвержденным поступлениям: Группа СВК (12 224 925,00 ₽ по 16 операциям).",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "customer_revenue_and_payments",
|
||
dialogContinuationContract: {
|
||
target_intent: "customer_revenue_and_payments"
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
data_need_graph: {
|
||
business_fact_family: "value_flow",
|
||
subject_candidates: [],
|
||
ranking_need: "top_desc",
|
||
clarification_gaps: [],
|
||
reason_codes: ["data_need_graph_built", "data_need_graph_ranking_top_desc"]
|
||
},
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "turnover",
|
||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||
explicit_date_scope: "2020",
|
||
seeded_ranking_need: "top_desc"
|
||
}
|
||
},
|
||
bridge: {
|
||
bridge_status: "answer_draft_ready",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: true,
|
||
requires_user_clarification: false,
|
||
answer_draft: {
|
||
answer_mode: "confirmed_with_bounded_inference",
|
||
headline: "Рейтинг по контрагентам построен по подтвержденным строкам 1С.",
|
||
confirmed_lines: [
|
||
"Больше всего денег принёс контрагент СБЕРБАНК, ПАО по организации ООО Альтернатива Плюс за период 2020: 12 792 194,31 руб. по 9 строкам с суммой."
|
||
],
|
||
inference_lines: [
|
||
"Рейтинг по контрагентам по организации ООО Альтернатива Плюс за период 2020 рассчитан только по подтвержденным строкам 1С."
|
||
],
|
||
unknown_lines: ["Полный исторический рейтинг вне проверенного окна не доказан."],
|
||
limitation_lines: [],
|
||
next_step_line: null
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.decision).toBe("apply_candidate");
|
||
expect(result.reply_text).toContain("ООО Альтернатива Плюс");
|
||
expect(result.reply_text).toContain("2020");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_semantic_conflict_allows_candidate_override");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_aligned_factual_address_reply");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_factual_address_continuation_target");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_exact_matched_factual_address_reply");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_open_scope_value_flow_candidate_priority");
|
||
});
|
||
|
||
it("keeps full-confirmed factual address replies even when discovery has a guarded candidate", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "ООО Ромашка | сумма: 128000 | операций: 3",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "receivables_confirmed_as_of_date",
|
||
truth_gate_contract_status: "full_confirmed",
|
||
assistant_truth_answer_policy_v1: {
|
||
truth_gate: {
|
||
coverage_status: "full",
|
||
grounding_status: "grounded",
|
||
source_truth_gate_status: "full_confirmed"
|
||
}
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "receivables",
|
||
asked_action_family: "confirmed_snapshot"
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reply_text).toBe("ООО Ромашка | сумма: 128000 | операций: 3");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_keep_full_confirmed_factual_address_reply");
|
||
});
|
||
|
||
it("overrides a stale full-confirmed lifecycle reply when discovery proves a different net-flow question", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "Коротко: активных заказчиков в 2020 году — 1.",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "counterparty_activity_lifecycle",
|
||
truth_gate_contract_status: "full_confirmed",
|
||
assistant_truth_answer_policy_v1: {
|
||
truth_gate: {
|
||
coverage_status: "full",
|
||
grounding_status: "grounded",
|
||
source_truth_gate_status: "full_confirmed"
|
||
}
|
||
},
|
||
dialog_continuation_contract_v2: {
|
||
target_intent: "counterparty_activity_lifecycle"
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "net_value_flow",
|
||
explicit_entity_candidates: ["Группа СВК"],
|
||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||
explicit_date_scope: "2020",
|
||
unsupported_but_understood_family: "counterparty_bidirectional_value_flow_or_netting"
|
||
}
|
||
},
|
||
bridge: {
|
||
bridge_status: "answer_draft_ready",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: true,
|
||
requires_user_clarification: false,
|
||
answer_draft: {
|
||
answer_mode: "confirmed_with_bounded_inference",
|
||
headline: "По данным 1С найдены строки входящих и исходящих денежных движений.",
|
||
confirmed_lines: ["Получили 47 628 853,03 руб.; заплатили 43 763 351,53 руб.; нетто 3 865 501,50 руб."],
|
||
inference_lines: [],
|
||
unknown_lines: ["Полное сальдо вне проверенного окна не подтверждено."],
|
||
limitation_lines: [],
|
||
next_step_line: null
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(true);
|
||
expect(result.decision).toBe("apply_candidate");
|
||
expect(result.reply_source).toBe("mcp_discovery_response_candidate_guarded");
|
||
expect(result.reply_text).toContain("47 628 853,03");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_semantic_conflict_allows_candidate_override");
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_keep_full_confirmed_factual_address_reply");
|
||
});
|
||
|
||
it("keeps runtime-adjusted exact VAT follow-up replies over stale discovery turn meaning", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "Коротко: подтвержденный НДС к уплате за май 2017 — 0,00 руб.",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
currentReplyType: "factual",
|
||
addressRuntimeMeta: {
|
||
detected_intent: "vat_liability_confirmed_for_tax_period",
|
||
truth_gate_contract_status: "full_confirmed",
|
||
assistant_truth_answer_policy_v1: {
|
||
truth_gate: {
|
||
coverage_status: "full",
|
||
grounding_status: "grounded",
|
||
source_truth_gate_status: "full_confirmed"
|
||
},
|
||
answer_shape: {
|
||
reply_type: "factual",
|
||
capability_contract_id: "confirmed_vat_liability_for_tax_period"
|
||
}
|
||
},
|
||
assistant_state_transition_v1: {
|
||
reason_codes: [
|
||
"root_followup_continue_previous",
|
||
"intent_adjusted_to_vat_followup_context",
|
||
"period_from_from_followup_context",
|
||
"period_to_from_followup_context",
|
||
"confirmed_balance_exact_vat_tax_period_intent"
|
||
]
|
||
},
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "counterparty_value",
|
||
asked_action_family: "confirmed_snapshot",
|
||
explicit_entity_candidates: ["ООО Альтернатива Плюс"],
|
||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||
explicit_date_scope: "2017-05-31",
|
||
unsupported_but_understood_family: "counterparty_value_or_turnover"
|
||
}
|
||
},
|
||
bridge: {
|
||
bridge_status: "checked_sources_only",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: false,
|
||
requires_user_clarification: false,
|
||
answer_draft: {
|
||
answer_mode: "checked_sources_only",
|
||
headline: "Я проверил доступный контур, но подтвержденного факта для ответа не получил.",
|
||
confirmed_lines: [],
|
||
inference_lines: [],
|
||
unknown_lines: ["Полный объем входящих поступлений вне проверенного периода этим поиском не подтвержден."],
|
||
limitation_lines: [],
|
||
next_step_line: null
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reply_text).toContain("подтвержденный НДС к уплате");
|
||
expect(result.reason_codes).toContain(
|
||
"mcp_discovery_response_policy_keep_runtime_adjusted_exact_reply_over_stale_discovery_turn_meaning"
|
||
);
|
||
expect(result.reason_codes).not.toContain("mcp_discovery_response_policy_semantic_conflict_allows_candidate_override");
|
||
});
|
||
|
||
it("keeps address lane answers when discovery was not requested for the current turn", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "supported exact route answer",
|
||
currentReplySource: "address_query_runtime_v1",
|
||
addressRuntimeMeta: {
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "not_applicable",
|
||
should_run_discovery: false
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.reply_text).toBe("supported exact route answer");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_not_discovery_ready_address_candidate");
|
||
});
|
||
|
||
it("keeps the current reply when the candidate has no grounded text", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "route is not wired",
|
||
currentReplySource: "deterministic_unsupported_current_turn_boundary",
|
||
modeDecisionReason: "unsupported_current_turn_meaning_boundary",
|
||
addressRuntimeMeta: {
|
||
mcpDiscoveryRuntimeEntryPoint: entryPoint({
|
||
bridge: {
|
||
bridge_status: "unsupported",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: false,
|
||
requires_user_clarification: false,
|
||
answer_draft: null
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.reply_text).toBe("route is not wired");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_candidate_not_eligible");
|
||
expect(result.reason_codes).toContain("mcp_discovery_response_policy_kept_current_reply");
|
||
});
|
||
|
||
it("keeps deterministic broad business evaluation summary instead of replacing it with a clarification candidate", () => {
|
||
const result = applyAssistantMcpDiscoveryResponsePolicy({
|
||
currentReply: "Коротко: по уже подтвержденным данным в 1С компания выглядит живой операционно.",
|
||
currentReplySource: "deterministic_broad_business_evaluation_contract",
|
||
livingChatSource: "deterministic_broad_business_evaluation_contract",
|
||
modeDecisionReason: "unsupported_current_turn_meaning_boundary",
|
||
addressRuntimeMeta: {
|
||
assistant_mcp_discovery_entry_point_v1: entryPoint({
|
||
turn_input: {
|
||
adapter_status: "ready",
|
||
should_run_discovery: true,
|
||
turn_meaning_ref: {
|
||
asked_domain_family: "business_summary",
|
||
asked_action_family: "broad_evaluation",
|
||
unsupported_but_understood_family: "broad_business_evaluation",
|
||
stale_replay_forbidden: true
|
||
}
|
||
},
|
||
bridge: {
|
||
bridge_status: "needs_clarification",
|
||
user_facing_response_allowed: true,
|
||
business_fact_answer_allowed: false,
|
||
requires_user_clarification: true,
|
||
answer_draft: {
|
||
answer_mode: "needs_clarification",
|
||
headline: "Нужно уточнить контекст перед поиском в 1С.",
|
||
confirmed_lines: [],
|
||
inference_lines: [],
|
||
unknown_lines: ["MCP discovery pilot needs more scope before execution"],
|
||
limitation_lines: ["MCP discovery pilot needs more scope before execution"],
|
||
next_step_line: "Уточните контрагента, период или организацию."
|
||
}
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
expect(result.applied).toBe(false);
|
||
expect(result.decision).toBe("keep_current_reply");
|
||
expect(result.reply_source).toBe("deterministic_broad_business_evaluation_contract");
|
||
expect(result.reply_text).toContain("компания выглядит живой операционно");
|
||
expect(result.reason_codes).toContain(
|
||
"mcp_discovery_response_policy_keep_broad_business_summary_over_clarification_candidate"
|
||
);
|
||
});
|
||
});
|