Planner Autonomy: закрепить alignment guard для catalog chains

This commit is contained in:
2026-05-01 14:47:19 +03:00
parent 417b51096e
commit 67f5e908c9
3 changed files with 151 additions and 2 deletions
@@ -63,6 +63,147 @@ describe("assistant MCP discovery planner", () => {
expect(result.reason_codes).toContain("planner_catalog_chain_template_search_top_value_flow");
});
it("keeps representative graph-selected chains aligned with top catalog template matches", () => {
const graph = (
businessFactFamily: string,
actionFamily: string,
extra: {
subject_candidates?: string[];
comparison_need?: string | null;
ranking_need?: string | null;
} = {}
) => ({
schema_version: "assistant_data_need_graph_v1" as const,
policy_owner: "assistantMcpDiscoveryDataNeedGraph" as const,
subject_candidates: extra.subject_candidates ?? ["SVK"],
business_fact_family: businessFactFamily,
action_family: actionFamily,
aggregation_need: null,
time_scope_need: "explicit_period",
comparison_need: extra.comparison_need ?? null,
ranking_need: extra.ranking_need ?? null,
proof_expectation: "coverage_checked_fact",
clarification_gaps: [],
decomposition_candidates: [],
forbidden_overclaim_flags: ["no_raw_model_claims", "no_unchecked_fact_totals"],
reason_codes: ["data_need_graph_built"]
});
const cases = [
{
name: "value_flow",
expected: "value_flow",
input: {
dataNeedGraph: graph("value_flow", "turnover"),
turnMeaning: {
asked_action_family: "turnover",
explicit_entity_candidates: ["SVK"],
explicit_date_scope: "2020"
}
}
},
{
name: "value_flow_comparison",
expected: "value_flow_comparison",
input: {
dataNeedGraph: graph("value_flow", "net_value_flow", { comparison_need: "incoming_vs_outgoing" }),
turnMeaning: {
asked_action_family: "net_value_flow",
explicit_entity_candidates: ["SVK"],
explicit_date_scope: "2020"
}
}
},
{
name: "value_flow_ranking",
expected: "value_flow_ranking",
input: {
dataNeedGraph: graph("value_flow", "turnover", { subject_candidates: [], ranking_need: "top_desc" }),
turnMeaning: {
asked_action_family: "turnover",
explicit_date_scope: "2020",
explicit_organization_scope: "Org"
}
}
},
{
name: "document_evidence",
expected: "document_evidence",
input: {
dataNeedGraph: graph("document_evidence", "list_documents"),
turnMeaning: {
asked_action_family: "list_documents",
explicit_entity_candidates: ["SVK"],
explicit_date_scope: "2020"
}
}
},
{
name: "movement_evidence",
expected: "movement_evidence",
input: {
dataNeedGraph: graph("movement_evidence", "list_movements"),
turnMeaning: {
asked_action_family: "list_movements",
explicit_entity_candidates: ["SVK"],
explicit_date_scope: "2020"
}
}
},
{
name: "schema_surface",
expected: "metadata_inspection",
input: {
dataNeedGraph: graph("schema_surface", "inspect_catalog", { subject_candidates: [] }),
turnMeaning: {
asked_action_family: "inspect_catalog"
}
}
},
{
name: "entity_resolution",
expected: "entity_resolution",
input: {
dataNeedGraph: graph("entity_grounding", "search_business_entity"),
turnMeaning: {
asked_action_family: "search_business_entity",
explicit_entity_candidates: ["SVK"]
}
}
},
{
name: "lifecycle",
expected: "lifecycle",
input: {
dataNeedGraph: graph("activity_lifecycle", "activity_duration"),
turnMeaning: {
asked_action_family: "activity_duration",
explicit_entity_candidates: ["SVK"]
}
}
},
{
name: "inventory_stock_snapshot",
expected: "inventory_stock_snapshot",
input: {
dataNeedGraph: graph("inventory_stock_snapshot", "stock_snapshot", { subject_candidates: [] }),
turnMeaning: {
asked_action_family: "stock_snapshot",
explicit_date_scope: "2020",
explicit_organization_scope: "Org"
}
}
}
] as const;
for (const item of cases) {
const result = planAssistantMcpDiscovery(item.input);
expect(result.selected_chain_id, item.name).toBe(item.expected);
expect(result.catalog_chain_template_alignment.top_chain_template_match, item.name).toBe(item.expected);
expect(result.catalog_chain_template_alignment.selected_chain_template_rank, item.name).toBe(1);
expect(result.catalog_chain_template_alignment.selected_chain_matches_top, item.name).toBe(true);
}
});
it("keeps a value-flow plan in clarification state when period axis is missing", () => {
const result = planAssistantMcpDiscovery({
turnMeaning: {