ARCH: замкнуть metadata-scoped clarification recovery loops
This commit is contained in:
@@ -329,6 +329,27 @@ export function readAssistantMcpDiscoveryLoopUnsupportedFamily(
|
||||
return toNonEmptyString(readAssistantMcpDiscoveryLoopState(debug)?.unsupported_but_understood_family);
|
||||
}
|
||||
|
||||
export function readAssistantMcpDiscoveryLoopMetadataScopeHint(
|
||||
debug: Record<string, unknown> | null,
|
||||
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||
): string | null {
|
||||
return (
|
||||
toNonEmptyString(readAssistantMcpDiscoveryLoopState(debug)?.metadata_scope_hint) ??
|
||||
toNonEmptyString(readAssistantMcpDiscoveryTurnMeaning(debug)?.metadata_scope_hint) ??
|
||||
toNonEmptyString(readAssistantMcpDiscoveryDataNeedGraph(debug)?.metadata_scope_hint)
|
||||
);
|
||||
}
|
||||
|
||||
export function readAssistantMcpDiscoveryLoopSubjectResolutionOptional(
|
||||
debug: Record<string, unknown> | null
|
||||
): boolean {
|
||||
return (
|
||||
readAssistantMcpDiscoveryLoopState(debug)?.subject_resolution_optional === true ||
|
||||
readAssistantMcpDiscoveryTurnMeaning(debug)?.subject_resolution_optional === true ||
|
||||
readAssistantMcpDiscoveryDataNeedGraph(debug)?.subject_resolution_optional === true
|
||||
);
|
||||
}
|
||||
|
||||
export function readAssistantMcpDiscoveryMetadataRouteFamily(
|
||||
debug: Record<string, unknown> | null,
|
||||
toNonEmptyString: (value: unknown) => string | null = fallbackToNonEmptyString
|
||||
@@ -557,6 +578,13 @@ export function readAddressDebugCounterparty(
|
||||
if (String(debug?.anchor_type ?? "") === "counterparty") {
|
||||
return toNonEmptyString(debug?.anchor_value_resolved) ?? toNonEmptyString(debug?.anchor_value_raw);
|
||||
}
|
||||
const discoveryPilotScope = readAssistantMcpDiscoveryPilotScope(debug, toNonEmptyString);
|
||||
const suppressDiscoveryEntityCarryover =
|
||||
discoveryPilotScope === "metadata_inspection_v1" ||
|
||||
readAssistantMcpDiscoveryLoopSubjectResolutionOptional(debug);
|
||||
if (suppressDiscoveryEntityCarryover) {
|
||||
return null;
|
||||
}
|
||||
const discoveryEntities = collectAssistantMcpDiscoveryEntityCandidates(debug, toNonEmptyString);
|
||||
for (const entity of discoveryEntities) {
|
||||
const text = toNonEmptyString(entity);
|
||||
|
||||
@@ -14,6 +14,8 @@ export interface AssistantMcpDiscoveryDataNeedGraphContract {
|
||||
schema_version: typeof ASSISTANT_MCP_DISCOVERY_DATA_NEED_GRAPH_SCHEMA_VERSION;
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph";
|
||||
subject_candidates: string[];
|
||||
metadata_scope_hint?: string | null;
|
||||
subject_resolution_optional?: boolean;
|
||||
business_fact_family: string | null;
|
||||
action_family: string | null;
|
||||
aggregation_need: string | null;
|
||||
@@ -205,6 +207,16 @@ function allowsOpenScopeWithoutSubject(input: {
|
||||
);
|
||||
}
|
||||
|
||||
function allowsMetadataScopedOpenLaneWithoutSubject(input: {
|
||||
family: string | null;
|
||||
subjectResolutionOptional: boolean;
|
||||
}): boolean {
|
||||
return Boolean(
|
||||
input.subjectResolutionOptional &&
|
||||
(input.family === "movement_evidence" || input.family === "document_evidence")
|
||||
);
|
||||
}
|
||||
|
||||
function rankingNeedFromRawUtterance(value: string): string | null {
|
||||
const text = lower(value);
|
||||
if (!text) {
|
||||
@@ -249,6 +261,7 @@ function decompositionCandidatesFor(input: {
|
||||
comparisonNeed: string | null;
|
||||
rankingNeed: string | null;
|
||||
openScopeWithoutSubject: boolean;
|
||||
metadataScopedOpenLaneWithoutSubject: boolean;
|
||||
}): string[] {
|
||||
const result: string[] = [];
|
||||
if (input.family === "schema_surface") {
|
||||
@@ -295,13 +308,17 @@ function decompositionCandidatesFor(input: {
|
||||
return result;
|
||||
}
|
||||
if (input.family === "movement_evidence") {
|
||||
pushUnique(result, "resolve_entity_reference");
|
||||
if (!input.metadataScopedOpenLaneWithoutSubject) {
|
||||
pushUnique(result, "resolve_entity_reference");
|
||||
}
|
||||
pushUnique(result, "fetch_scoped_movements");
|
||||
pushUnique(result, "probe_coverage");
|
||||
return result;
|
||||
}
|
||||
if (input.family === "document_evidence") {
|
||||
pushUnique(result, "resolve_entity_reference");
|
||||
if (!input.metadataScopedOpenLaneWithoutSubject) {
|
||||
pushUnique(result, "resolve_entity_reference");
|
||||
}
|
||||
pushUnique(result, "fetch_scoped_documents");
|
||||
pushUnique(result, "probe_coverage");
|
||||
return result;
|
||||
@@ -345,6 +362,8 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
|
||||
const seededRankingNeed = toNonEmptyString(turnMeaning?.seeded_ranking_need);
|
||||
const explicitDateScope = toNonEmptyString(turnMeaning?.explicit_date_scope);
|
||||
const explicitOrganizationScope = toNonEmptyString(turnMeaning?.explicit_organization_scope);
|
||||
const metadataScopeHint = toNonEmptyString(turnMeaning?.metadata_scope_hint);
|
||||
const subjectResolutionOptional = turnMeaning?.subject_resolution_optional === true;
|
||||
const subjectCandidates = (turnMeaning?.explicit_entity_candidates ?? [])
|
||||
.map((item) => toNonEmptyString(item))
|
||||
.filter((item): item is string => Boolean(item));
|
||||
@@ -369,6 +388,12 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
|
||||
rankingNeed,
|
||||
oneSidedOpenScopeTotalHint
|
||||
});
|
||||
const metadataScopedOpenLaneWithoutSubject =
|
||||
subjectCandidates.length === 0 &&
|
||||
allowsMetadataScopedOpenLaneWithoutSubject({
|
||||
family: businessFactFamily,
|
||||
subjectResolutionOptional
|
||||
});
|
||||
const clarificationGaps: string[] = [];
|
||||
if (unsupported === "metadata_lane_choice_clarification" || action === "resolve_next_lane") {
|
||||
pushUnique(clarificationGaps, "lane_family_choice");
|
||||
@@ -380,7 +405,18 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
|
||||
!explicitOrganizationScope
|
||||
) {
|
||||
pushUnique(clarificationGaps, "organization");
|
||||
} else if (subjectCandidates.length === 0 && businessFactFamily !== "schema_surface" && !openScopeWithoutSubject) {
|
||||
} else if (
|
||||
subjectCandidates.length === 0 &&
|
||||
metadataScopedOpenLaneWithoutSubject &&
|
||||
!explicitOrganizationScope
|
||||
) {
|
||||
pushUnique(clarificationGaps, "organization");
|
||||
} else if (
|
||||
subjectCandidates.length === 0 &&
|
||||
businessFactFamily !== "schema_surface" &&
|
||||
!openScopeWithoutSubject &&
|
||||
!metadataScopedOpenLaneWithoutSubject
|
||||
) {
|
||||
pushUnique(clarificationGaps, "subject");
|
||||
}
|
||||
const timeScopeNeed = timeScopeNeedFor({
|
||||
@@ -393,12 +429,13 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
|
||||
}
|
||||
const decompositionCandidates = decompositionCandidatesFor({
|
||||
family: businessFactFamily,
|
||||
action,
|
||||
aggregationNeed,
|
||||
comparisonNeed,
|
||||
rankingNeed,
|
||||
openScopeWithoutSubject
|
||||
});
|
||||
action,
|
||||
aggregationNeed,
|
||||
comparisonNeed,
|
||||
rankingNeed,
|
||||
openScopeWithoutSubject,
|
||||
metadataScopedOpenLaneWithoutSubject
|
||||
});
|
||||
const reasonCodes: string[] = [];
|
||||
pushReason(reasonCodes, "data_need_graph_built");
|
||||
if (businessFactFamily) {
|
||||
@@ -418,6 +455,9 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
|
||||
if (openScopeWithoutSubject && !rankingNeed && !comparisonNeed) {
|
||||
pushReason(reasonCodes, "data_need_graph_open_scope_total_without_subject");
|
||||
}
|
||||
if (metadataScopedOpenLaneWithoutSubject) {
|
||||
pushReason(reasonCodes, "data_need_graph_metadata_scoped_open_lane_without_subject");
|
||||
}
|
||||
if (allTimeScopeHint) {
|
||||
pushReason(reasonCodes, "data_need_graph_all_time_scope_hint");
|
||||
}
|
||||
@@ -432,6 +472,8 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
|
||||
schema_version: ASSISTANT_MCP_DISCOVERY_DATA_NEED_GRAPH_SCHEMA_VERSION,
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph",
|
||||
subject_candidates: subjectCandidates,
|
||||
metadata_scope_hint: metadataScopeHint,
|
||||
subject_resolution_optional: subjectResolutionOptional || undefined,
|
||||
business_fact_family: businessFactFamily,
|
||||
action_family: toNonEmptyString(turnMeaning?.asked_action_family),
|
||||
aggregation_need: aggregationNeed,
|
||||
|
||||
@@ -127,6 +127,16 @@ function hasSubjectCandidates(graph: AssistantMcpDiscoveryDataNeedGraphContract
|
||||
return (graph?.subject_candidates.length ?? 0) > 0;
|
||||
}
|
||||
|
||||
function hasMetadataScopedOpenLane(
|
||||
graph: AssistantMcpDiscoveryDataNeedGraphContract | null | undefined,
|
||||
meaning: AssistantMcpDiscoveryTurnMeaningRef | null | undefined
|
||||
): boolean {
|
||||
return Boolean(
|
||||
graph?.subject_resolution_optional === true ||
|
||||
meaning?.subject_resolution_optional === true
|
||||
);
|
||||
}
|
||||
|
||||
function hasReasonCode(
|
||||
graph: AssistantMcpDiscoveryDataNeedGraphContract | null | undefined,
|
||||
reasonCode: string
|
||||
@@ -150,6 +160,12 @@ function addScopeAxes(axes: string[], meaning: AssistantMcpDiscoveryTurnMeaningR
|
||||
}
|
||||
}
|
||||
|
||||
function addMetadataScopeAxis(axes: string[], meaning: AssistantMcpDiscoveryTurnMeaningRef | null | undefined): void {
|
||||
if (toNonEmptyString(meaning?.metadata_scope_hint)) {
|
||||
pushUnique(axes, "metadata_scope");
|
||||
}
|
||||
}
|
||||
|
||||
function addTimeScopeAxes(
|
||||
axes: string[],
|
||||
dataNeedGraph: AssistantMcpDiscoveryDataNeedGraphContract | null | undefined
|
||||
@@ -417,7 +433,7 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
||||
const graphAction = lower(dataNeedGraph?.action_family);
|
||||
const graphAggregation = lower(dataNeedGraph?.aggregation_need);
|
||||
const graphClarificationGaps = (dataNeedGraph?.clarification_gaps ?? []).map((item) => lower(item));
|
||||
const organizationScope = toNonEmptyString(meaning?.explicit_organization_scope);
|
||||
const metadataScopedOpenLane = hasMetadataScopedOpenLane(dataNeedGraph, meaning);
|
||||
const openScopeTotalWithoutSubject =
|
||||
graphFactFamily === "value_flow" &&
|
||||
!hasSubjectCandidates(dataNeedGraph) &&
|
||||
@@ -426,6 +442,7 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
||||
const axes: string[] = [];
|
||||
const requestedAggregationAxis = aggregationAxis(meaning);
|
||||
addScopeAxes(axes, meaning);
|
||||
addMetadataScopeAxis(axes, meaning);
|
||||
addTimeScopeAxes(axes, dataNeedGraph);
|
||||
|
||||
if (graphClarificationGaps.includes("lane_family_choice")) {
|
||||
@@ -654,6 +671,27 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
||||
}
|
||||
|
||||
if (graphFactFamily === "movement_evidence") {
|
||||
if (metadataScopedOpenLane) {
|
||||
pushUnique(axes, "organization");
|
||||
pushUnique(axes, "coverage_target");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["query_movements", "probe_coverage"],
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "movement evidence",
|
||||
chainId: "movement_evidence",
|
||||
chainSummary:
|
||||
"Keep the metadata-scoped movement lane, ask only for the remaining business scope, then fetch scoped movement rows and probe coverage without pretending there is a grounded counterparty.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
reason: "planner_selected_metadata_scoped_movement_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
}
|
||||
pushUnique(axes, "coverage_target");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
@@ -674,6 +712,27 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
|
||||
}
|
||||
|
||||
if (graphFactFamily === "document_evidence") {
|
||||
if (metadataScopedOpenLane) {
|
||||
pushUnique(axes, "organization");
|
||||
pushUnique(axes, "coverage_target");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["query_documents", "probe_coverage"],
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "document evidence",
|
||||
chainId: "document_evidence",
|
||||
chainSummary:
|
||||
"Keep the metadata-scoped document lane, ask only for the remaining business scope, then fetch scoped document rows and probe coverage without pretending there is a grounded counterparty.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
reason: "planner_selected_metadata_scoped_document_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
}
|
||||
pushUnique(axes, "coverage_target");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
|
||||
@@ -27,8 +27,10 @@ export interface AssistantMcpDiscoveryTurnMeaningRef {
|
||||
seeded_ranking_need?: string | null;
|
||||
explicit_entity_candidates?: string[];
|
||||
metadata_ambiguity_entity_sets?: string[];
|
||||
metadata_scope_hint?: string | null;
|
||||
explicit_organization_scope?: string | null;
|
||||
explicit_date_scope?: string | null;
|
||||
subject_resolution_optional?: boolean | null;
|
||||
meaning_confidence?: number | null;
|
||||
unsupported_but_understood_family?: string | null;
|
||||
stale_replay_forbidden?: boolean | null;
|
||||
|
||||
@@ -53,6 +53,8 @@ export interface AssistantMcpDiscoveryLoopStateContract {
|
||||
pending_axes: string[];
|
||||
provided_axes: string[];
|
||||
explicit_entity_candidates: string[];
|
||||
metadata_scope_hint: string | null;
|
||||
subject_resolution_optional: boolean;
|
||||
explicit_organization_scope: string | null;
|
||||
explicit_date_scope: string | null;
|
||||
}
|
||||
@@ -184,6 +186,13 @@ function buildLoopState(
|
||||
pending_axes: plannerClarificationGaps.length > 0 ? plannerClarificationGaps : flattenAxes(pilot, "missing_axis_options"),
|
||||
provided_axes: flattenAxes(pilot, "provided_axes"),
|
||||
explicit_entity_candidates: entityCandidatesFromPlanner(planner),
|
||||
metadata_scope_hint:
|
||||
planner.discovery_plan.turn_meaning_ref?.metadata_scope_hint ??
|
||||
planner.data_need_graph?.metadata_scope_hint ??
|
||||
null,
|
||||
subject_resolution_optional:
|
||||
planner.discovery_plan.turn_meaning_ref?.subject_resolution_optional === true ||
|
||||
planner.data_need_graph?.subject_resolution_optional === true,
|
||||
explicit_organization_scope: planner.discovery_plan.turn_meaning_ref?.explicit_organization_scope ?? null,
|
||||
explicit_date_scope: planner.discovery_plan.turn_meaning_ref?.explicit_date_scope ?? null
|
||||
};
|
||||
|
||||
@@ -427,6 +427,8 @@ function collectFollowupDiscoverySeed(followupContext: Record<string, unknown> |
|
||||
rankingNeed: string | null;
|
||||
organization: string | null;
|
||||
dateScope: string | null;
|
||||
metadataScopeHint: string | null;
|
||||
subjectResolutionOptional: boolean;
|
||||
metadataRouteFamily: AssistantMcpDiscoveryMetadataRouteFamily | null;
|
||||
metadataRouteFamilySelectionBasis: AssistantMcpDiscoveryMetadataSurfaceRef["route_family_selection_basis"];
|
||||
metadataSelectedEntitySet: string | null;
|
||||
@@ -445,6 +447,9 @@ function collectFollowupDiscoverySeed(followupContext: Record<string, unknown> |
|
||||
const loopAskedDomainFamily = toNonEmptyString(followupContext?.previous_discovery_loop_asked_domain_family);
|
||||
const loopAskedActionFamily = toNonEmptyString(followupContext?.previous_discovery_loop_asked_action_family);
|
||||
const loopUnsupportedFamily = toNonEmptyString(followupContext?.previous_discovery_loop_unsupported_family);
|
||||
const loopMetadataScopeHint = toNonEmptyString(followupContext?.previous_discovery_loop_metadata_scope_hint);
|
||||
const loopSubjectResolutionOptional =
|
||||
followupContext?.previous_discovery_loop_subject_resolution_optional === true;
|
||||
const previousIntent =
|
||||
toNonEmptyString(followupContext?.target_intent) ?? toNonEmptyString(followupContext?.previous_intent);
|
||||
const loopMapped =
|
||||
@@ -474,14 +479,19 @@ function collectFollowupDiscoverySeed(followupContext: Record<string, unknown> |
|
||||
followupContext?.previous_discovery_entity_ambiguity_candidates
|
||||
);
|
||||
const ambiguityBlocksImplicitGrounding =
|
||||
pilotScope === "entity_resolution_search_v1" && entityResolutionStatus === "ambiguous";
|
||||
effectivePilotScope === "entity_resolution_search_v1" && entityResolutionStatus === "ambiguous";
|
||||
const metadataPilotCarriesScopeOnly =
|
||||
effectivePilotScope === "metadata_inspection_v1" || loopSubjectResolutionOptional;
|
||||
const metadataScopeHint =
|
||||
loopMetadataScopeHint ??
|
||||
(loopSubjectResolutionOptional ? discoveryEntities[0] ?? null : null);
|
||||
const counterparty =
|
||||
toNonEmptyString(previousFilters?.counterparty) ??
|
||||
toNonEmptyString(rootFilters?.counterparty) ??
|
||||
(toNonEmptyString(followupContext?.previous_anchor_type) === "counterparty"
|
||||
? toNonEmptyString(followupContext?.previous_anchor_value)
|
||||
: null) ??
|
||||
(ambiguityBlocksImplicitGrounding ? null : discoveryEntities[0] ?? null);
|
||||
(ambiguityBlocksImplicitGrounding || metadataPilotCarriesScopeOnly ? null : discoveryEntities[0] ?? null);
|
||||
const organization =
|
||||
toNonEmptyString(previousFilters?.organization) ??
|
||||
toNonEmptyString(rootFilters?.organization) ??
|
||||
@@ -501,12 +511,15 @@ function collectFollowupDiscoverySeed(followupContext: Record<string, unknown> |
|
||||
loopPendingAxes,
|
||||
loopProvidedAxes,
|
||||
counterparty,
|
||||
discoveryEntity: ambiguityBlocksImplicitGrounding ? null : discoveryEntities[0] ?? null,
|
||||
discoveryEntity:
|
||||
ambiguityBlocksImplicitGrounding || loopSubjectResolutionOptional ? null : discoveryEntities[0] ?? null,
|
||||
entityResolutionStatus,
|
||||
entityResolutionAmbiguityCandidates,
|
||||
rankingNeed: toNonEmptyString(followupContext?.previous_discovery_ranking_need),
|
||||
organization,
|
||||
dateScope,
|
||||
metadataScopeHint,
|
||||
subjectResolutionOptional: loopSubjectResolutionOptional,
|
||||
metadataRouteFamily: normalizeMetadataRouteFamily(followupContext?.previous_discovery_metadata_route_family),
|
||||
metadataRouteFamilySelectionBasis: normalizeMetadataRouteFamilySelectionBasis(
|
||||
followupContext?.previous_discovery_metadata_route_family_selection_basis
|
||||
@@ -1084,11 +1097,18 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
!rawValueFlowSignal &&
|
||||
hasMetadataObjectHint(rawText)
|
||||
);
|
||||
const metadataLaneCarryoverAvailable = Boolean(
|
||||
followupSeed.counterparty ||
|
||||
followupSeed.discoveryEntity ||
|
||||
followupSeed.metadataScopeHint ||
|
||||
followupSeed.metadataSelectedEntitySet ||
|
||||
followupSeed.metadataSelectedSurfaceObjects.length > 0
|
||||
);
|
||||
const metadataGroundedDocumentFollowupApplicable = Boolean(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataRouteFamily === "document_evidence" &&
|
||||
!followupSeed.metadataAmbiguityDetected &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
metadataDocumentHintSignal
|
||||
@@ -1098,7 +1118,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
(followupSeed.metadataAmbiguityEntitySets.length === 0 ||
|
||||
metadataEntitySetsSuggestDocumentLane(followupSeed.metadataAmbiguityEntitySets)) &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
metadataDocumentHintSignal
|
||||
@@ -1107,7 +1127,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataRouteFamily === "movement_evidence" &&
|
||||
!followupSeed.metadataAmbiguityDetected &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
metadataMovementHintSignal
|
||||
);
|
||||
@@ -1116,7 +1136,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
(followupSeed.metadataAmbiguityEntitySets.length === 0 ||
|
||||
metadataEntitySetsSuggestMovementLane(followupSeed.metadataAmbiguityEntitySets)) &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
metadataMovementHintSignal
|
||||
);
|
||||
@@ -1206,7 +1226,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
(followupSeed.metadataRouteFamily === "document_evidence" ||
|
||||
followupSeed.metadataRouteFamily === "movement_evidence") &&
|
||||
!followupSeed.metadataAmbiguityDetected &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
@@ -1229,7 +1249,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
metadataAmbiguityCollapsesToDocumentLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
@@ -1241,7 +1261,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
followupSeed.pilotScope === "metadata_inspection_v1" &&
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
metadataAmbiguityCollapsesToMovementLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
@@ -1254,7 +1274,7 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
followupSeed.metadataAmbiguityDetected &&
|
||||
!metadataAmbiguityCollapsesToDocumentLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
!metadataAmbiguityCollapsesToMovementLane(followupSeed.metadataAmbiguityEntitySets) &&
|
||||
followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
@@ -1265,6 +1285,14 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
const metadataGroundedDocumentLaneApplicable =
|
||||
metadataGroundedDocumentFollowupApplicable ||
|
||||
metadataAmbiguityResolvedDocumentFollowupApplicable ||
|
||||
(followupSeed.subjectResolutionOptional &&
|
||||
!followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
followupSeed.domain === "documents" &&
|
||||
followupSeed.action === "list_documents") ||
|
||||
entityResolutionGroundedDocumentFollowupApplicable ||
|
||||
entityResolutionClarifiedDocumentFollowupApplicable ||
|
||||
valueFlowGroundedDocumentFollowupApplicable ||
|
||||
@@ -1274,6 +1302,14 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
const metadataGroundedMovementLaneApplicable =
|
||||
metadataGroundedMovementFollowupApplicable ||
|
||||
metadataAmbiguityResolvedMovementFollowupApplicable ||
|
||||
(followupSeed.subjectResolutionOptional &&
|
||||
!followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable &&
|
||||
!rawLifecycleSignal &&
|
||||
!rawValueFlowSignal &&
|
||||
!rawMetadataSignal &&
|
||||
followupSeed.domain === "movements" &&
|
||||
followupSeed.action === "list_movements") ||
|
||||
entityResolutionGroundedMovementFollowupApplicable ||
|
||||
entityResolutionClarifiedMovementFollowupApplicable ||
|
||||
valueFlowGroundedMovementFollowupApplicable ||
|
||||
@@ -1346,7 +1382,20 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
!metadataGroundedDocumentLaneApplicable &&
|
||||
!metadataGroundedMovementLaneApplicable
|
||||
});
|
||||
const groundedFollowupEntity = followupSeed.counterparty ?? followupSeed.discoveryEntity;
|
||||
const metadataLaneScopeHint =
|
||||
rawMetadataScopeHint ??
|
||||
followupSeed.metadataScopeHint ??
|
||||
followupSeed.discoveryEntity ??
|
||||
followupSeed.metadataSelectedEntitySet ??
|
||||
null;
|
||||
const metadataScopedLaneWithoutSubject = Boolean(
|
||||
(metadataGroundedMovementLaneApplicable || metadataGroundedDocumentLaneApplicable) &&
|
||||
!followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable
|
||||
);
|
||||
const groundedFollowupEntity = metadataScopedLaneWithoutSubject
|
||||
? null
|
||||
: followupSeed.counterparty ?? followupSeed.discoveryEntity;
|
||||
const entityCandidates = entityResolutionSignal ? [] : [];
|
||||
if (entityResolutionSignal) {
|
||||
pushNormalizedEntityResolutionCandidate(entityCandidates, entityResolutionClarificationCandidate);
|
||||
@@ -1366,11 +1415,17 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
pushScopedEntityCandidate(entityCandidates, normalizedPredecomposeCounterparty, groundedFollowupEntity);
|
||||
if (!groundedFollowupEntity) {
|
||||
pushScopedEntityCandidate(entityCandidates, followupSeed.counterparty, null);
|
||||
pushScopedEntityCandidate(entityCandidates, followupSeed.discoveryEntity, null);
|
||||
if (!metadataScopedLaneWithoutSubject) {
|
||||
pushScopedEntityCandidate(entityCandidates, followupSeed.discoveryEntity, null);
|
||||
}
|
||||
}
|
||||
pushScopedEntityCandidate(entityCandidates, rawEntityCandidate, groundedFollowupEntity);
|
||||
}
|
||||
if ((rawMetadataSignal || metadataFollowupSeedApplicable) && !groundedFollowupEntity) {
|
||||
if (
|
||||
(rawMetadataSignal || metadataFollowupSeedApplicable) &&
|
||||
!groundedFollowupEntity &&
|
||||
!metadataScopedLaneWithoutSubject
|
||||
) {
|
||||
pushUnique(entityCandidates, followupSeed.discoveryEntity);
|
||||
pushUnique(entityCandidates, rawMetadataScopeHint);
|
||||
}
|
||||
@@ -1487,8 +1542,10 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
metadataAmbiguityLaneClarificationApplicable && followupSeed.metadataAmbiguityEntitySets.length > 0
|
||||
? followupSeed.metadataAmbiguityEntitySets
|
||||
: undefined,
|
||||
metadata_scope_hint: metadataLaneScopeHint,
|
||||
explicit_organization_scope: explicitOrganizationScope,
|
||||
explicit_date_scope: explicitDateScope,
|
||||
subject_resolution_optional: metadataScopedLaneWithoutSubject || undefined,
|
||||
unsupported_but_understood_family:
|
||||
unsupported ??
|
||||
(lifecycleSignal
|
||||
@@ -1546,12 +1603,18 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
if ((turnMeaning.metadata_ambiguity_entity_sets?.length ?? 0) > 0) {
|
||||
cleanTurnMeaning.metadata_ambiguity_entity_sets = turnMeaning.metadata_ambiguity_entity_sets;
|
||||
}
|
||||
if (toNonEmptyString(turnMeaning.metadata_scope_hint)) {
|
||||
cleanTurnMeaning.metadata_scope_hint = turnMeaning.metadata_scope_hint;
|
||||
}
|
||||
if (toNonEmptyString(turnMeaning.explicit_organization_scope)) {
|
||||
cleanTurnMeaning.explicit_organization_scope = turnMeaning.explicit_organization_scope;
|
||||
}
|
||||
if (toNonEmptyString(turnMeaning.explicit_date_scope)) {
|
||||
cleanTurnMeaning.explicit_date_scope = turnMeaning.explicit_date_scope;
|
||||
}
|
||||
if (turnMeaning.subject_resolution_optional) {
|
||||
cleanTurnMeaning.subject_resolution_optional = true;
|
||||
}
|
||||
if (toNonEmptyString(turnMeaning.unsupported_but_understood_family)) {
|
||||
cleanTurnMeaning.unsupported_but_understood_family = turnMeaning.unsupported_but_understood_family;
|
||||
}
|
||||
@@ -1668,6 +1731,9 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||
if (metadataAmbiguityResolvedMovementFollowupApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_ambiguity_resolved_to_movement_lane");
|
||||
}
|
||||
if (metadataScopedLaneWithoutSubject) {
|
||||
pushReason(reasonCodes, "mcp_discovery_metadata_scoped_lane_without_subject");
|
||||
}
|
||||
if (entityResolutionGroundedDocumentFollowupApplicable) {
|
||||
pushReason(reasonCodes, "mcp_discovery_entity_resolution_grounded_document_followup");
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import {
|
||||
readAssistantMcpDiscoveryLoopAskedDomainFamily,
|
||||
readAssistantMcpDiscoveryLoopAskedActionFamily,
|
||||
readAssistantMcpDiscoveryLoopUnsupportedFamily,
|
||||
readAssistantMcpDiscoveryLoopMetadataScopeHint,
|
||||
readAssistantMcpDiscoveryLoopSubjectResolutionOptional,
|
||||
readAddressDebugTemporalScope,
|
||||
readAssistantMcpDiscoveryPilotScope,
|
||||
resolveOrganizationClarificationContinuation,
|
||||
@@ -727,6 +729,12 @@ export function createAssistantTransitionPolicy(deps) {
|
||||
carryoverSourceDebug,
|
||||
deps.toNonEmptyString
|
||||
);
|
||||
const sourceDiscoveryLoopMetadataScopeHint = readAssistantMcpDiscoveryLoopMetadataScopeHint(
|
||||
carryoverSourceDebug,
|
||||
deps.toNonEmptyString
|
||||
);
|
||||
const sourceDiscoveryLoopSubjectResolutionOptional =
|
||||
readAssistantMcpDiscoveryLoopSubjectResolutionOptional(carryoverSourceDebug);
|
||||
const sourceDiscoveryRankingNeed = readAssistantMcpDiscoveryRankingNeed(
|
||||
carryoverSourceDebug,
|
||||
deps.toNonEmptyString
|
||||
@@ -1083,6 +1091,9 @@ export function createAssistantTransitionPolicy(deps) {
|
||||
previous_discovery_loop_asked_domain_family: sourceDiscoveryLoopAskedDomainFamily ?? undefined,
|
||||
previous_discovery_loop_asked_action_family: sourceDiscoveryLoopAskedActionFamily ?? undefined,
|
||||
previous_discovery_loop_unsupported_family: sourceDiscoveryLoopUnsupportedFamily ?? undefined,
|
||||
previous_discovery_loop_metadata_scope_hint: sourceDiscoveryLoopMetadataScopeHint ?? undefined,
|
||||
previous_discovery_loop_subject_resolution_optional:
|
||||
sourceDiscoveryLoopSubjectResolutionOptional || undefined,
|
||||
previous_discovery_ranking_need: sourceDiscoveryRankingNeed ?? undefined,
|
||||
previous_discovery_entity_ambiguity_candidates:
|
||||
sourceDiscoveryEntityAmbiguityCandidates.length > 0
|
||||
|
||||
Reference in New Issue
Block a user