ARCH: замкнуть grounded entity follow-up на документы и денежный поток
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
applyTemporalCarryoverFilters,
|
||||
buildRootScopedCarryoverFilters,
|
||||
hydrateInventoryRootFrameState,
|
||||
readAddressDebugCounterparty,
|
||||
readAddressDebugIntent,
|
||||
readAddressDebugTemporalScope,
|
||||
resolveNavigationSessionContextState,
|
||||
@@ -191,6 +192,49 @@ describe("assistantContinuityPolicy organization authority", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("prefers the resolved entity from grounded entity-resolution discovery for counterparty carryover", () => {
|
||||
const debug = {
|
||||
execution_lane: "living_chat",
|
||||
mcp_discovery_response_applied: true,
|
||||
assistant_mcp_discovery_entry_point_v1: {
|
||||
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||||
entry_status: "bridge_executed",
|
||||
turn_input: {
|
||||
turn_meaning_ref: {
|
||||
asked_domain_family: "entity_resolution",
|
||||
asked_action_family: "search_business_entity",
|
||||
explicit_entity_candidates: ["СВК"]
|
||||
}
|
||||
},
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
business_fact_answer_allowed: true,
|
||||
pilot: {
|
||||
pilot_scope: "entity_resolution_search_v1",
|
||||
derived_entity_resolution: {
|
||||
requested_entity: "СВК",
|
||||
resolution_status: "resolved",
|
||||
resolved_entity: "Группа СВК",
|
||||
ambiguity_candidates: []
|
||||
}
|
||||
},
|
||||
answer_draft: {
|
||||
answer_mode: "confirmed_with_bounded_inference"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(readAddressDebugCounterparty(debug)).toBe("Группа СВК");
|
||||
expect(resolveAddressDebugCarryoverFilters(debug)).toEqual({
|
||||
counterparty: "Группа СВК"
|
||||
});
|
||||
expect(resolveAddressDebugAnchorContext(debug)).toEqual({
|
||||
anchorType: "counterparty",
|
||||
anchorValue: "Группа СВК"
|
||||
});
|
||||
});
|
||||
|
||||
it("resolves navigation session context through one shared helper", () => {
|
||||
const state = resolveNavigationSessionContextState({
|
||||
session_context: {
|
||||
|
||||
@@ -31,6 +31,24 @@ function buildSequentialDeps(results: Array<{ rows: Array<Record<string, unknown
|
||||
return { executeAddressMcpQuery };
|
||||
}
|
||||
|
||||
function buildCustomQueryDeps(result: {
|
||||
fetched_rows: number;
|
||||
matched_rows: number;
|
||||
rows: Array<Record<string, unknown>>;
|
||||
raw_rows?: Array<Record<string, unknown>>;
|
||||
error?: string | null;
|
||||
}) {
|
||||
return {
|
||||
executeAddressMcpQuery: vi.fn(async () => ({
|
||||
fetched_rows: result.fetched_rows,
|
||||
matched_rows: result.matched_rows,
|
||||
rows: result.rows,
|
||||
raw_rows: result.raw_rows ?? result.rows,
|
||||
error: result.error ?? null
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
function buildMetadataDeps(rows: Array<Record<string, unknown>>, error: string | null = null) {
|
||||
return {
|
||||
executeAddressMcpMetadata: vi.fn(async () => ({
|
||||
@@ -108,11 +126,15 @@ describe("assistant MCP discovery answer adapter", () => {
|
||||
|
||||
expect(draft.answer_mode).toBe("confirmed_with_bounded_inference");
|
||||
expect(draft.headline).toContain("документ");
|
||||
expect(draft.confirmed_lines).toContain("1C document rows were found for counterparty SVK");
|
||||
expect(draft.headline).toContain("2020");
|
||||
expect(draft.headline).toContain("SVK");
|
||||
expect(draft.confirmed_lines).toContain("В 1С найдены строки документов по контрагенту SVK за 2020.");
|
||||
expect(draft.inference_lines).toContain(
|
||||
"Counterparty document evidence is limited to confirmed 1C document rows in the checked scope"
|
||||
"Срез документов по контрагенту SVK за 2020 ограничен только подтвержденными строками документов, найденными этим поиском."
|
||||
);
|
||||
expect(draft.unknown_lines).toContain(
|
||||
"Полный исторический срез документов по контрагенту SVK вне периода 2020 этим поиском не подтвержден."
|
||||
);
|
||||
expect(draft.unknown_lines).toContain("Full document history outside the checked period is not proven by this MCP discovery pilot");
|
||||
expect(draft.must_not_claim).toContain("Do not claim full document history outside the checked period.");
|
||||
});
|
||||
|
||||
@@ -134,16 +156,54 @@ describe("assistant MCP discovery answer adapter", () => {
|
||||
const draft = buildAssistantMcpDiscoveryAnswerDraft(pilot);
|
||||
|
||||
expect(draft.answer_mode).toBe("confirmed_with_bounded_inference");
|
||||
expect(draft.headline).toContain("движений");
|
||||
expect(draft.confirmed_lines).toContain("1C movement rows were found for counterparty SVK");
|
||||
expect(draft.headline).toContain("движени");
|
||||
expect(draft.headline).toContain("2020");
|
||||
expect(draft.headline).toContain("SVK");
|
||||
expect(draft.confirmed_lines).toContain("В 1С найдены строки движений по контрагенту SVK за 2020.");
|
||||
expect(draft.inference_lines).toContain(
|
||||
"Counterparty movement evidence is limited to confirmed 1C movement rows in the checked scope"
|
||||
"Срез движений по контрагенту SVK за 2020 ограничен только подтвержденными строками движений, найденными этим поиском."
|
||||
);
|
||||
expect(draft.unknown_lines).toContain(
|
||||
"Полный исторический срез движений по контрагенту SVK вне периода 2020 этим поиском не подтвержден."
|
||||
);
|
||||
expect(draft.unknown_lines).toContain("Full movement history outside the checked period is not proven by this MCP discovery pilot");
|
||||
expect(draft.must_not_claim).toContain("Do not claim full movement history outside the checked period.");
|
||||
expect(draft.must_not_claim).toContain("Do not present the confirmed movement rows as a complete movement universe.");
|
||||
});
|
||||
|
||||
it("keeps bounded-only movement answers tied to the resolved entity and checked period", async () => {
|
||||
const planner = planAssistantMcpDiscovery({
|
||||
turnMeaning: {
|
||||
asked_domain_family: "movements",
|
||||
asked_action_family: "list_movements",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "movement_evidence"
|
||||
}
|
||||
});
|
||||
const pilot = await executeAssistantMcpDiscoveryPilot(
|
||||
planner,
|
||||
buildCustomQueryDeps({
|
||||
fetched_rows: 100,
|
||||
matched_rows: 0,
|
||||
rows: [],
|
||||
raw_rows: [{ Period: "2020-06-30T00:00:00", Counterparty: "Группа СВК", Registrar: "Move1" }]
|
||||
})
|
||||
);
|
||||
|
||||
const draft = buildAssistantMcpDiscoveryAnswerDraft(pilot);
|
||||
|
||||
expect(draft.answer_mode).toBe("bounded_inference_only");
|
||||
expect(draft.headline).toContain("движени");
|
||||
expect(draft.headline).toContain("Группа СВК");
|
||||
expect(draft.headline).toContain("2020");
|
||||
expect(draft.inference_lines).toContain(
|
||||
"По движениям по контрагенту Группа СВК за 2020 удалось проверить только ограниченный срез 1С; подтвержденных строк движений этим поиском не найдено."
|
||||
);
|
||||
expect(draft.unknown_lines).toContain(
|
||||
"Полный исторический срез движений по контрагенту Группа СВК вне периода 2020 этим поиском не подтвержден."
|
||||
);
|
||||
});
|
||||
|
||||
it("asks for clarification when discovery did not execute due to missing scope", async () => {
|
||||
const planner = planAssistantMcpDiscovery({
|
||||
turnMeaning: {
|
||||
@@ -372,8 +432,9 @@ describe("assistant MCP discovery answer adapter", () => {
|
||||
const confirmedText = draft.confirmed_lines.join("\n");
|
||||
|
||||
expect(draft.answer_mode).toBe("confirmed_with_bounded_inference");
|
||||
expect(draft.headline).toContain("денежных движений");
|
||||
expect(draft.headline).toContain("входящих денежных поступлений");
|
||||
expect(confirmedText).toContain("3 750,50 руб.");
|
||||
expect(confirmedText).toContain("входящих денежных поступлений");
|
||||
expect(confirmedText).toContain("2020-01-15");
|
||||
expect(confirmedText).toContain("2020-02-20");
|
||||
expect(draft.unknown_lines).toContain("Full turnover outside the checked period is not proven by this MCP discovery pilot");
|
||||
|
||||
@@ -148,12 +148,12 @@ describe("assistant MCP discovery pilot executor", () => {
|
||||
expect(result.pilot_status).toBe("executed");
|
||||
expect(result.pilot_scope).toBe("counterparty_document_evidence_query_documents_v1");
|
||||
expect(result.executed_primitives).toEqual(["query_documents"]);
|
||||
expect(result.evidence.confirmed_facts).toContain("1C document rows were found for counterparty SVK");
|
||||
expect(result.evidence.confirmed_facts).toContain("В 1С найдены строки документов по контрагенту SVK за 2020.");
|
||||
expect(result.evidence.inferred_facts).toContain(
|
||||
"Counterparty document evidence is limited to confirmed 1C document rows in the checked scope"
|
||||
"Срез документов по контрагенту SVK за 2020 ограничен только подтвержденными строками документов, найденными этим поиском."
|
||||
);
|
||||
expect(result.evidence.unknown_facts).toContain(
|
||||
"Full document history outside the checked period is not proven by this MCP discovery pilot"
|
||||
"Полный исторический срез документов по контрагенту SVK вне периода 2020 этим поиском не подтвержден."
|
||||
);
|
||||
expect(result.source_rows_summary).toBe("2 MCP document rows fetched, 2 matched document scope");
|
||||
});
|
||||
@@ -180,12 +180,12 @@ describe("assistant MCP discovery pilot executor", () => {
|
||||
expect(result.executed_primitives).toEqual(["query_movements"]);
|
||||
expect(result.derived_value_flow).toBeNull();
|
||||
expect(result.derived_bidirectional_value_flow).toBeNull();
|
||||
expect(result.evidence.confirmed_facts).toContain("1C movement rows were found for counterparty SVK");
|
||||
expect(result.evidence.confirmed_facts).toContain("В 1С найдены строки движений по контрагенту SVK за 2020.");
|
||||
expect(result.evidence.inferred_facts).toContain(
|
||||
"Counterparty movement evidence is limited to confirmed 1C movement rows in the checked scope"
|
||||
"Срез движений по контрагенту SVK за 2020 ограничен только подтвержденными строками движений, найденными этим поиском."
|
||||
);
|
||||
expect(result.evidence.unknown_facts).toContain(
|
||||
"Full movement history outside the checked period is not proven by this MCP discovery pilot"
|
||||
"Полный исторический срез движений по контрагенту SVK вне периода 2020 этим поиском не подтвержден."
|
||||
);
|
||||
expect(result.source_rows_summary).toBe("2 MCP movement rows fetched, 2 matched movement scope");
|
||||
|
||||
@@ -762,6 +762,56 @@ describe("assistant MCP discovery pilot executor", () => {
|
||||
expect(deps.executeAddressMcpQuery).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("keeps document and movement evidence scoped to the resolved entity and checked period", async () => {
|
||||
const documentPlanner = planAssistantMcpDiscovery({
|
||||
turnMeaning: {
|
||||
asked_domain_family: "documents",
|
||||
asked_action_family: "list_documents",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "document_evidence"
|
||||
}
|
||||
});
|
||||
const documentResult = await executeAssistantMcpDiscoveryPilot(
|
||||
documentPlanner,
|
||||
buildDeps([{ Period: "2020-01-15T00:00:00", Counterparty: "Группа СВК", Registrar: "Doc1" }])
|
||||
);
|
||||
|
||||
expect(documentResult.evidence.confirmed_facts).toContain(
|
||||
"В 1С найдены строки документов по контрагенту Группа СВК за 2020."
|
||||
);
|
||||
expect(documentResult.evidence.inferred_facts).toContain(
|
||||
"Срез документов по контрагенту Группа СВК за 2020 ограничен только подтвержденными строками документов, найденными этим поиском."
|
||||
);
|
||||
expect(documentResult.evidence.unknown_facts).toContain(
|
||||
"Полный исторический срез документов по контрагенту Группа СВК вне периода 2020 этим поиском не подтвержден."
|
||||
);
|
||||
|
||||
const movementPlanner = planAssistantMcpDiscovery({
|
||||
turnMeaning: {
|
||||
asked_domain_family: "movements",
|
||||
asked_action_family: "list_movements",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "movement_evidence"
|
||||
}
|
||||
});
|
||||
const movementResult = await executeAssistantMcpDiscoveryPilot(
|
||||
movementPlanner,
|
||||
buildDeps([{ Period: "2020-01-15T00:00:00", Counterparty: "Группа СВК", Registrar: "Move1" }])
|
||||
);
|
||||
|
||||
expect(movementResult.evidence.confirmed_facts).toContain(
|
||||
"В 1С найдены строки движений по контрагенту Группа СВК за 2020."
|
||||
);
|
||||
expect(movementResult.evidence.inferred_facts).toContain(
|
||||
"Срез движений по контрагенту Группа СВК за 2020 ограничен только подтвержденными строками движений, найденными этим поиском."
|
||||
);
|
||||
expect(movementResult.evidence.unknown_facts).toContain(
|
||||
"Полный исторический срез движений по контрагенту Группа СВК вне периода 2020 этим поиском не подтвержден."
|
||||
);
|
||||
});
|
||||
|
||||
it("records MCP errors as limitations without converting them into facts", async () => {
|
||||
const planner = planAssistantMcpDiscovery({
|
||||
turnMeaning: {
|
||||
|
||||
@@ -54,10 +54,10 @@ describe("assistant MCP discovery response candidate", () => {
|
||||
requires_user_clarification: false,
|
||||
answer_draft: {
|
||||
answer_mode: "confirmed_with_bounded_inference",
|
||||
headline: "По данным 1С найдены строки денежных движений; сумму можно называть только в рамках проверенного периода и найденных строк.",
|
||||
headline: "По данным 1С найдены строки входящих денежных поступлений; сумму можно называть только в рамках проверенного периода и найденных строк.",
|
||||
confirmed_lines: [
|
||||
"1C value-flow rows were found for counterparty SVK",
|
||||
"По найденным строкам денежных движений в 1С по контрагенту SVK за период 2020 сумма составляет 3 750 руб."
|
||||
"По найденным строкам входящих денежных поступлений в 1С по контрагенту SVK за период 2020 сумма входящих денежных поступлений составляет 3 750 руб."
|
||||
],
|
||||
inference_lines: ["Counterparty value-flow total was calculated from confirmed 1C movement rows"],
|
||||
unknown_lines: ["Full turnover outside the checked period is not proven by this MCP discovery pilot"],
|
||||
@@ -69,9 +69,9 @@ describe("assistant MCP discovery response candidate", () => {
|
||||
);
|
||||
|
||||
expect(candidate.candidate_status).toBe("ready_for_guarded_use");
|
||||
expect(candidate.reply_text).toContain("В 1С найдены строки денежных движений по контрагенту SVK.");
|
||||
expect(candidate.reply_text).toContain("В 1С найдены строки входящих денежных поступлений по контрагенту SVK.");
|
||||
expect(candidate.reply_text).toContain("3 750 руб.");
|
||||
expect(candidate.reply_text).toContain("Полный оборот вне проверенного периода этим поиском не подтвержден.");
|
||||
expect(candidate.reply_text).toContain("Полный объем входящих поступлений вне проверенного периода этим поиском не подтвержден.");
|
||||
expect(candidate.reply_text).not.toContain("pilot_");
|
||||
expect(candidate.reply_text).not.toContain("query_movements");
|
||||
});
|
||||
|
||||
@@ -209,6 +209,145 @@ describe("assistant MCP discovery turn input adapter", () => {
|
||||
expect(result.reason_codes).toContain("mcp_discovery_entity_scope_from_raw_entity_search");
|
||||
});
|
||||
|
||||
it("seeds document evidence follow-up from prior entity-resolution grounding", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "по нему документы за 2020 год",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "entity_resolution_search_v1",
|
||||
previous_anchor_type: "counterparty",
|
||||
previous_anchor_value: "Группа СВК",
|
||||
previous_discovery_entity_candidates: ["Группа СВК", "СВК"]
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.source_signal).toBe("followup_context");
|
||||
expect(result.semantic_data_need).toBe("document evidence");
|
||||
expect(result.turn_meaning_ref).toMatchObject({
|
||||
asked_domain_family: "documents",
|
||||
asked_action_family: "list_documents",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "document_evidence",
|
||||
stale_replay_forbidden: true
|
||||
});
|
||||
expect(result.reason_codes).toContain("mcp_discovery_entity_resolution_grounded_document_followup");
|
||||
expect(result.reason_codes).toContain("mcp_discovery_counterparty_from_followup_context");
|
||||
});
|
||||
|
||||
it("seeds movement evidence follow-up from prior entity-resolution grounding", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "а теперь по нему движения за 2020 год",
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "entity_resolution_search_v1",
|
||||
previous_discovery_entity_candidates: ["Группа СВК", "СВК"]
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.source_signal).toBe("followup_context");
|
||||
expect(result.semantic_data_need).toBe("movement evidence");
|
||||
expect(result.turn_meaning_ref).toMatchObject({
|
||||
asked_domain_family: "movements",
|
||||
asked_action_family: "list_movements",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "movement_evidence",
|
||||
stale_replay_forbidden: true
|
||||
});
|
||||
expect(result.reason_codes).toContain("mcp_discovery_entity_resolution_grounded_movement_followup");
|
||||
expect(result.reason_codes).toContain("mcp_discovery_counterparty_from_followup_context");
|
||||
});
|
||||
|
||||
it("overrides a wrong exact document intent when a grounded document follow-up asks to switch into movements", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "а теперь по нему движения за 2020 год",
|
||||
assistantTurnMeaning: {
|
||||
asked_domain_family: "inventory",
|
||||
asked_action_family: "purchase_documents",
|
||||
explicit_intent_candidate: "inventory_purchase_documents_for_item",
|
||||
explicit_entity_candidates: [{ value: "нему" }]
|
||||
},
|
||||
predecomposeContract: {
|
||||
entities: {
|
||||
counterparty: "нему"
|
||||
},
|
||||
period: {
|
||||
period_from: "2020-01-01",
|
||||
period_to: "2020-12-31"
|
||||
}
|
||||
},
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "counterparty_document_evidence_query_documents_v1",
|
||||
previous_filters: {
|
||||
counterparty: "Группа СВК",
|
||||
period_from: "2020-01-01",
|
||||
period_to: "2020-12-31"
|
||||
},
|
||||
previous_discovery_entity_candidates: ["Группа СВК", "СВК"]
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.source_signal).toBe("assistant_turn_meaning");
|
||||
expect(result.semantic_data_need).toBe("movement evidence");
|
||||
expect(result.turn_meaning_ref).toMatchObject({
|
||||
asked_domain_family: "movements",
|
||||
asked_action_family: "list_movements",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "movement_evidence",
|
||||
stale_replay_forbidden: true
|
||||
});
|
||||
expect(result.reason_codes).toContain("mcp_discovery_document_evidence_grounded_movement_followup");
|
||||
expect(result.reason_codes).not.toContain("mcp_discovery_not_applicable_for_supported_exact_turn");
|
||||
});
|
||||
|
||||
it("overrides a supported exact turnover intent when a grounded entity follow-up asks about incoming money", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "сколько получили по нему за 2020 год",
|
||||
assistantTurnMeaning: {
|
||||
asked_domain_family: "counterparty",
|
||||
asked_action_family: "turnover",
|
||||
explicit_intent_candidate: "customer_revenue_and_payments",
|
||||
explicit_entity_candidates: [{ value: "нему" }]
|
||||
},
|
||||
predecomposeContract: {
|
||||
entities: {
|
||||
counterparty: "нему"
|
||||
},
|
||||
period: {
|
||||
period_from: "2020-01-01",
|
||||
period_to: "2020-12-31"
|
||||
}
|
||||
},
|
||||
followupContext: {
|
||||
previous_discovery_pilot_scope: "entity_resolution_search_v1",
|
||||
previous_filters: {
|
||||
counterparty: "Группа СВК"
|
||||
},
|
||||
previous_discovery_entity_candidates: ["Группа СВК", "СВК"]
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.semantic_data_need).toBe("counterparty value-flow evidence");
|
||||
expect(result.turn_meaning_ref).toMatchObject({
|
||||
asked_domain_family: "counterparty_value",
|
||||
asked_action_family: "turnover",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "counterparty_value_or_turnover",
|
||||
stale_replay_forbidden: true
|
||||
});
|
||||
expect(result.reason_codes).toContain("mcp_discovery_grounded_value_flow_followup");
|
||||
expect(result.reason_codes).not.toContain("mcp_discovery_not_applicable_for_supported_exact_turn");
|
||||
});
|
||||
|
||||
it("seeds short monthly follow-up from prior bidirectional discovery context", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "а по месяцам?",
|
||||
|
||||
@@ -1114,6 +1114,65 @@ describe("assistantTransitionPolicy", () => {
|
||||
period_to: "2020-12-31"
|
||||
});
|
||||
});
|
||||
it("carries resolved entity candidates from grounded entity-resolution discovery into followup context", () => {
|
||||
const policy = buildPolicy({
|
||||
findLastAddressAssistantItem: () => null,
|
||||
hasAddressFollowupContextSignal: () => true
|
||||
});
|
||||
|
||||
const carryover = policy.resolveAddressFollowupCarryoverContext(
|
||||
"по нему документы за 2020 год",
|
||||
[
|
||||
{
|
||||
role: "assistant",
|
||||
text: "В текущем каталожном срезе 1С по запросу \"СВК\" найден контрагент \"Группа СВК\".",
|
||||
debug: {
|
||||
execution_lane: "living_chat",
|
||||
mcp_discovery_response_applied: true,
|
||||
assistant_mcp_discovery_entry_point_v1: {
|
||||
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||||
entry_status: "bridge_executed",
|
||||
turn_input: {
|
||||
turn_meaning_ref: {
|
||||
asked_domain_family: "entity_resolution",
|
||||
asked_action_family: "search_business_entity",
|
||||
explicit_entity_candidates: ["СВК"]
|
||||
}
|
||||
},
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
business_fact_answer_allowed: true,
|
||||
pilot: {
|
||||
pilot_scope: "entity_resolution_search_v1",
|
||||
derived_entity_resolution: {
|
||||
requested_entity: "СВК",
|
||||
resolution_status: "resolved",
|
||||
resolved_entity: "Группа СВК",
|
||||
ambiguity_candidates: []
|
||||
}
|
||||
},
|
||||
answer_draft: {
|
||||
answer_mode: "confirmed_with_bounded_inference"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
expect(carryover?.followupContext?.previous_discovery_pilot_scope).toBe("entity_resolution_search_v1");
|
||||
expect(carryover?.followupContext?.previous_discovery_entity_candidates).toEqual(["Группа СВК", "СВК"]);
|
||||
expect(carryover?.followupContext?.previous_anchor_type).toBe("counterparty");
|
||||
expect(carryover?.followupContext?.previous_anchor_value).toBe("Группа СВК");
|
||||
expect(carryover?.followupContext?.previous_filters).toMatchObject({
|
||||
counterparty: "Группа СВК"
|
||||
});
|
||||
});
|
||||
|
||||
it("carries grounded metadata downstream route hints into followup context", () => {
|
||||
const policy = buildPolicy({
|
||||
findLastAddressAssistantItem: () => null,
|
||||
|
||||
Reference in New Issue
Block a user