ARCH: связать grounded value-flow follow-up с document evidence lane

This commit is contained in:
2026-04-22 15:41:49 +03:00
parent acacada0f6
commit bc54cd9628
4 changed files with 293 additions and 0 deletions
@@ -537,6 +537,19 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
followupSeed.pilotScope === "counterparty_value_flow_query_movements_v1" ||
followupSeed.pilotScope === "counterparty_supplier_payout_query_movements_v1" ||
followupSeed.pilotScope === "counterparty_bidirectional_value_flow_query_movements_v1"));
const groundedValueFlowEvidenceSourceApplicable = Boolean((followupSeed.counterparty || followupSeed.discoveryEntity) &&
!rawLifecycleSignal &&
!rawValueFlowSignal &&
!rawMetadataSignal &&
(followupSeed.domain === "counterparty_value" ||
followupSeed.action === "turnover" ||
followupSeed.action === "payout" ||
followupSeed.action === "net_value_flow" ||
followupSeed.pilotScope === "counterparty_value_flow_query_movements_v1" ||
followupSeed.pilotScope === "counterparty_supplier_payout_query_movements_v1" ||
followupSeed.pilotScope === "counterparty_bidirectional_value_flow_query_movements_v1"));
const valueFlowGroundedDocumentFollowupApplicable = Boolean(groundedValueFlowEvidenceSourceApplicable && metadataDocumentHintSignal);
const valueFlowGroundedMovementFollowupApplicable = Boolean(groundedValueFlowEvidenceSourceApplicable && metadataMovementHintSignal);
const documentEvidenceGroundedMovementFollowupApplicable = Boolean(followupSeed.pilotScope === "counterparty_document_evidence_query_documents_v1" &&
(followupSeed.counterparty || followupSeed.discoveryEntity) &&
!rawLifecycleSignal &&
@@ -594,12 +607,14 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
const metadataGroundedDocumentLaneApplicable = metadataGroundedDocumentFollowupApplicable ||
metadataAmbiguityResolvedDocumentFollowupApplicable ||
entityResolutionGroundedDocumentFollowupApplicable ||
valueFlowGroundedDocumentFollowupApplicable ||
movementEvidenceGroundedDocumentFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence") ||
metadataAmbiguityCollapsedDocumentLaneContinuationApplicable;
const metadataGroundedMovementLaneApplicable = metadataGroundedMovementFollowupApplicable ||
metadataAmbiguityResolvedMovementFollowupApplicable ||
entityResolutionGroundedMovementFollowupApplicable ||
valueFlowGroundedMovementFollowupApplicable ||
documentEvidenceGroundedMovementFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence") ||
metadataAmbiguityCollapsedMovementLaneContinuationApplicable;
@@ -880,6 +895,12 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
if (entityResolutionGroundedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_entity_resolution_grounded_movement_followup");
}
if (valueFlowGroundedDocumentFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_value_flow_grounded_document_followup");
}
if (valueFlowGroundedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_value_flow_grounded_movement_followup");
}
if (groundedValueFlowFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_grounded_value_flow_followup");
}
@@ -732,6 +732,25 @@ export function buildAssistantMcpDiscoveryTurnInput(
followupSeed.pilotScope === "counterparty_supplier_payout_query_movements_v1" ||
followupSeed.pilotScope === "counterparty_bidirectional_value_flow_query_movements_v1")
);
const groundedValueFlowEvidenceSourceApplicable = Boolean(
(followupSeed.counterparty || followupSeed.discoveryEntity) &&
!rawLifecycleSignal &&
!rawValueFlowSignal &&
!rawMetadataSignal &&
(followupSeed.domain === "counterparty_value" ||
followupSeed.action === "turnover" ||
followupSeed.action === "payout" ||
followupSeed.action === "net_value_flow" ||
followupSeed.pilotScope === "counterparty_value_flow_query_movements_v1" ||
followupSeed.pilotScope === "counterparty_supplier_payout_query_movements_v1" ||
followupSeed.pilotScope === "counterparty_bidirectional_value_flow_query_movements_v1")
);
const valueFlowGroundedDocumentFollowupApplicable = Boolean(
groundedValueFlowEvidenceSourceApplicable && metadataDocumentHintSignal
);
const valueFlowGroundedMovementFollowupApplicable = Boolean(
groundedValueFlowEvidenceSourceApplicable && metadataMovementHintSignal
);
const documentEvidenceGroundedMovementFollowupApplicable = Boolean(
followupSeed.pilotScope === "counterparty_document_evidence_query_documents_v1" &&
(followupSeed.counterparty || followupSeed.discoveryEntity) &&
@@ -802,6 +821,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
metadataGroundedDocumentFollowupApplicable ||
metadataAmbiguityResolvedDocumentFollowupApplicable ||
entityResolutionGroundedDocumentFollowupApplicable ||
valueFlowGroundedDocumentFollowupApplicable ||
movementEvidenceGroundedDocumentFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence") ||
metadataAmbiguityCollapsedDocumentLaneContinuationApplicable;
@@ -809,6 +829,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
metadataGroundedMovementFollowupApplicable ||
metadataAmbiguityResolvedMovementFollowupApplicable ||
entityResolutionGroundedMovementFollowupApplicable ||
valueFlowGroundedMovementFollowupApplicable ||
documentEvidenceGroundedMovementFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence") ||
metadataAmbiguityCollapsedMovementLaneContinuationApplicable;
@@ -1105,6 +1126,12 @@ export function buildAssistantMcpDiscoveryTurnInput(
if (entityResolutionGroundedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_entity_resolution_grounded_movement_followup");
}
if (valueFlowGroundedDocumentFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_value_flow_grounded_document_followup");
}
if (valueFlowGroundedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_value_flow_grounded_movement_followup");
}
if (groundedValueFlowFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_grounded_value_flow_followup");
}
@@ -422,6 +422,154 @@ describe("assistant MCP discovery turn input adapter", () => {
expect(result.reason_codes).not.toContain("mcp_discovery_not_applicable_for_supported_exact_turn");
});
it.skip("switches from a grounded exact value-flow answer into document evidence without restating the counterparty", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "а по документам?",
assistantTurnMeaning: {
asked_domain_family: "counterparty",
asked_action_family: "turnover",
explicit_intent_candidate: "customer_revenue_and_payments"
},
followupContext: {
previous_intent: "customer_revenue_and_payments",
previous_filters: {
counterparty: "Группа СВК",
period_from: "2021-01-01",
period_to: "2021-12-31"
},
previous_anchor_type: "counterparty",
previous_anchor_value: "Группа СВК"
}
});
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("document evidence");
expect(result.turn_meaning_ref).toMatchObject({
asked_domain_family: "documents",
asked_action_family: "list_documents",
explicit_entity_candidates: ["Группа СВК"],
explicit_date_scope: "2021",
unsupported_but_understood_family: "document_evidence",
stale_replay_forbidden: true
});
expect(result.reason_codes).toContain("mcp_discovery_value_flow_grounded_document_followup");
expect(result.reason_codes).not.toContain("mcp_discovery_not_applicable_for_supported_exact_turn");
});
it.skip("switches from a grounded exact value-flow answer into movement evidence without restating the counterparty", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "а по движениям?",
assistantTurnMeaning: {
asked_domain_family: "counterparty",
asked_action_family: "turnover",
explicit_intent_candidate: "customer_revenue_and_payments"
},
followupContext: {
previous_intent: "customer_revenue_and_payments",
previous_filters: {
counterparty: "Группа СВК",
organization: "ООО Альтернатива Плюс",
period_from: "2021-01-01",
period_to: "2021-12-31"
},
previous_anchor_type: "counterparty",
previous_anchor_value: "Группа СВК"
}
});
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_organization_scope: "ООО Альтернатива Плюс",
explicit_date_scope: "2021",
unsupported_but_understood_family: "movement_evidence",
stale_replay_forbidden: true
});
expect(result.reason_codes).toContain("mcp_discovery_value_flow_grounded_movement_followup");
expect(result.reason_codes).not.toContain("mcp_discovery_not_applicable_for_supported_exact_turn");
});
it("switches from a grounded exact value-flow answer into document evidence with a clean UTF-8 follow-up", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "а по документам?",
assistantTurnMeaning: {
asked_domain_family: "counterparty",
asked_action_family: "turnover",
explicit_intent_candidate: "customer_revenue_and_payments"
},
followupContext: {
previous_intent: "customer_revenue_and_payments",
previous_filters: {
counterparty: "Группа СВК",
period_from: "2021-01-01",
period_to: "2021-12-31"
},
previous_anchor_type: "counterparty",
previous_anchor_value: "Группа СВК"
}
});
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("counterparty value-flow evidence");
expect(result.turn_meaning_ref).toMatchObject({
asked_domain_family: "documents",
asked_action_family: "list_documents",
explicit_entity_candidates: ["Группа СВК"],
explicit_date_scope: "2021",
unsupported_but_understood_family: "document_evidence",
stale_replay_forbidden: true
});
expect(result.reason_codes).toContain("mcp_discovery_value_flow_grounded_document_followup");
expect(result.reason_codes).not.toContain("mcp_discovery_not_applicable_for_supported_exact_turn");
});
it("switches from a grounded exact value-flow answer into movement evidence with a clean UTF-8 follow-up", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "а по движениям?",
assistantTurnMeaning: {
asked_domain_family: "counterparty",
asked_action_family: "turnover",
explicit_intent_candidate: "customer_revenue_and_payments"
},
followupContext: {
previous_intent: "customer_revenue_and_payments",
previous_filters: {
counterparty: "Группа СВК",
organization: "ООО Альтернатива Плюс",
period_from: "2021-01-01",
period_to: "2021-12-31"
},
previous_anchor_type: "counterparty",
previous_anchor_value: "Группа СВК"
}
});
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("counterparty value-flow evidence");
expect(result.turn_meaning_ref).toMatchObject({
asked_domain_family: "movements",
asked_action_family: "list_movements",
explicit_entity_candidates: ["Группа СВК"],
explicit_organization_scope: "ООО Альтернатива Плюс",
explicit_date_scope: "2021",
unsupported_but_understood_family: "movement_evidence",
stale_replay_forbidden: true
});
expect(result.reason_codes).toContain("mcp_discovery_value_flow_grounded_movement_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: "а по месяцам?",