Planner Autonomy: связать inventory templates с exact runtime
This commit is contained in:
@@ -293,7 +293,11 @@ describe("assistant MCP discovery runtime bridge", () => {
|
||||
expect(result.reason_codes).toContain("runtime_bridge_status_checked_sources_only");
|
||||
});
|
||||
|
||||
it("keeps inventory catalog templates unsupported until exact runtime evidence is bridged", async () => {
|
||||
it("bridges inventory stock catalog templates through exact runtime evidence", async () => {
|
||||
const deps = buildDeps([
|
||||
{ Period: "2021-09-30T00:00:00", Item: "Widget A", Quantity: 10, Warehouse: "Main" },
|
||||
{ Period: "2021-09-30T00:00:00", Item: "Widget B", Quantity: 4, Warehouse: "Reserve" }
|
||||
]);
|
||||
const result = await runAssistantMcpDiscoveryRuntimeBridge({
|
||||
dataNeedGraph: {
|
||||
schema_version: "assistant_data_need_graph_v1",
|
||||
@@ -322,7 +326,7 @@ describe("assistant MCP discovery runtime bridge", () => {
|
||||
explicit_organization_scope: "OOO Alternative Plus",
|
||||
explicit_date_scope: "2021-09-30"
|
||||
},
|
||||
deps: buildDeps([])
|
||||
deps
|
||||
});
|
||||
const userFacing = [
|
||||
result.answer_draft.headline,
|
||||
@@ -333,12 +337,14 @@ describe("assistant MCP discovery runtime bridge", () => {
|
||||
result.answer_draft.next_step_line ?? ""
|
||||
].join("\n");
|
||||
|
||||
expect(result.bridge_status).toBe("unsupported");
|
||||
expect(result.answer_draft.answer_mode).toBe("checked_sources_only");
|
||||
expect(result.bridge_status).toBe("answer_draft_ready");
|
||||
expect(result.answer_draft.answer_mode).toBe("confirmed_with_bounded_inference");
|
||||
expect(result.pilot.pilot_scope).toBe("inventory_route_template_v1");
|
||||
expect(result.pilot.mcp_execution_performed).toBe(false);
|
||||
expect(result.pilot.mcp_execution_performed).toBe(true);
|
||||
expect(result.pilot.executed_primitives).toEqual(["query_movements"]);
|
||||
expect(deps.executeAddressMcpQuery).toHaveBeenCalledWith(expect.objectContaining({ account_scope: ["41.01"] }));
|
||||
expect(result.loop_state).toMatchObject({
|
||||
loop_status: "blocked",
|
||||
loop_status: "ready_for_next_hop",
|
||||
selected_chain_id: "inventory_stock_snapshot",
|
||||
pilot_scope: "inventory_route_template_v1",
|
||||
asked_domain_family: "inventory_stock",
|
||||
@@ -346,21 +352,126 @@ describe("assistant MCP discovery runtime bridge", () => {
|
||||
explicit_organization_scope: "OOO Alternative Plus",
|
||||
explicit_date_scope: "2021-09-30"
|
||||
});
|
||||
expect(result.business_fact_answer_allowed).toBe(false);
|
||||
expect(result.reason_codes).toContain("pilot_scope_unsupported_for_live_execution");
|
||||
expect(result.business_fact_answer_allowed).toBe(true);
|
||||
expect(result.reason_codes).toContain("pilot_inventory_exact_recipe_selected");
|
||||
expect(result.reason_codes).toContain("pilot_inventory_exact_mcp_executed");
|
||||
expect(result.reason_codes).not.toContain("pilot_scope_unsupported_for_live_execution");
|
||||
expect(result.answer_draft.must_not_claim).toEqual(
|
||||
expect.arrayContaining([
|
||||
"Do not present inventory route-template planning as executed stock, supplier, purchase, or sale evidence.",
|
||||
"Do not expose inventory_route_template_v1 or MCP primitive names in the user answer."
|
||||
"Do not expose inventory_route_template_v1 or MCP primitive names in the user answer.",
|
||||
"Do not claim full inventory coverage outside the checked rows, date, organization, item, or supplier scope."
|
||||
])
|
||||
);
|
||||
expect(userFacing).toContain("Инвентарный route-template");
|
||||
expect(result.answer_draft.must_not_claim).not.toContain(
|
||||
"Do not present inventory route-template planning as executed stock, supplier, purchase, or sale evidence."
|
||||
);
|
||||
expect(userFacing).toContain("exact inventory runtime");
|
||||
expect(userFacing).toContain("Widget A");
|
||||
expect(userFacing).not.toContain("inventory_route_template_v1");
|
||||
expect(userFacing).not.toContain("query_movements");
|
||||
expect(userFacing).not.toContain("primitive");
|
||||
expect(userFacing).not.toContain("MCP discovery pilot");
|
||||
});
|
||||
|
||||
it("bridges selected-item inventory provenance templates through exact document evidence", async () => {
|
||||
const deps = buildDeps([
|
||||
{
|
||||
Period: "2021-08-10T00:00:00",
|
||||
Item: "Widget A",
|
||||
Counterparty: "Supplier One",
|
||||
Registrator: "Purchase 0001"
|
||||
}
|
||||
]);
|
||||
const result = await runAssistantMcpDiscoveryRuntimeBridge({
|
||||
dataNeedGraph: {
|
||||
schema_version: "assistant_data_need_graph_v1",
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph",
|
||||
subject_candidates: ["Widget A"],
|
||||
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: ["Widget A"]
|
||||
},
|
||||
deps
|
||||
});
|
||||
const userFacing = [
|
||||
result.answer_draft.headline,
|
||||
...result.answer_draft.confirmed_lines,
|
||||
...result.answer_draft.inference_lines,
|
||||
...result.answer_draft.unknown_lines,
|
||||
...result.answer_draft.limitation_lines,
|
||||
result.answer_draft.next_step_line ?? ""
|
||||
].join("\n");
|
||||
|
||||
expect(result.bridge_status).toBe("answer_draft_ready");
|
||||
expect(result.business_fact_answer_allowed).toBe(true);
|
||||
expect(result.planner.selected_chain_id).toBe("inventory_purchase_provenance");
|
||||
expect(result.pilot.executed_primitives).toEqual(["query_documents"]);
|
||||
expect(deps.executeAddressMcpQuery).toHaveBeenCalledWith(expect.objectContaining({ account_scope: ["41.01"] }));
|
||||
expect(userFacing).toContain("Widget A");
|
||||
expect(userFacing).toContain("Supplier One");
|
||||
expect(userFacing).not.toContain("inventory_route_template_v1");
|
||||
expect(userFacing).not.toContain("query_documents");
|
||||
expect(userFacing).not.toContain("primitive");
|
||||
});
|
||||
|
||||
it("keeps selected-item inventory templates in clarification when the item anchor is missing", async () => {
|
||||
const result = await runAssistantMcpDiscoveryRuntimeBridge({
|
||||
dataNeedGraph: {
|
||||
schema_version: "assistant_data_need_graph_v1",
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph",
|
||||
subject_candidates: [],
|
||||
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: "clarification_required",
|
||||
clarification_gaps: ["item"],
|
||||
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"
|
||||
},
|
||||
deps: buildDeps([])
|
||||
});
|
||||
|
||||
expect(result.bridge_status).toBe("needs_clarification");
|
||||
expect(result.requires_user_clarification).toBe(true);
|
||||
expect(result.pilot.pilot_scope).toBe("inventory_route_template_v1");
|
||||
expect(result.pilot.mcp_execution_performed).toBe(false);
|
||||
expect(result.reason_codes).toContain("runtime_bridge_loop_state_awaiting_clarification");
|
||||
expect(result.loop_state.pending_axes).toContain("item");
|
||||
});
|
||||
|
||||
it("keeps document evidence executable when the planner expands primitives from fact-axis search", async () => {
|
||||
const result = await runAssistantMcpDiscoveryRuntimeBridge({
|
||||
dataNeedGraph: {
|
||||
|
||||
Reference in New Issue
Block a user