NODEDC_1C/llm_normalizer/backend/tests/assistantMcpDiscoveryPlanne...

99 lines
4.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { planAssistantMcpDiscovery } from "../src/services/assistantMcpDiscoveryPlanner";
describe("assistant MCP discovery planner", () => {
it("builds a catalog-compatible value-flow discovery plan from current turn meaning", () => {
const result = planAssistantMcpDiscovery({
turnMeaning: {
asked_domain_family: "counterparty_value",
asked_action_family: "turnover",
explicit_entity_candidates: ["SVK"],
explicit_date_scope: "2020"
}
});
expect(result.planner_status).toBe("ready_for_execution");
expect(result.semantic_data_need).toBe("counterparty value-flow evidence");
expect(result.proposed_primitives).toEqual([
"resolve_entity_reference",
"query_movements",
"aggregate_by_axis",
"probe_coverage"
]);
expect(result.required_axes).toEqual(["counterparty", "period", "aggregate_axis", "amount", "coverage_target"]);
expect(result.catalog_review.review_status).toBe("catalog_compatible");
expect(result.discovery_plan.answer_may_use_raw_model_claims).toBe(false);
});
it("keeps a value-flow plan in clarification state when period axis is missing", () => {
const result = planAssistantMcpDiscovery({
turnMeaning: {
asked_domain_family: "counterparty_value",
asked_action_family: "turnover",
explicit_entity_candidates: ["SVK"]
}
});
expect(result.planner_status).toBe("needs_clarification");
expect(result.catalog_review.review_status).toBe("needs_more_axes");
expect(result.catalog_review.missing_axes_by_primitive.query_movements).toContainEqual(["period", "counterparty"]);
expect(result.reason_codes).toContain("planner_needs_more_user_or_scope_context");
});
it("builds a document discovery plan without falling back to movement primitives", () => {
const result = planAssistantMcpDiscovery({
turnMeaning: {
asked_domain_family: "counterparty_documents",
asked_action_family: "list_documents",
explicit_entity_candidates: ["SVK"]
}
});
expect(result.planner_status).toBe("ready_for_execution");
expect(result.proposed_primitives).toEqual(["resolve_entity_reference", "query_documents", "probe_coverage"]);
expect(result.proposed_primitives).not.toContain("query_movements");
expect(result.required_axes).toEqual(["counterparty", "coverage_target"]);
});
it("builds an inference-safe lifecycle plan with evidence explanation", () => {
const result = planAssistantMcpDiscovery({
turnMeaning: {
asked_domain_family: "counterparty_lifecycle",
asked_action_family: "activity_duration",
explicit_entity_candidates: ["SVK"]
}
});
expect(result.planner_status).toBe("ready_for_execution");
expect(result.proposed_primitives).toEqual([
"resolve_entity_reference",
"query_documents",
"probe_coverage",
"explain_evidence_basis"
]);
expect(result.required_axes).toEqual(["counterparty", "document_date", "coverage_target", "evidence_basis"]);
});
it("uses metadata-only planning when the user asks about available schema surface", () => {
const result = planAssistantMcpDiscovery({
turnMeaning: {
asked_domain_family: "metadata",
asked_action_family: "inspect_catalog"
}
});
expect(result.planner_status).toBe("ready_for_execution");
expect(result.proposed_primitives).toEqual(["inspect_1c_metadata"]);
expect(result.required_axes).toEqual(["metadata_scope"]);
expect(result.catalog_review.evidence_floors.inspect_1c_metadata).toBe("source_summary");
});
it("does not mark an unclassified turn as executable without turn meaning context", () => {
const result = planAssistantMcpDiscovery({});
expect(result.planner_status).toBe("needs_clarification");
expect(result.discovery_plan.plan_status).toBe("needs_clarification");
expect(result.reason_codes).toContain("planner_needs_more_user_or_scope_context");
});
});