Planner Autonomy: вынести catalog chain matches в контракт
This commit is contained in:
@@ -345,6 +345,20 @@ function budgetOverrideFor(input, recipe) {
|
||||
}
|
||||
return {};
|
||||
}
|
||||
function catalogChainTemplateMatchesForContract(input, recipe) {
|
||||
const dataNeedGraph = input.dataNeedGraph ?? null;
|
||||
if (!dataNeedGraph) {
|
||||
return [];
|
||||
}
|
||||
return (0, assistantMcpCatalogIndex_1.searchAssistantMcpCatalogChainTemplatesByFactAxis)({
|
||||
business_fact_family: dataNeedGraph.business_fact_family,
|
||||
action_family: toNonEmptyString(input.turnMeaning?.asked_action_family) ?? dataNeedGraph.action_family,
|
||||
required_axes: recipe.axes,
|
||||
comparison_need: dataNeedGraph.comparison_need,
|
||||
ranking_need: dataNeedGraph.ranking_need,
|
||||
aggregation_need: dataNeedGraph.aggregation_need
|
||||
});
|
||||
}
|
||||
function routeFamilyFromThinMetadataSurfaceInput(input) {
|
||||
const surface = input.metadataSurface ?? null;
|
||||
const surfaceRouteFamily = routeFamilyFromMetadataSurfaceRef(surface);
|
||||
@@ -956,6 +970,7 @@ function planAssistantMcpDiscovery(input) {
|
||||
const semanticDataNeed = toNonEmptyString(input.semanticDataNeed) ?? recipe.semanticDataNeed;
|
||||
const dataNeedGraph = input.dataNeedGraph ?? null;
|
||||
const metadataSurface = input.metadataSurface ?? null;
|
||||
const catalogChainTemplateMatches = catalogChainTemplateMatchesForContract(input, recipe);
|
||||
const reasonCodes = [];
|
||||
pushReason(reasonCodes, recipe.reason);
|
||||
for (const reason of recipe.extraReasons ?? []) {
|
||||
@@ -1018,6 +1033,7 @@ function planAssistantMcpDiscovery(input) {
|
||||
metadata_surface_ref: metadataSurface,
|
||||
selected_chain_id: recipe.chainId,
|
||||
selected_chain_summary: recipe.chainSummary,
|
||||
catalog_chain_template_matches: catalogChainTemplateMatches,
|
||||
proposed_primitives: recipe.primitives,
|
||||
required_axes: recipe.axes,
|
||||
discovery_plan: plan,
|
||||
|
||||
@@ -70,6 +70,7 @@ export interface AssistantMcpDiscoveryPlannerContract {
|
||||
metadata_surface_ref: AssistantMcpDiscoveryMetadataSurfaceRef | null;
|
||||
selected_chain_id: AssistantMcpDiscoveryChainId;
|
||||
selected_chain_summary: string;
|
||||
catalog_chain_template_matches: AssistantMcpCatalogChainTemplateId[];
|
||||
proposed_primitives: AssistantMcpDiscoveryPrimitive[];
|
||||
required_axes: string[];
|
||||
discovery_plan: AssistantMcpDiscoveryPlanContract;
|
||||
@@ -536,6 +537,24 @@ function budgetOverrideFor(input: AssistantMcpDiscoveryPlannerInput, recipe: Pla
|
||||
return {};
|
||||
}
|
||||
|
||||
function catalogChainTemplateMatchesForContract(
|
||||
input: AssistantMcpDiscoveryPlannerInput,
|
||||
recipe: PlannerRecipe
|
||||
): AssistantMcpCatalogChainTemplateId[] {
|
||||
const dataNeedGraph = input.dataNeedGraph ?? null;
|
||||
if (!dataNeedGraph) {
|
||||
return [];
|
||||
}
|
||||
return searchAssistantMcpCatalogChainTemplatesByFactAxis({
|
||||
business_fact_family: dataNeedGraph.business_fact_family,
|
||||
action_family: toNonEmptyString(input.turnMeaning?.asked_action_family) ?? dataNeedGraph.action_family,
|
||||
required_axes: recipe.axes,
|
||||
comparison_need: dataNeedGraph.comparison_need,
|
||||
ranking_need: dataNeedGraph.ranking_need,
|
||||
aggregation_need: dataNeedGraph.aggregation_need
|
||||
});
|
||||
}
|
||||
|
||||
function routeFamilyFromThinMetadataSurfaceInput(
|
||||
input: AssistantMcpDiscoveryPlannerInput
|
||||
): AssistantMcpDiscoveryMetadataRouteFamily | null {
|
||||
@@ -1193,6 +1212,7 @@ export function planAssistantMcpDiscovery(
|
||||
const semanticDataNeed = toNonEmptyString(input.semanticDataNeed) ?? recipe.semanticDataNeed;
|
||||
const dataNeedGraph = input.dataNeedGraph ?? null;
|
||||
const metadataSurface = input.metadataSurface ?? null;
|
||||
const catalogChainTemplateMatches = catalogChainTemplateMatchesForContract(input, recipe);
|
||||
const reasonCodes: string[] = [];
|
||||
pushReason(reasonCodes, recipe.reason);
|
||||
for (const reason of recipe.extraReasons ?? []) {
|
||||
@@ -1259,6 +1279,7 @@ export function planAssistantMcpDiscovery(
|
||||
metadata_surface_ref: metadataSurface,
|
||||
selected_chain_id: recipe.chainId,
|
||||
selected_chain_summary: recipe.chainSummary,
|
||||
catalog_chain_template_matches: catalogChainTemplateMatches,
|
||||
proposed_primitives: recipe.primitives,
|
||||
required_axes: recipe.axes,
|
||||
discovery_plan: plan,
|
||||
|
||||
@@ -47,6 +47,7 @@ describe("assistant MCP discovery planner", () => {
|
||||
expect(result.catalog_review.review_status).toBe("catalog_compatible");
|
||||
expect(result.discovery_plan.answer_may_use_raw_model_claims).toBe(false);
|
||||
expect(result.data_need_graph?.business_fact_family).toBe("value_flow");
|
||||
expect(result.catalog_chain_template_matches[0]).toBe("value_flow");
|
||||
expect(result.discovery_plan.execution_budget.max_probe_count).toBe(30);
|
||||
expect(result.reason_codes).toContain("planner_enabled_chunked_coverage_probe_budget");
|
||||
expect(result.reason_codes).toContain("planner_consumed_data_need_graph_v1");
|
||||
@@ -148,6 +149,7 @@ describe("assistant MCP discovery planner", () => {
|
||||
expect(result.reason_codes).toContain("planner_selected_catalog_primitives_from_fact_axis_search");
|
||||
expect(result.reason_codes).toContain("planner_instantiated_catalog_chain_template_document_evidence");
|
||||
expect(result.reason_codes).toContain("planner_catalog_chain_template_search_top_document_evidence");
|
||||
expect(result.catalog_chain_template_matches[0]).toBe("document_evidence");
|
||||
expect(result.reason_codes).not.toContain("planner_fell_back_to_recipe_primitives_after_empty_catalog_search");
|
||||
});
|
||||
|
||||
@@ -637,6 +639,7 @@ describe("assistant MCP discovery planner", () => {
|
||||
expect(result.catalog_review.review_status).toBe("catalog_compatible");
|
||||
expect(result.reason_codes).toContain("planner_selected_top_ranked_value_flow_from_data_need_graph");
|
||||
expect(result.reason_codes).toContain("planner_instantiated_catalog_chain_template_value_flow_ranking");
|
||||
expect(result.catalog_chain_template_matches[0]).toBe("value_flow_ranking");
|
||||
});
|
||||
|
||||
it("does not collapse incoming-vs-outgoing comparison into entity-resolution when no counterparty is preselected", () => {
|
||||
@@ -670,6 +673,7 @@ describe("assistant MCP discovery planner", () => {
|
||||
expect(result.required_axes).toEqual(["period", "amount", "coverage_target"]);
|
||||
expect(result.reason_codes).toContain("planner_selected_bidirectional_value_flow_comparison_from_data_need_graph");
|
||||
expect(result.reason_codes).toContain("planner_instantiated_catalog_chain_template_value_flow_comparison");
|
||||
expect(result.catalog_chain_template_matches[0]).toBe("value_flow_comparison");
|
||||
expect(result.selected_chain_id).not.toBe("entity_resolution");
|
||||
});
|
||||
|
||||
@@ -942,6 +946,7 @@ describe("assistant MCP discovery planner", () => {
|
||||
|
||||
expect(result.planner_status).toBe("needs_clarification");
|
||||
expect(result.discovery_plan.plan_status).toBe("needs_clarification");
|
||||
expect(result.catalog_chain_template_matches).toEqual([]);
|
||||
expect(result.reason_codes).toContain("planner_needs_more_user_or_scope_context");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user