ARCH: разрешать metadata ambiguity явным выбором data lane

This commit is contained in:
dctouch 2026-04-22 09:33:57 +03:00
parent eac3709f2b
commit f951dae9f0
3 changed files with 106 additions and 0 deletions

View File

@ -374,6 +374,12 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
!rawLifecycleSignal && !rawLifecycleSignal &&
!rawValueFlowSignal && !rawValueFlowSignal &&
hasDocumentEvidenceFollowupSignal(rawText)); hasDocumentEvidenceFollowupSignal(rawText));
const metadataAmbiguityResolvedDocumentFollowupApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
followupSeed.metadataAmbiguityDetected &&
followupSeed.counterparty &&
!rawLifecycleSignal &&
!rawValueFlowSignal &&
hasDocumentEvidenceFollowupSignal(rawText));
const metadataGroundedMovementFollowupApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" && const metadataGroundedMovementFollowupApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
followupSeed.metadataRouteFamily === "movement_evidence" && followupSeed.metadataRouteFamily === "movement_evidence" &&
!followupSeed.metadataAmbiguityDetected && !followupSeed.metadataAmbiguityDetected &&
@ -381,6 +387,12 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
!rawLifecycleSignal && !rawLifecycleSignal &&
!rawValueFlowSignal && !rawValueFlowSignal &&
hasMovementEvidenceFollowupSignal(rawText)); hasMovementEvidenceFollowupSignal(rawText));
const metadataAmbiguityResolvedMovementFollowupApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
followupSeed.metadataAmbiguityDetected &&
followupSeed.counterparty &&
!rawLifecycleSignal &&
!rawValueFlowSignal &&
hasMovementEvidenceFollowupSignal(rawText));
const metadataGroundedLaneContinuationApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" && const metadataGroundedLaneContinuationApplicable = Boolean(followupSeed.pilotScope === "metadata_inspection_v1" &&
(followupSeed.metadataRouteFamily === "document_evidence" || (followupSeed.metadataRouteFamily === "document_evidence" ||
followupSeed.metadataRouteFamily === "movement_evidence") && followupSeed.metadataRouteFamily === "movement_evidence") &&
@ -393,8 +405,10 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
!hasMovementEvidenceFollowupSignal(rawText) && !hasMovementEvidenceFollowupSignal(rawText) &&
hasMetadataDownstreamContinuationSignal(rawText)); hasMetadataDownstreamContinuationSignal(rawText));
const metadataGroundedDocumentLaneApplicable = metadataGroundedDocumentFollowupApplicable || const metadataGroundedDocumentLaneApplicable = metadataGroundedDocumentFollowupApplicable ||
metadataAmbiguityResolvedDocumentFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence"); (metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence");
const metadataGroundedMovementLaneApplicable = metadataGroundedMovementFollowupApplicable || const metadataGroundedMovementLaneApplicable = metadataGroundedMovementFollowupApplicable ||
metadataAmbiguityResolvedMovementFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence"); (metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence");
const effectiveMetadataFollowupSeedApplicable = metadataFollowupSeedApplicable && const effectiveMetadataFollowupSeedApplicable = metadataFollowupSeedApplicable &&
!metadataGroundedDocumentLaneApplicable && !metadataGroundedDocumentLaneApplicable &&
@ -590,9 +604,15 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
if (metadataGroundedDocumentFollowupApplicable) { if (metadataGroundedDocumentFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_document_followup"); pushReason(reasonCodes, "mcp_discovery_metadata_grounded_document_followup");
} }
if (metadataAmbiguityResolvedDocumentFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_resolved_to_document_lane");
}
if (metadataGroundedMovementFollowupApplicable) { if (metadataGroundedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_movement_followup"); pushReason(reasonCodes, "mcp_discovery_metadata_grounded_movement_followup");
} }
if (metadataAmbiguityResolvedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_resolved_to_movement_lane");
}
if (metadataGroundedLaneContinuationApplicable) { if (metadataGroundedLaneContinuationApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_lane_continuation"); pushReason(reasonCodes, "mcp_discovery_metadata_grounded_lane_continuation");
} }

View File

