ARCH: довести catalog drilldown от metadata surface до planner chain

This commit is contained in:
2026-04-23 10:48:01 +03:00
parent c2392f6420
commit 8fc90ae65f
12 changed files with 322 additions and 15 deletions
@@ -95,6 +95,18 @@ describe("assistant MCP catalog index", () => {
expect(primitives).toEqual(["query_movements", "resolve_entity_reference", "probe_coverage"]);
});
it("can search reviewed primitives directly from a confirmed catalog metadata surface without inventing an unsupported drilldown primitive", () => {
const primitives = searchAssistantMcpCatalogPrimitivesByMetadataSurface({
downstream_route_family: "catalog_drilldown",
selected_entity_set: "Catalog",
selected_surface_objects: ["Catalog.Counterparties"],
recommended_next_primitive: "drilldown_related_objects",
required_axes: ["metadata_scope"]
});
expect(primitives).toEqual(["inspect_1c_metadata"]);
});
it("marks a counterparty turnover discovery plan as catalog-compatible when required axes exist", () => {
const plan = buildAssistantMcpDiscoveryPlan({
semanticDataNeed: "counterparty turnover evidence",
@@ -249,6 +249,57 @@ describe("assistant MCP discovery pilot executor", () => {
});
});
it("executes catalog drilldown through a narrowed metadata probe seeded from the confirmed surface object", async () => {
const planner = planAssistantMcpDiscovery({
metadataSurface: {
selected_entity_set: "Catalog",
selected_surface_objects: ["Catalog.Counterparties"],
downstream_route_family: "catalog_drilldown",
route_family_selection_basis: "selected_entity_set",
recommended_next_primitive: "drilldown_related_objects",
ambiguity_detected: false,
ambiguity_entity_sets: []
},
turnMeaning: {
asked_domain_family: "metadata",
asked_action_family: "inspect_catalog",
unsupported_but_understood_family: "schema_surface"
}
});
const deps = buildMetadataDeps([
{
FullName: "Catalog.Counterparties",
MetaType: "Catalog",
attributes: [{ Name: "Description" }]
},
{
FullName: "Catalog.Contracts",
MetaType: "Catalog",
attributes: [{ Name: "Owner" }]
}
]);
const result = await executeAssistantMcpDiscoveryPilot(planner, deps);
expect(result.pilot_status).toBe("executed");
expect(result.pilot_scope).toBe("metadata_inspection_v1");
expect(result.executed_primitives).toEqual(["inspect_1c_metadata"]);
expect(result.derived_metadata_surface).toMatchObject({
metadata_scope: "Counterparties",
requested_meta_types: ["Catalog"],
available_entity_sets: ["Catalog"],
selected_entity_set: "Catalog",
downstream_route_family: "catalog_drilldown",
recommended_next_primitive: "drilldown_related_objects"
});
expect(result.reason_codes).toContain("pilot_catalog_drilldown_metadata_scope_seeded_from_surface_ref");
expect(deps.executeAddressMcpMetadata).toHaveBeenCalledTimes(1);
expect(deps.executeAddressMcpMetadata.mock.calls[0]?.[0]).toMatchObject({
meta_type: ["Catalog"],
name_mask: "Counterparties"
});
});
it("executes the full entity-resolution chain through the checked counterparty catalog slice", async () => {
const planner = planAssistantMcpDiscovery({
turnMeaning: {
@@ -323,6 +323,32 @@ describe("assistant MCP discovery planner", () => {
expect(result.reason_codes).toContain("planner_selected_catalog_primitives_from_metadata_surface_search");
});
it("can select catalog drilldown directly from a confirmed catalog metadata surface when the follow-up itself is thin", () => {
const result = planAssistantMcpDiscovery({
metadataSurface: {
selected_entity_set: "Catalog",
selected_surface_objects: ["Catalog.Counterparties"],
downstream_route_family: "catalog_drilldown",
route_family_selection_basis: "selected_entity_set",
recommended_next_primitive: "drilldown_related_objects",
ambiguity_detected: false,
ambiguity_entity_sets: []
},
turnMeaning: {
asked_domain_family: "metadata",
asked_action_family: "inspect_catalog",
unsupported_but_understood_family: "schema_surface"
}
});
expect(result.planner_status).toBe("ready_for_execution");
expect(result.selected_chain_id).toBe("catalog_drilldown");
expect(result.proposed_primitives).toEqual(["inspect_1c_metadata"]);
expect(result.required_axes).toEqual(["metadata_scope"]);
expect(result.reason_codes).toContain("planner_selected_catalog_drilldown_from_confirmed_metadata_surface_ref");
expect(result.reason_codes).toContain("planner_selected_catalog_primitives_from_metadata_surface_search");
});
it("does not force a lane from ambiguous metadata surface even when decomposition hints mention both documents and movements", () => {
const result = planAssistantMcpDiscovery({
dataNeedGraph: {
@@ -1148,6 +1148,38 @@ describe("assistant MCP discovery turn input adapter", () => {
expect(result.reason_codes).toContain("mcp_discovery_metadata_ambiguity_collapsed_to_movement_lane");
});
it("continues from a confirmed catalog metadata surface into inspect_catalog on a generic downstream follow-up", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "continue with data",
followupContext: {
previous_discovery_pilot_scope: "metadata_inspection_v1",
previous_discovery_metadata_route_family: "catalog_drilldown",
previous_discovery_metadata_selected_surface_objects: ["Catalog.Counterparties"],
previous_discovery_metadata_recommended_next_primitive: "drilldown_related_objects",
previous_discovery_metadata_ambiguity_detected: false
}
});
expect(result.adapter_status).toBe("ready");
expect(result.should_run_discovery).toBe(true);
expect(result.semantic_data_need).toBe("1C metadata evidence");
expect(result.turn_meaning_ref).toMatchObject({
asked_domain_family: "metadata",
asked_action_family: "inspect_catalog"
});
expect(result.metadata_surface_ref).toMatchObject({
selected_entity_set: null,
selected_surface_objects: ["Catalog.Counterparties"],
downstream_route_family: "catalog_drilldown",
route_family_selection_basis: null,
recommended_next_primitive: "drilldown_related_objects",
ambiguity_detected: false,
ambiguity_entity_sets: []
});
expect(result.reason_codes).toContain("mcp_discovery_metadata_grounded_catalog_continuation");
expect(result.reason_codes).toContain("mcp_discovery_metadata_surface_ref_from_followup_context");
});
it("requires an explicit lane choice on a generic downstream follow-up when metadata ambiguity stays mixed", () => {
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage: "давай дальше",