Planner Autonomy: поднять inventory routes в MCP catalog
This commit is contained in:
@@ -34,6 +34,10 @@ describe("assistant MCP catalog index", () => {
|
||||
"entity_resolution",
|
||||
"document_evidence",
|
||||
"movement_evidence",
|
||||
"inventory_stock_snapshot",
|
||||
"inventory_supplier_overlap",
|
||||
"inventory_purchase_provenance",
|
||||
"inventory_sale_trace",
|
||||
"value_flow",
|
||||
"value_flow_comparison",
|
||||
"value_flow_ranking",
|
||||
@@ -58,6 +62,9 @@ describe("assistant MCP catalog index", () => {
|
||||
const valueFlowComparisonTemplate = getAssistantMcpCatalogChainTemplate("value_flow_comparison");
|
||||
const valueFlowRankingTemplate = getAssistantMcpCatalogChainTemplate("value_flow_ranking");
|
||||
const lifecycleTemplate = getAssistantMcpCatalogChainTemplate("lifecycle");
|
||||
const inventorySnapshotTemplate = getAssistantMcpCatalogChainTemplate("inventory_stock_snapshot");
|
||||
const inventoryProvenanceTemplate = getAssistantMcpCatalogChainTemplate("inventory_purchase_provenance");
|
||||
const inventorySaleTraceTemplate = getAssistantMcpCatalogChainTemplate("inventory_sale_trace");
|
||||
|
||||
expect(documentTemplate.fallback_primitives).toEqual([
|
||||
"resolve_entity_reference",
|
||||
@@ -86,6 +93,19 @@ describe("assistant MCP catalog index", () => {
|
||||
expect(lifecycleTemplate.planning_tags).toEqual(
|
||||
expect.arrayContaining(["bounded_inference", "activity_window", "legal_fact_boundary"])
|
||||
);
|
||||
expect(inventorySnapshotTemplate.base_required_axes).toEqual(
|
||||
expect.arrayContaining(["as_of_date", "warehouse", "aggregate_axis", "quantity", "coverage_target"])
|
||||
);
|
||||
expect(inventoryProvenanceTemplate.fallback_primitives).toEqual([
|
||||
"resolve_entity_reference",
|
||||
"query_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
]);
|
||||
expect(inventorySaleTraceTemplate.supported_action_families).toEqual(
|
||||
expect.arrayContaining(["sale_trace", "purchase_to_sale_chain"])
|
||||
);
|
||||
});
|
||||
|
||||
it("can search reviewed primitives from data-need decomposition candidates", () => {
|
||||
@@ -131,6 +151,53 @@ describe("assistant MCP catalog index", () => {
|
||||
expect(primitives).toEqual(["resolve_entity_reference", "query_documents", "probe_coverage"]);
|
||||
});
|
||||
|
||||
it("can search reviewed primitives for inventory stock snapshot chains", () => {
|
||||
const primitives = searchAssistantMcpCatalogPrimitivesByFactAxis({
|
||||
business_fact_family: "inventory_stock_snapshot",
|
||||
action_family: "stock_snapshot",
|
||||
required_axes: ["as_of_date", "organization", "warehouse", "aggregate_axis", "quantity", "coverage_target", "evidence_basis"]
|
||||
});
|
||||
|
||||
expect(primitives).toEqual(
|
||||
expect.arrayContaining(["query_movements", "aggregate_by_axis", "probe_coverage", "explain_evidence_basis"])
|
||||
);
|
||||
expect(primitives).not.toContain("query_documents");
|
||||
});
|
||||
|
||||
it("can search reviewed primitives for inventory provenance and sale-trace chains", () => {
|
||||
const provenancePrimitives = searchAssistantMcpCatalogPrimitivesByFactAxis({
|
||||
business_fact_family: "inventory_purchase_provenance",
|
||||
action_family: "purchase_provenance",
|
||||
has_subject_candidates: true,
|
||||
required_axes: ["item", "document", "supplier", "coverage_target", "evidence_basis"]
|
||||
});
|
||||
const saleTracePrimitives = searchAssistantMcpCatalogPrimitivesByFactAxis({
|
||||
business_fact_family: "inventory_sale_trace",
|
||||
action_family: "sale_trace",
|
||||
has_subject_candidates: true,
|
||||
required_axes: ["item", "document", "buyer", "coverage_target", "evidence_basis"]
|
||||
});
|
||||
|
||||
expect(provenancePrimitives).toEqual(
|
||||
expect.arrayContaining([
|
||||
"resolve_entity_reference",
|
||||
"query_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
])
|
||||
);
|
||||
expect(saleTracePrimitives).toEqual(
|
||||
expect.arrayContaining([
|
||||
"resolve_entity_reference",
|
||||
"query_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it("treats all-time organization-scoped value-flow as catalog-compatible without inventing a fake period axis", () => {
|
||||
const primitives = searchAssistantMcpCatalogPrimitivesByFactAxis({
|
||||
business_fact_family: "value_flow",
|
||||
@@ -215,6 +282,8 @@ describe("assistant MCP catalog index", () => {
|
||||
expect(review.reason_codes).toContain("catalog_required_axes_missing_for_primitive");
|
||||
expect(review.missing_axes_by_primitive.query_documents).toEqual([
|
||||
["document"],
|
||||
["item"],
|
||||
["supplier"],
|
||||
["counterparty"],
|
||||
["contract"],
|
||||
["period", "organization"],
|
||||
|
||||
@@ -71,6 +71,87 @@ describe("assistant MCP discovery data need graph", () => {
|
||||
expect(result.forbidden_overclaim_flags).toContain("no_unresolved_entity_claim");
|
||||
});
|
||||
|
||||
it("builds a subjectless inventory stock snapshot graph with an as-of date gate", () => {
|
||||
const result = buildAssistantMcpDiscoveryDataNeedGraph({
|
||||
semanticDataNeed: "inventory stock snapshot evidence",
|
||||
rawUtterance: "show stock snapshot for warehouse main as of 2021-09-30",
|
||||
turnMeaning: {
|
||||
asked_domain_family: "inventory_stock",
|
||||
asked_action_family: "stock_snapshot",
|
||||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||||
explicit_date_scope: "2021-09-30"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.business_fact_family).toBe("inventory_stock_snapshot");
|
||||
expect(result.subject_candidates).toEqual([]);
|
||||
expect(result.clarification_gaps).toEqual([]);
|
||||
expect(result.time_scope_need).toBe("explicit_period");
|
||||
expect(result.decomposition_candidates).toEqual([
|
||||
"fetch_scoped_movements",
|
||||
"aggregate_checked_amounts",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
]);
|
||||
expect(result.forbidden_overclaim_flags).toContain("no_unchecked_stock_snapshot");
|
||||
});
|
||||
|
||||
it("keeps inventory stock snapshot blocked on an explicit as-of date when no date exists", () => {
|
||||
const result = buildAssistantMcpDiscoveryDataNeedGraph({
|
||||
semanticDataNeed: "inventory stock snapshot evidence",
|
||||
rawUtterance: "show current stock snapshot",
|
||||
turnMeaning: {
|
||||
asked_domain_family: "inventory_stock",
|
||||
asked_action_family: "stock_snapshot",
|
||||
explicit_organization_scope: "ООО Альтернатива Плюс"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.business_fact_family).toBe("inventory_stock_snapshot");
|
||||
expect(result.clarification_gaps).toEqual(["as_of_date"]);
|
||||
expect(result.proof_expectation).toBe("clarification_required");
|
||||
});
|
||||
|
||||
it("builds inventory provenance and sale-trace graphs as checked document drilldowns", () => {
|
||||
const provenance = buildAssistantMcpDiscoveryDataNeedGraph({
|
||||
semanticDataNeed: "inventory purchase provenance evidence",
|
||||
rawUtterance: "who supplied the selected stock item",
|
||||
turnMeaning: {
|
||||
asked_domain_family: "inventory_stock",
|
||||
asked_action_family: "purchase_provenance",
|
||||
explicit_entity_candidates: ["Столешница 600"]
|
||||
}
|
||||
});
|
||||
const saleTrace = buildAssistantMcpDiscoveryDataNeedGraph({
|
||||
semanticDataNeed: "inventory sale trace evidence",
|
||||
rawUtterance: "who bought the selected stock item",
|
||||
turnMeaning: {
|
||||
asked_domain_family: "inventory_stock",
|
||||
asked_action_family: "sale_trace",
|
||||
explicit_entity_candidates: ["Столешница 600"]
|
||||
}
|
||||
});
|
||||
|
||||
expect(provenance.business_fact_family).toBe("inventory_purchase_provenance");
|
||||
expect(provenance.decomposition_candidates).toEqual([
|
||||
"resolve_entity_reference",
|
||||
"fetch_scoped_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
]);
|
||||
expect(provenance.forbidden_overclaim_flags).toContain("no_unproven_supplier_attribution");
|
||||
expect(saleTrace.business_fact_family).toBe("inventory_sale_trace");
|
||||
expect(saleTrace.decomposition_candidates).toEqual([
|
||||
"resolve_entity_reference",
|
||||
"fetch_scoped_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
]);
|
||||
expect(saleTrace.forbidden_overclaim_flags).toContain("no_unproven_buyer_or_sale_trace");
|
||||
});
|
||||
|
||||
it("treats top-value wording as a ranking ask rather than a missing-subject fact ask", () => {
|
||||
const result = buildAssistantMcpDiscoveryDataNeedGraph({
|
||||
semanticDataNeed: "counterparty value-flow evidence",
|
||||
|
||||
@@ -683,6 +683,141 @@ describe("assistant MCP discovery planner", () => {
|
||||
expect(result.reason_codes).toContain("planner_lifecycle_legal_fact_boundary_required");
|
||||
});
|
||||
|
||||
it("instantiates inventory stock snapshot from the catalog fabric", () => {
|
||||
const result = planAssistantMcpDiscovery({
|
||||
dataNeedGraph: {
|
||||
schema_version: "assistant_data_need_graph_v1",
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph",
|
||||
subject_candidates: [],
|
||||
business_fact_family: "inventory_stock_snapshot",
|
||||
action_family: "stock_snapshot",
|
||||
aggregation_need: null,
|
||||
time_scope_need: "explicit_period",
|
||||
comparison_need: null,
|
||||
ranking_need: null,
|
||||
proof_expectation: "coverage_checked_fact",
|
||||
clarification_gaps: [],
|
||||
decomposition_candidates: [
|
||||
"fetch_scoped_movements",
|
||||
"aggregate_checked_amounts",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
],
|
||||
forbidden_overclaim_flags: ["no_raw_model_claims", "no_unchecked_stock_snapshot"],
|
||||
reason_codes: ["data_need_graph_built", "data_need_graph_family_inventory_stock_snapshot"]
|
||||
},
|
||||
turnMeaning: {
|
||||
asked_domain_family: "inventory_stock",
|
||||
asked_action_family: "stock_snapshot",
|
||||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||||
explicit_date_scope: "2021-09-30"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.planner_status).toBe("ready_for_execution");
|
||||
expect(result.selected_chain_id).toBe("inventory_stock_snapshot");
|
||||
expect(result.proposed_primitives).toEqual([
|
||||
"query_movements",
|
||||
"aggregate_by_axis",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
]);
|
||||
expect(result.required_axes).toEqual([
|
||||
"organization",
|
||||
"period",
|
||||
"as_of_date",
|
||||
"warehouse",
|
||||
"aggregate_axis",
|
||||
"quantity",
|
||||
"coverage_target",
|
||||
"evidence_basis"
|
||||
]);
|
||||
expect(result.reason_codes).toContain("planner_selected_inventory_stock_snapshot_from_data_need_graph");
|
||||
expect(result.reason_codes).toContain("planner_instantiated_catalog_chain_template_inventory_stock_snapshot");
|
||||
});
|
||||
|
||||
it("instantiates inventory provenance and sale-trace chains from reviewed templates", () => {
|
||||
const provenance = planAssistantMcpDiscovery({
|
||||
dataNeedGraph: {
|
||||
schema_version: "assistant_data_need_graph_v1",
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph",
|
||||
subject_candidates: ["Столешница 600"],
|
||||
business_fact_family: "inventory_purchase_provenance",
|
||||
action_family: "purchase_provenance",
|
||||
aggregation_need: null,
|
||||
time_scope_need: null,
|
||||
comparison_need: null,
|
||||
ranking_need: null,
|
||||
proof_expectation: "coverage_checked_fact",
|
||||
clarification_gaps: [],
|
||||
decomposition_candidates: [
|
||||
"resolve_entity_reference",
|
||||
"fetch_scoped_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
],
|
||||
forbidden_overclaim_flags: ["no_raw_model_claims", "no_unproven_supplier_attribution"],
|
||||
reason_codes: ["data_need_graph_built", "data_need_graph_family_inventory_purchase_provenance"]
|
||||
},
|
||||
turnMeaning: {
|
||||
asked_domain_family: "inventory_stock",
|
||||
asked_action_family: "purchase_provenance",
|
||||
explicit_entity_candidates: ["Столешница 600"]
|
||||
}
|
||||
});
|
||||
const saleTrace = planAssistantMcpDiscovery({
|
||||
dataNeedGraph: {
|
||||
schema_version: "assistant_data_need_graph_v1",
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph",
|
||||
subject_candidates: ["Столешница 600"],
|
||||
business_fact_family: "inventory_sale_trace",
|
||||
action_family: "sale_trace",
|
||||
aggregation_need: null,
|
||||
time_scope_need: null,
|
||||
comparison_need: null,
|
||||
ranking_need: null,
|
||||
proof_expectation: "coverage_checked_fact",
|
||||
clarification_gaps: [],
|
||||
decomposition_candidates: [
|
||||
"resolve_entity_reference",
|
||||
"fetch_scoped_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
],
|
||||
forbidden_overclaim_flags: ["no_raw_model_claims", "no_unproven_buyer_or_sale_trace"],
|
||||
reason_codes: ["data_need_graph_built", "data_need_graph_family_inventory_sale_trace"]
|
||||
},
|
||||
turnMeaning: {
|
||||
asked_domain_family: "inventory_stock",
|
||||
asked_action_family: "sale_trace",
|
||||
explicit_entity_candidates: ["Столешница 600"]
|
||||
}
|
||||
});
|
||||
|
||||
expect(provenance.planner_status).toBe("ready_for_execution");
|
||||
expect(provenance.selected_chain_id).toBe("inventory_purchase_provenance");
|
||||
expect(provenance.proposed_primitives).toEqual([
|
||||
"resolve_entity_reference",
|
||||
"query_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
]);
|
||||
expect(provenance.reason_codes).toContain("planner_instantiated_catalog_chain_template_inventory_purchase_provenance");
|
||||
expect(saleTrace.planner_status).toBe("ready_for_execution");
|
||||
expect(saleTrace.selected_chain_id).toBe("inventory_sale_trace");
|
||||
expect(saleTrace.proposed_primitives).toEqual([
|
||||
"resolve_entity_reference",
|
||||
"query_documents",
|
||||
"drilldown_related_objects",
|
||||
"probe_coverage",
|
||||
"explain_evidence_basis"
|
||||
]);
|
||||
expect(saleTrace.reason_codes).toContain("planner_instantiated_catalog_chain_template_inventory_sale_trace");
|
||||
});
|
||||
|
||||
it("uses metadata-only planning when the user asks about available schema surface", () => {
|
||||
const result = planAssistantMcpDiscovery({
|
||||
turnMeaning: {
|
||||
|
||||
Reference in New Issue
Block a user