@ -515,6 +515,14 @@ export function buildAssistantMcpDiscoveryTurnInput(
!rawValueFlowSignal && !rawValueFlowSignal &&
hasDocumentEvidenceFollowupSignal(rawText) hasDocumentEvidenceFollowupSignal(rawText)
); );
const metadataAmbiguityResolvedDocumentFollowupApplicable = Boolean(
followupSeed.pilotScope === "metadata_inspection_v1" &&
followupSeed.metadataAmbiguityDetected &&
followupSeed.counterparty &&
!rawLifecycleSignal &&
!rawValueFlowSignal &&
hasDocumentEvidenceFollowupSignal(rawText)
);
const metadataGroundedMovementFollowupApplicable = Boolean( const metadataGroundedMovementFollowupApplicable = Boolean(
followupSeed.pilotScope === "metadata_inspection_v1" && followupSeed.pilotScope === "metadata_inspection_v1" &&
followupSeed.metadataRouteFamily === "movement_evidence" && followupSeed.metadataRouteFamily === "movement_evidence" &&
@ -524,6 +532,14 @@ export function buildAssistantMcpDiscoveryTurnInput(
!rawValueFlowSignal && !rawValueFlowSignal &&
hasMovementEvidenceFollowupSignal(rawText) hasMovementEvidenceFollowupSignal(rawText)
); );
const metadataAmbiguityResolvedMovementFollowupApplicable = Boolean(
followupSeed.pilotScope === "metadata_inspection_v1" &&
followupSeed.metadataAmbiguityDetected &&
followupSeed.counterparty &&
!rawLifecycleSignal &&
!rawValueFlowSignal &&
hasMovementEvidenceFollowupSignal(rawText)
);
const metadataGroundedLaneContinuationApplicable = Boolean( const metadataGroundedLaneContinuationApplicable = Boolean(
followupSeed.pilotScope === "metadata_inspection_v1" && followupSeed.pilotScope === "metadata_inspection_v1" &&
(followupSeed.metadataRouteFamily === "document_evidence" || (followupSeed.metadataRouteFamily === "document_evidence" ||
@ -539,9 +555,11 @@ export function buildAssistantMcpDiscoveryTurnInput(
); );
const metadataGroundedDocumentLaneApplicable = const metadataGroundedDocumentLaneApplicable =
metadataGroundedDocumentFollowupApplicable || metadataGroundedDocumentFollowupApplicable ||
metadataAmbiguityResolvedDocumentFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence"); (metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "document_evidence");
const metadataGroundedMovementLaneApplicable = const metadataGroundedMovementLaneApplicable =
metadataGroundedMovementFollowupApplicable || metadataGroundedMovementFollowupApplicable ||
metadataAmbiguityResolvedMovementFollowupApplicable ||
(metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence"); (metadataGroundedLaneContinuationApplicable && followupSeed.metadataRouteFamily === "movement_evidence");
const effectiveMetadataFollowupSeedApplicable = const effectiveMetadataFollowupSeedApplicable =
metadataFollowupSeedApplicable && metadataFollowupSeedApplicable &&
@ -752,9 +770,15 @@ export function buildAssistantMcpDiscoveryTurnInput(
if (metadataGroundedDocumentFollowupApplicable) { if (metadataGroundedDocumentFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_document_followup"); pushReason(reasonCodes, "mcp_discovery_metadata_grounded_document_followup");
} }
if (metadataAmbiguityResolvedDocumentFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_resolved_to_document_lane");
}
if (metadataGroundedMovementFollowupApplicable) { if (metadataGroundedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_movement_followup"); pushReason(reasonCodes, "mcp_discovery_metadata_grounded_movement_followup");
} }
if (metadataAmbiguityResolvedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_resolved_to_movement_lane");
}
if (metadataGroundedLaneContinuationApplicable) { if (metadataGroundedLaneContinuationApplicable) {
pushReason(reasonCodes, "mcp_discovery_metadata_grounded_lane_continuation"); pushReason(reasonCodes, "mcp_discovery_metadata_grounded_lane_continuation");
} }

View File

@ -361,6 +361,68 @@ describe("assistant MCP discovery turn input adapter", () => {
expect(result.reason_codes).toContain("mcp_discovery_metadata_grounded_lane_continuation"); expect(result.reason_codes).toContain("mcp_discovery_metadata_grounded_lane_continuation");
}); });
it("resolves ambiguous metadata surface into document lane when the follow-up explicitly asks for documents", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "по документам",
followupContext: {
previous_discovery_pilot_scope: "metadata_inspection_v1",
previous_discovery_metadata_ambiguity_detected: true,
previous_filters: {
counterparty: "SVK",
period_from: "2020-01-01",
period_to: "2020-12-31"
},
previous_anchor_type: "counterparty",
previous_anchor_value: "SVK"
}
});
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: ["SVK"],
explicit_date_scope: "2020",
unsupported_but_understood_family: "document_evidence",
stale_replay_forbidden: true
});
expect(result.reason_codes).toContain("mcp_discovery_metadata_ambiguity_resolved_to_document_lane");
});
it("resolves ambiguous metadata surface into movement lane when the follow-up explicitly asks for movements", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "по движениям",
followupContext: {
previous_discovery_pilot_scope: "metadata_inspection_v1",
previous_discovery_metadata_ambiguity_detected: true,
previous_filters: {
counterparty: "SVK",
period_from: "2020-01-01",
period_to: "2020-12-31"
},
previous_anchor_type: "counterparty",
previous_anchor_value: "SVK"
}
});
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: ["SVK"],
explicit_date_scope: "2020",
unsupported_but_understood_family: "movement_evidence",
stale_replay_forbidden: true
});
expect(result.reason_codes).toContain("mcp_discovery_metadata_ambiguity_resolved_to_movement_lane");
});
it("switches the checked year on a short payout follow-up while keeping prior discovery counterparty", () => { it("switches the checked year on a short payout follow-up while keeping prior discovery counterparty", () => {
const result = buildAssistantMcpDiscoveryTurnInput({ const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "а теперь за 2021?", userMessage: "а теперь за 2021?",