Planner Autonomy: поднять inventory routes в MCP catalog

This commit is contained in:
dctouch 2026-05-01 13:08:21 +03:00
parent 6bfbd5cb20
commit 9243642400
15 changed files with 1162 additions and 61 deletions

View File

@ -78,6 +78,17 @@ Two arbitration seams were also hardened because they are part of the same plann
These changes keep the route fabric broader without letting the planner pretend that inferred evidence is a formally proven legal fact.
The following consolidation step promoted the accepted inventory-stock breadth behavior into reviewed catalog route fabric:
- `inventory_stock_snapshot`
- `inventory_supplier_overlap`
- `inventory_purchase_provenance`
- `inventory_sale_trace`
These templates are now first-class catalog chain descriptors and can be selected by the data-need graph/planner. They reuse reviewed generic primitives (`query_movements`, `query_documents`, `aggregate_by_axis`, `drilldown_related_objects`, `probe_coverage`, `explain_evidence_basis`) and add inventory-specific axes such as `as_of_date`, `warehouse`, `supplier`, `buyer`, `quantity`, and `evidence_basis`.
The live MCP pilot intentionally marks these new inventory templates as `inventory_route_template_v1` / unsupported for live generic pilot execution until the exact inventory runtime paths are explicitly bridged into the bounded MCP executor. This keeps the architecture honest: route fabric exists, but runtime execution is still gated by the existing exact inventory capabilities and future bridging work.
## Why This Matters
This reduces the pressure to add one hard route per user wording.
@ -121,13 +132,20 @@ Latest validation after the lifecycle and arbitration hardening:
- live broad-eval to net-flow follow-up: `address_truth_harness_phase21_net_followup_after_broad_eval_planner_lifecycle_rerun2`, accepted `3/3`
- live broad-evaluation bridge: `address_truth_harness_phase22_broad_business_evaluation_bridge_planner_lifecycle_rerun2`, accepted `3/3`
Latest validation after the inventory catalog-template lift:
- targeted catalog/data-need/planner/turn-input tests: passed, `139 passed`, `6 skipped`
- full MCP-discovery suite: passed, `276 passed`, `9 skipped`
- `npm.cmd run build`: passed
- graphify rebuild: `5912 nodes`, `12833 edges`, `138 communities`
## Next Step
The next safe step is to continue from catalog-instantiated known chain templates, first scoring rules, and lifecycle bounded inference into broader reviewed evidence templates.
The next safe step is to continue from catalog-instantiated inventory templates into runtime bridging and broader reviewed scoring.
Recommended order:
1. promote repeated inventory-stock evidence behaviors into reviewed catalog templates;
1. bridge inventory catalog templates into the bounded MCP executor only where exact inventory runtime evidence can be reused safely;
2. broaden catalog scoring beyond explicit document/movement lane choice into unfamiliar 1C asks;
3. grow primitive descriptors only where live replay shows a real evidence gap;
4. keep phase19, phase21, phase22, value-flow, metadata ambiguity, and inventory-stock canaries as regression gates.

View File

@ -76,6 +76,7 @@ It now documents a turnaround that is already operational in code, already mater
- lifecycle now behaves as a bounded activity-window inference chain with an explicit legal-fact boundary instead of an unqualified age answer;
- current-turn value-flow aggregate questions can override narrower supported exact routes when the user asks for totals/net/payment amounts;
- broad business evaluation remains in the deterministic living-chat bridge instead of being displaced by generic metadata discovery;
- inventory stock snapshot, supplier overlap, purchase provenance, and sale trace are now reviewed catalog chain templates, while live generic MCP pilot execution remains explicitly gated until the exact inventory runtime evidence is bridged safely;
- live map sync: [20 - planner_autonomy_consolidation_2026-05-01.md](./20%20-%20planner_autonomy_consolidation_2026-05-01.md)
Current honest status:
@ -84,10 +85,10 @@ Current honest status:
- exit-from-danger-zone readiness: `~97%`
- pre-multidomain readiness: `~90%`
- bounded-autonomy foundation readiness: `~89%`
- open-world bounded-autonomy readiness: `~84%`
- open-world bounded-autonomy readiness: `~85%`
- Post-F semantic integrity module progress: `~99%` operationally closed, with remaining risk now treated as next-slice discovery rather than an open blocker inside the closed slice
- active inventory-stock breadth slice progress: `100%` for the declared scenario pack, not for arbitrary inventory questions
- Planner Autonomy Consolidation progress: `~62%` for the declared module, with catalog-fabric, value-flow arbitration, lifecycle bounded inference, and broad-evaluation bridge validated, but broader unfamiliar 1C asks still pending
- Planner Autonomy Consolidation progress: `~68%` for the declared module, with catalog-fabric, value-flow arbitration, lifecycle bounded inference, broad-evaluation bridge, and inventory catalog templates validated, but live inventory-template bridging and broader unfamiliar 1C asks still pending
- graph snapshot after latest rebuild: `5912 nodes`, `12833 edges`, `138 communities`
- current breakpoint:
- the validated hot paths are no longer structurally broken;
@ -128,6 +129,7 @@ Latest live proof now includes:
- lifecycle/value-flow Planner Autonomy response gate accepted: `address_truth_harness_phase19_mcp_discovery_response_gate_planner_lifecycle_rerun4` accepted `8/8`, proving bounded lifecycle inference, current-turn value-flow aggregate arbitration, and sanitized evidence wording
- broad-evaluation bridge continuity accepted: `address_truth_harness_phase21_net_followup_after_broad_eval_planner_lifecycle_rerun2` accepted `3/3` and `address_truth_harness_phase22_broad_business_evaluation_bridge_planner_lifecycle_rerun2` accepted `3/3`
- latest local Planner Autonomy slice accepted: full MCP-discovery suite passed `268/268` with `9` skipped; broad MCP/living-chat/route/meaning slice passed `305/305` with `9` skipped; build passed
- inventory template lift accepted locally: catalog/data-need/planner/turn-input slice passed `139/139` with `6` skipped; full MCP-discovery slice passed `276/276` with `9` skipped; build passed; graphify stayed at `5912 nodes`, `12833 edges`, `138 communities`
Current architectural reading:

View File

@ -44,8 +44,28 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "resolve_entity_reference",
purpose: "Resolve a user-visible entity name to a concrete 1C reference candidate.",
decomposition_hints: ["resolve_entity_reference"],
supported_fact_families: ["entity_grounding", "value_flow", "document_evidence", "movement_evidence", "activity_lifecycle"],
supported_action_families: ["search_business_entity", "turnover", "payout", "net_value_flow", "list_documents", "list_movements", "activity_duration"],
supported_fact_families: [
"entity_grounding",
"value_flow",
"document_evidence",
"movement_evidence",
"activity_lifecycle",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: [
"search_business_entity",
"turnover",
"payout",
"net_value_flow",
"list_documents",
"list_movements",
"activity_duration",
"purchase_provenance",
"sale_trace",
"supplier_overlap"
],
planning_tags: ["subject_resolution"],
required_axes_any_of: [["business_entity"], ["counterparty"], ["organization"], ["contract"], ["item"]],
optional_axes: ["period", "inn", "document"],
@ -63,18 +83,21 @@ const PRIMITIVE_CONTRACTS = [
"collect_outgoing_movements",
"fetch_scoped_movements"
],
supported_fact_families: ["value_flow", "movement_evidence"],
supported_action_families: ["turnover", "payout", "net_value_flow", "list_movements"],
supported_fact_families: ["value_flow", "movement_evidence", "inventory_stock_snapshot", "inventory_supplier_overlap"],
supported_action_families: ["turnover", "payout", "net_value_flow", "list_movements", "stock_snapshot", "supplier_overlap"],
planning_tags: ["movement", "comparison", "ranking", "aggregation", "monthly_aggregation"],
required_axes_any_of: [
["period", "account"],
["period", "counterparty"],
["period", "organization"],
["as_of_date", "organization"],
["as_of_date", "warehouse"],
["as_of_date", "item"],
["all_time_scope", "counterparty"],
["all_time_scope", "organization"]
],
optional_axes: ["contract", "document", "amount", "item", "warehouse"],
output_fact_kinds: ["movement_rows", "turnover", "balance_delta"],
optional_axes: ["contract", "document", "amount", "item", "warehouse", "quantity", "supplier"],
output_fact_kinds: ["movement_rows", "turnover", "balance_delta", "stock_rows", "stock_quantity"],
evidence_floor: "rows_matched",
safe_for_model_planning: true,
runtime_must_execute: true
@ -83,19 +106,27 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "query_documents",
purpose: "Fetch documents related to a scoped entity, period, contract, or movement explanation.",
decomposition_hints: ["fetch_scoped_documents", "fetch_supporting_documents"],
supported_fact_families: ["document_evidence", "activity_lifecycle"],
supported_action_families: ["list_documents", "activity_duration"],
supported_fact_families: [
"document_evidence",
"activity_lifecycle",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: ["list_documents", "activity_duration", "purchase_provenance", "sale_trace", "supplier_overlap"],
planning_tags: ["document"],
required_axes_any_of: [
["document"],
["item"],
["supplier"],
["counterparty"],
["contract"],
["period", "organization"],
["all_time_scope", "counterparty"],
["all_time_scope", "organization"]
],
optional_axes: ["account", "amount", "item", "warehouse"],
output_fact_kinds: ["document_rows", "document_dates", "document_amounts"],
optional_axes: ["account", "amount", "item", "warehouse", "as_of_date", "supplier", "buyer"],
output_fact_kinds: ["document_rows", "document_dates", "document_amounts", "purchase_documents", "sale_documents"],
evidence_floor: "rows_matched",
safe_for_model_planning: true,
runtime_must_execute: true
@ -104,18 +135,19 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "aggregate_by_axis",
purpose: "Aggregate already-scoped 1C evidence by a business axis such as counterparty, contract, or period.",
decomposition_hints: ["aggregate_checked_amounts", "aggregate_ranked_axis_values", "aggregate_by_month"],
supported_fact_families: ["value_flow"],
supported_action_families: ["turnover", "payout", "net_value_flow"],
supported_fact_families: ["value_flow", "inventory_stock_snapshot", "inventory_supplier_overlap"],
supported_action_families: ["turnover", "payout", "net_value_flow", "stock_snapshot", "supplier_overlap"],
planning_tags: ["aggregation", "ranking", "monthly_aggregation"],
required_axes_any_of: [
["aggregate_axis", "period"],
["aggregate_axis", "as_of_date"],
["aggregate_axis", "counterparty"],
["aggregate_axis", "account"],
["aggregate_axis", "counterparty", "all_time_scope"],
["aggregate_axis", "organization", "all_time_scope"]
],
optional_axes: ["organization", "contract", "document", "amount"],
output_fact_kinds: ["aggregate_totals", "ranked_axis_values"],
optional_axes: ["organization", "contract", "document", "amount", "quantity", "item", "warehouse", "supplier"],
output_fact_kinds: ["aggregate_totals", "ranked_axis_values", "stock_totals", "item_totals"],
evidence_floor: "rows_matched",
safe_for_model_planning: true,
runtime_must_execute: true
@ -124,12 +156,12 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "drilldown_related_objects",
purpose: "Drill from a known entity or document into related contracts, documents, movements, or payments.",
decomposition_hints: ["drilldown_related_objects"],
supported_fact_families: [],
supported_action_families: [],
planning_tags: ["drilldown"],
required_axes_any_of: [["business_entity"], ["document"], ["contract"], ["counterparty"]],
optional_axes: ["period", "account", "amount"],
output_fact_kinds: ["related_objects", "relationship_edges"],
supported_fact_families: ["inventory_purchase_provenance", "inventory_sale_trace", "inventory_supplier_overlap"],
supported_action_families: ["purchase_provenance", "sale_trace", "supplier_overlap", "purchase_to_sale_chain"],
planning_tags: ["drilldown", "inventory"],
required_axes_any_of: [["business_entity"], ["document"], ["contract"], ["counterparty"], ["item"], ["supplier"]],
optional_axes: ["period", "account", "amount", "warehouse", "as_of_date", "buyer"],
output_fact_kinds: ["related_objects", "relationship_edges", "supplier_item_edges", "buyer_item_edges"],
evidence_floor: "rows_received",
safe_for_model_planning: true,
runtime_must_execute: true
@ -144,7 +176,11 @@ const PRIMITIVE_CONTRACTS = [
"value_flow",
"document_evidence",
"movement_evidence",
"activity_lifecycle"
"activity_lifecycle",
"inventory_stock_snapshot",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: [
"inspect_catalog",
@ -158,11 +194,16 @@ const PRIMITIVE_CONTRACTS = [
"net_value_flow",
"list_documents",
"list_movements",
"activity_duration"
"activity_duration",
"stock_snapshot",
"purchase_provenance",
"sale_trace",
"supplier_overlap",
"purchase_to_sale_chain"
],
planning_tags: ["coverage"],
required_axes_any_of: [["coverage_target"], ["domain_family"], ["primitive_id"]],
optional_axes: ["period", "organization", "counterparty", "document", "account"],
optional_axes: ["period", "organization", "counterparty", "document", "account", "item", "warehouse", "as_of_date"],
output_fact_kinds: ["coverage_status", "known_gaps"],
evidence_floor: "source_summary",
safe_for_model_planning: true,
@ -172,11 +213,24 @@ const PRIMITIVE_CONTRACTS = [
primitive_id: "explain_evidence_basis",
purpose: "Produce a machine-readable explanation of which checked MCP evidence supports, limits, or fails the answer.",
decomposition_hints: ["explain_evidence_basis"],
supported_fact_families: ["activity_lifecycle"],
supported_action_families: ["activity_duration"],
planning_tags: ["explanation"],
supported_fact_families: [
"activity_lifecycle",
"inventory_stock_snapshot",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: [
"activity_duration",
"stock_snapshot",
"purchase_provenance",
"sale_trace",
"supplier_overlap",
"purchase_to_sale_chain"
],
planning_tags: ["explanation", "inventory"],
required_axes_any_of: [["evidence_basis"], ["primitive_id"], ["source_rows_summary"]],
optional_axes: ["coverage_target", "domain_family"],
optional_axes: ["coverage_target", "domain_family", "item", "warehouse", "as_of_date", "supplier", "buyer"],
output_fact_kinds: ["confirmed_facts", "inferred_facts", "unknown_facts"],
evidence_floor: "source_summary",
safe_for_model_planning: true,
@ -245,6 +299,73 @@ const CHAIN_TEMPLATES = [
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_stock_snapshot",
semantic_data_need: "inventory stock snapshot evidence",
chain_summary: "Fetch checked inventory movement or balance rows for the requested as-of date, aggregate item quantities, then probe coverage and explain stock-snapshot limits before answering.",
fallback_primitives: ["query_movements", "aggregate_by_axis", "probe_coverage", "explain_evidence_basis"],
base_required_axes: ["as_of_date", "organization", "warehouse", "aggregate_axis", "quantity", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_stock_snapshot"],
supported_action_families: ["stock_snapshot"],
planning_tags: ["inventory", "movement", "aggregation", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_supplier_overlap",
semantic_data_need: "inventory supplier overlap evidence",
chain_summary: "Ground the supplier or item anchor, fetch checked stock and supporting purchase evidence for the requested slice, aggregate item overlap, then state supplier-link limits explicitly.",
fallback_primitives: [
"resolve_entity_reference",
"query_movements",
"query_documents",
"aggregate_by_axis",
"probe_coverage",
"explain_evidence_basis"
],
base_required_axes: ["supplier", "item", "warehouse", "as_of_date", "aggregate_axis", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_supplier_overlap"],
supported_action_families: ["supplier_overlap"],
planning_tags: ["inventory", "subject_resolution", "movement", "document", "aggregation", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_purchase_provenance",
semantic_data_need: "inventory purchase provenance evidence",
chain_summary: "Ground the selected item, fetch checked purchase documents, drill into related supplier evidence, then probe coverage before stating purchase provenance.",
fallback_primitives: [
"resolve_entity_reference",
"query_documents",
"drilldown_related_objects",
"probe_coverage",
"explain_evidence_basis"
],
base_required_axes: ["item", "document", "supplier", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_purchase_provenance"],
supported_action_families: ["purchase_provenance"],
planning_tags: ["inventory", "document", "drilldown", "subject_resolution", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_sale_trace",
semantic_data_need: "inventory sale trace evidence",
chain_summary: "Ground the selected item, fetch checked sale documents, drill into related buyer evidence, then probe coverage before stating the sale or purchase-to-sale trace.",
fallback_primitives: [
"resolve_entity_reference",
"query_documents",
"drilldown_related_objects",
"probe_coverage",
"explain_evidence_basis"
],
base_required_axes: ["item", "document", "buyer", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_sale_trace"],
supported_action_families: ["sale_trace", "purchase_to_sale_chain"],
planning_tags: ["inventory", "document", "drilldown", "subject_resolution", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "value_flow",
semantic_data_need: "counterparty value-flow evidence",
@ -355,6 +476,23 @@ function tagSetFromFactAxisInput(input) {
if (input.business_fact_family === "value_flow") {
tags.add("movement");
}
if (input.business_fact_family?.startsWith("inventory_")) {
tags.add("inventory");
}
if (input.business_fact_family === "inventory_stock_snapshot") {
tags.add("movement");
tags.add("aggregation");
}
if (input.business_fact_family === "inventory_supplier_overlap") {
tags.add("movement");
tags.add("document");
tags.add("aggregation");
}
if (input.business_fact_family === "inventory_purchase_provenance" ||
input.business_fact_family === "inventory_sale_trace") {
tags.add("document");
tags.add("drilldown");
}
if (input.comparison_need) {
tags.add("comparison");
}
@ -528,6 +666,9 @@ function searchAssistantMcpCatalogPrimitivesByFactAxis(input) {
if (contract.primitive_id === "explain_evidence_basis" && !desiredTags.has("explanation")) {
continue;
}
if (contract.primitive_id === "drilldown_related_objects" && !desiredTags.has("drilldown")) {
continue;
}
if (!factMatch && !actionMatch && tagMatches.length <= 0) {
continue;
}

View File

@ -44,6 +44,32 @@ function businessFactFamilyFor(input) {
if (combined.includes("entity discovery") || combined.includes("entity_resolution")) {
return "entity_grounding";
}
if (combined.includes("inventory") ||
combined.includes("stock") ||
combined.includes("warehouse") ||
combined.includes("item provenance") ||
combined.includes("purchase provenance")) {
if (combined.includes("sale_trace") ||
combined.includes("sale trace") ||
combined.includes("buyer") ||
combined.includes("purchase_to_sale") ||
combined.includes("purchase-to-sale")) {
return "inventory_sale_trace";
}
if (combined.includes("supplier_overlap") ||
combined.includes("supplier overlap") ||
combined.includes("supplier stock") ||
combined.includes("stock by supplier")) {
return "inventory_supplier_overlap";
}
if (combined.includes("purchase_provenance") ||
combined.includes("purchase provenance") ||
combined.includes("purchase document") ||
combined.includes("supplier provenance")) {
return "inventory_purchase_provenance";
}
return "inventory_stock_snapshot";
}
if (combined.includes("lifecycle") || combined.includes("activity")) {
return "activity_lifecycle";
}
@ -87,6 +113,12 @@ function timeScopeNeedFor(input) {
if (input.family === "activity_lifecycle") {
return "open_activity_window";
}
if (input.family === "inventory_stock_snapshot" || input.family === "inventory_supplier_overlap") {
return input.explicitDateScope ? "explicit_period" : "as_of_date_required";
}
if (input.family === "inventory_purchase_provenance" || input.family === "inventory_sale_trace") {
return input.explicitDateScope ? "explicit_period" : null;
}
return null;
}
function comparisonNeedFor(action) {
@ -230,6 +262,30 @@ function decompositionCandidatesFor(input) {
pushUnique(result, "fetch_supporting_documents");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
return result;
}
if (input.family === "inventory_stock_snapshot") {
pushUnique(result, "fetch_scoped_movements");
pushUnique(result, "aggregate_checked_amounts");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
return result;
}
if (input.family === "inventory_supplier_overlap") {
pushUnique(result, "resolve_entity_reference");
pushUnique(result, "fetch_scoped_movements");
pushUnique(result, "fetch_scoped_documents");
pushUnique(result, "aggregate_checked_amounts");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
return result;
}
if (input.family === "inventory_purchase_provenance" || input.family === "inventory_sale_trace") {
pushUnique(result, "resolve_entity_reference");
pushUnique(result, "fetch_scoped_documents");
pushUnique(result, "drilldown_related_objects");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
}
return result;
}
@ -247,6 +303,15 @@ function forbiddenOverclaimFlagsFor(family) {
if (family === "value_flow" || family === "movement_evidence" || family === "document_evidence") {
pushUnique(result, "no_unchecked_fact_totals");
}
if (family === "inventory_stock_snapshot") {
pushUnique(result, "no_unchecked_stock_snapshot");
}
if (family === "inventory_purchase_provenance" || family === "inventory_supplier_overlap") {
pushUnique(result, "no_unproven_supplier_attribution");
}
if (family === "inventory_sale_trace") {
pushUnique(result, "no_unproven_buyer_or_sale_trace");
}
return result;
}
function buildAssistantMcpDiscoveryDataNeedGraph(input) {
@ -290,6 +355,8 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
family: businessFactFamily,
subjectResolutionOptional
});
const inventoryStockSnapshotWithoutSubject = subjectCandidates.length === 0 &&
businessFactFamily === "inventory_stock_snapshot";
const clarificationGaps = [];
if (unsupported === "metadata_lane_choice_clarification" || action === "resolve_next_lane") {
pushUnique(clarificationGaps, "lane_family_choice");
@ -308,7 +375,8 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
else if (subjectCandidates.length === 0 &&
businessFactFamily !== "schema_surface" &&
!openScopeWithoutSubject &&
!metadataScopedOpenLaneWithoutSubject) {
!metadataScopedOpenLaneWithoutSubject &&
!inventoryStockSnapshotWithoutSubject) {
pushUnique(clarificationGaps, "subject");
}
const timeScopeNeed = timeScopeNeedFor({
@ -319,6 +387,9 @@ function buildAssistantMcpDiscoveryDataNeedGraph(input) {
if (timeScopeNeed === "period_required" && !explicitDateScope) {
pushUnique(clarificationGaps, "period");
}
if (timeScopeNeed === "as_of_date_required" && !explicitDateScope) {
pushUnique(clarificationGaps, "as_of_date");
}
const decompositionCandidates = decompositionCandidatesFor({
family: businessFactFamily,
action,

View File

@ -1812,6 +1812,11 @@ function pilotScopeForPlanner(planner) {
case "metadata_lane_clarification":
case "metadata_inspection":
return "metadata_inspection_v1";
case "inventory_stock_snapshot":
case "inventory_supplier_overlap":
case "inventory_purchase_provenance":
case "inventory_sale_trace":
return "inventory_route_template_v1";
case "movement_evidence":
return "counterparty_movement_evidence_query_movements_v1";
case "value_flow_comparison":
@ -1827,6 +1832,12 @@ function pilotScopeForPlanner(planner) {
}
}
function isLivePilotChainSupported(chainId) {
if (chainId === "inventory_stock_snapshot" ||
chainId === "inventory_supplier_overlap" ||
chainId === "inventory_purchase_provenance" ||
chainId === "inventory_sale_trace") {
return false;
}
return true;
}
async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {

View File

@ -530,6 +530,100 @@ function recipeFor(input) {
extraReasons: [...primitiveSelection.reasonCodes, ...LIFECYCLE_BOUNDED_INFERENCE_REASON_CODES]
});
}
if (graphFactFamily === "inventory_stock_snapshot") {
pushUnique(axes, "as_of_date");
pushUnique(axes, "organization");
pushUnique(axes, "warehouse");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "quantity");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("inventory_stock_snapshot");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction,
allowAggregateByAxis: true
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_stock_snapshot",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_stock_snapshot_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "inventory_supplier_overlap") {
pushUnique(axes, "supplier");
pushUnique(axes, "item");
pushUnique(axes, "warehouse");
pushUnique(axes, "as_of_date");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("inventory_supplier_overlap");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction,
allowAggregateByAxis: true
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_supplier_overlap",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_supplier_overlap_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "inventory_purchase_provenance") {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "supplier");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("inventory_purchase_provenance");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_purchase_provenance",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_purchase_provenance_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "inventory_sale_trace") {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "buyer");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("inventory_sale_trace");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_sale_trace",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_sale_trace_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "schema_surface") {
pushUnique(axes, "metadata_scope");
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("metadata_inspection");
@ -658,6 +752,58 @@ function recipeFor(input) {
reason: "planner_selected_metadata_lane_clarification_recipe"
};
}
if (includesAny(combined, ["inventory_sale_trace", "sale_trace", "sale trace", "purchase_to_sale", "purchase-to-sale", "buyer"])) {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "buyer");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_sale_trace",
axes,
reason: "planner_selected_inventory_sale_trace_recipe"
});
}
if (includesAny(combined, ["inventory_supplier_overlap", "supplier overlap", "supplier stock", "stock by supplier"])) {
pushUnique(axes, "supplier");
pushUnique(axes, "item");
pushUnique(axes, "warehouse");
pushUnique(axes, "as_of_date");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_supplier_overlap",
axes,
reason: "planner_selected_inventory_supplier_overlap_recipe"
});
}
if (includesAny(combined, ["inventory_purchase_provenance", "purchase_provenance", "purchase provenance", "supplier provenance"])) {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "supplier");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_purchase_provenance",
axes,
reason: "planner_selected_inventory_purchase_provenance_recipe"
});
}
if (includesAny(combined, ["inventory", "stock", "warehouse"])) {
pushUnique(axes, "as_of_date");
pushUnique(axes, "organization");
pushUnique(axes, "warehouse");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "quantity");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_stock_snapshot",
axes,
reason: "planner_selected_inventory_stock_snapshot_recipe"
});
}
if (includesAny(combined, ["turnover", "revenue", "payment", "payout", "value", "net", "netting", "balance", "cashflow"])) {
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "amount");

View File

@ -787,6 +787,18 @@ function semanticNeedFor(input) {
if (/(?:document|documents|list_documents)/iu.test(combined)) {
return "document evidence";
}
if (/(?:inventory|stock|warehouse|purchase_provenance|purchase provenance|supplier provenance|supplier_overlap|supplier overlap|sale_trace|sale trace|purchase_to_sale|purchase-to-sale)/iu.test(combined)) {
if (/(?:sale_trace|sale trace|purchase_to_sale|purchase-to-sale|buyer)/iu.test(combined)) {
return "inventory sale trace evidence";
}
if (/(?:supplier_overlap|supplier overlap|supplier stock|stock by supplier)/iu.test(combined)) {
return "inventory supplier overlap evidence";
}
if (/(?:purchase_provenance|purchase provenance|supplier provenance|purchase document)/iu.test(combined)) {
return "inventory purchase provenance evidence";
}
return "inventory stock snapshot evidence";
}
return null;
}
function shouldRunDiscovery(input) {

View File

@ -12,6 +12,10 @@ export type AssistantMcpCatalogPlanReviewStatus = "catalog_compatible" | "needs_
export type AssistantMcpCatalogChainTemplateId =
| "metadata_inspection"
| "catalog_drilldown"
| "inventory_stock_snapshot"
| "inventory_supplier_overlap"
| "inventory_purchase_provenance"
| "inventory_sale_trace"
| "value_flow"
| "value_flow_comparison"
| "value_flow_ranking"
@ -100,8 +104,28 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
primitive_id: "resolve_entity_reference",
purpose: "Resolve a user-visible entity name to a concrete 1C reference candidate.",
decomposition_hints: ["resolve_entity_reference"],
supported_fact_families: ["entity_grounding", "value_flow", "document_evidence", "movement_evidence", "activity_lifecycle"],
supported_action_families: ["search_business_entity", "turnover", "payout", "net_value_flow", "list_documents", "list_movements", "activity_duration"],
supported_fact_families: [
"entity_grounding",
"value_flow",
"document_evidence",
"movement_evidence",
"activity_lifecycle",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: [
"search_business_entity",
"turnover",
"payout",
"net_value_flow",
"list_documents",
"list_movements",
"activity_duration",
"purchase_provenance",
"sale_trace",
"supplier_overlap"
],
planning_tags: ["subject_resolution"],
required_axes_any_of: [["business_entity"], ["counterparty"], ["organization"], ["contract"], ["item"]],
optional_axes: ["period", "inn", "document"],
@ -119,18 +143,21 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
"collect_outgoing_movements",
"fetch_scoped_movements"
],
supported_fact_families: ["value_flow", "movement_evidence"],
supported_action_families: ["turnover", "payout", "net_value_flow", "list_movements"],
supported_fact_families: ["value_flow", "movement_evidence", "inventory_stock_snapshot", "inventory_supplier_overlap"],
supported_action_families: ["turnover", "payout", "net_value_flow", "list_movements", "stock_snapshot", "supplier_overlap"],
planning_tags: ["movement", "comparison", "ranking", "aggregation", "monthly_aggregation"],
required_axes_any_of: [
["period", "account"],
["period", "counterparty"],
["period", "organization"],
["as_of_date", "organization"],
["as_of_date", "warehouse"],
["as_of_date", "item"],
["all_time_scope", "counterparty"],
["all_time_scope", "organization"]
],
optional_axes: ["contract", "document", "amount", "item", "warehouse"],
output_fact_kinds: ["movement_rows", "turnover", "balance_delta"],
optional_axes: ["contract", "document", "amount", "item", "warehouse", "quantity", "supplier"],
output_fact_kinds: ["movement_rows", "turnover", "balance_delta", "stock_rows", "stock_quantity"],
evidence_floor: "rows_matched",
safe_for_model_planning: true,
runtime_must_execute: true
@ -139,19 +166,27 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
primitive_id: "query_documents",
purpose: "Fetch documents related to a scoped entity, period, contract, or movement explanation.",
decomposition_hints: ["fetch_scoped_documents", "fetch_supporting_documents"],
supported_fact_families: ["document_evidence", "activity_lifecycle"],
supported_action_families: ["list_documents", "activity_duration"],
supported_fact_families: [
"document_evidence",
"activity_lifecycle",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: ["list_documents", "activity_duration", "purchase_provenance", "sale_trace", "supplier_overlap"],
planning_tags: ["document"],
required_axes_any_of: [
["document"],
["item"],
["supplier"],
["counterparty"],
["contract"],
["period", "organization"],
["all_time_scope", "counterparty"],
["all_time_scope", "organization"]
],
optional_axes: ["account", "amount", "item", "warehouse"],
output_fact_kinds: ["document_rows", "document_dates", "document_amounts"],
optional_axes: ["account", "amount", "item", "warehouse", "as_of_date", "supplier", "buyer"],
output_fact_kinds: ["document_rows", "document_dates", "document_amounts", "purchase_documents", "sale_documents"],
evidence_floor: "rows_matched",
safe_for_model_planning: true,
runtime_must_execute: true
@ -160,18 +195,19 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
primitive_id: "aggregate_by_axis",
purpose: "Aggregate already-scoped 1C evidence by a business axis such as counterparty, contract, or period.",
decomposition_hints: ["aggregate_checked_amounts", "aggregate_ranked_axis_values", "aggregate_by_month"],
supported_fact_families: ["value_flow"],
supported_action_families: ["turnover", "payout", "net_value_flow"],
supported_fact_families: ["value_flow", "inventory_stock_snapshot", "inventory_supplier_overlap"],
supported_action_families: ["turnover", "payout", "net_value_flow", "stock_snapshot", "supplier_overlap"],
planning_tags: ["aggregation", "ranking", "monthly_aggregation"],
required_axes_any_of: [
["aggregate_axis", "period"],
["aggregate_axis", "as_of_date"],
["aggregate_axis", "counterparty"],
["aggregate_axis", "account"],
["aggregate_axis", "counterparty", "all_time_scope"],
["aggregate_axis", "organization", "all_time_scope"]
],
optional_axes: ["organization", "contract", "document", "amount"],
output_fact_kinds: ["aggregate_totals", "ranked_axis_values"],
optional_axes: ["organization", "contract", "document", "amount", "quantity", "item", "warehouse", "supplier"],
output_fact_kinds: ["aggregate_totals", "ranked_axis_values", "stock_totals", "item_totals"],
evidence_floor: "rows_matched",
safe_for_model_planning: true,
runtime_must_execute: true
@ -180,12 +216,12 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
primitive_id: "drilldown_related_objects",
purpose: "Drill from a known entity or document into related contracts, documents, movements, or payments.",
decomposition_hints: ["drilldown_related_objects"],
supported_fact_families: [],
supported_action_families: [],
planning_tags: ["drilldown"],
required_axes_any_of: [["business_entity"], ["document"], ["contract"], ["counterparty"]],
optional_axes: ["period", "account", "amount"],
output_fact_kinds: ["related_objects", "relationship_edges"],
supported_fact_families: ["inventory_purchase_provenance", "inventory_sale_trace", "inventory_supplier_overlap"],
supported_action_families: ["purchase_provenance", "sale_trace", "supplier_overlap", "purchase_to_sale_chain"],
planning_tags: ["drilldown", "inventory"],
required_axes_any_of: [["business_entity"], ["document"], ["contract"], ["counterparty"], ["item"], ["supplier"]],
optional_axes: ["period", "account", "amount", "warehouse", "as_of_date", "buyer"],
output_fact_kinds: ["related_objects", "relationship_edges", "supplier_item_edges", "buyer_item_edges"],
evidence_floor: "rows_received",
safe_for_model_planning: true,
runtime_must_execute: true
@ -200,7 +236,11 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
"value_flow",
"document_evidence",
"movement_evidence",
"activity_lifecycle"
"activity_lifecycle",
"inventory_stock_snapshot",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: [
"inspect_catalog",
@ -214,11 +254,16 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
"net_value_flow",
"list_documents",
"list_movements",
"activity_duration"
"activity_duration",
"stock_snapshot",
"purchase_provenance",
"sale_trace",
"supplier_overlap",
"purchase_to_sale_chain"
],
planning_tags: ["coverage"],
required_axes_any_of: [["coverage_target"], ["domain_family"], ["primitive_id"]],
optional_axes: ["period", "organization", "counterparty", "document", "account"],
optional_axes: ["period", "organization", "counterparty", "document", "account", "item", "warehouse", "as_of_date"],
output_fact_kinds: ["coverage_status", "known_gaps"],
evidence_floor: "source_summary",
safe_for_model_planning: true,
@ -228,11 +273,24 @@ const PRIMITIVE_CONTRACTS: AssistantMcpCatalogPrimitiveContract[] = [
primitive_id: "explain_evidence_basis",
purpose: "Produce a machine-readable explanation of which checked MCP evidence supports, limits, or fails the answer.",
decomposition_hints: ["explain_evidence_basis"],
supported_fact_families: ["activity_lifecycle"],
supported_action_families: ["activity_duration"],
planning_tags: ["explanation"],
supported_fact_families: [
"activity_lifecycle",
"inventory_stock_snapshot",
"inventory_purchase_provenance",
"inventory_sale_trace",
"inventory_supplier_overlap"
],
supported_action_families: [
"activity_duration",
"stock_snapshot",
"purchase_provenance",
"sale_trace",
"supplier_overlap",
"purchase_to_sale_chain"
],
planning_tags: ["explanation", "inventory"],
required_axes_any_of: [["evidence_basis"], ["primitive_id"], ["source_rows_summary"]],
optional_axes: ["coverage_target", "domain_family"],
optional_axes: ["coverage_target", "domain_family", "item", "warehouse", "as_of_date", "supplier", "buyer"],
output_fact_kinds: ["confirmed_facts", "inferred_facts", "unknown_facts"],
evidence_floor: "source_summary",
safe_for_model_planning: true,
@ -308,6 +366,77 @@ const CHAIN_TEMPLATES: AssistantMcpCatalogChainTemplateContract[] = [
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_stock_snapshot",
semantic_data_need: "inventory stock snapshot evidence",
chain_summary:
"Fetch checked inventory movement or balance rows for the requested as-of date, aggregate item quantities, then probe coverage and explain stock-snapshot limits before answering.",
fallback_primitives: ["query_movements", "aggregate_by_axis", "probe_coverage", "explain_evidence_basis"],
base_required_axes: ["as_of_date", "organization", "warehouse", "aggregate_axis", "quantity", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_stock_snapshot"],
supported_action_families: ["stock_snapshot"],
planning_tags: ["inventory", "movement", "aggregation", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_supplier_overlap",
semantic_data_need: "inventory supplier overlap evidence",
chain_summary:
"Ground the supplier or item anchor, fetch checked stock and supporting purchase evidence for the requested slice, aggregate item overlap, then state supplier-link limits explicitly.",
fallback_primitives: [
"resolve_entity_reference",
"query_movements",
"query_documents",
"aggregate_by_axis",
"probe_coverage",
"explain_evidence_basis"
],
base_required_axes: ["supplier", "item", "warehouse", "as_of_date", "aggregate_axis", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_supplier_overlap"],
supported_action_families: ["supplier_overlap"],
planning_tags: ["inventory", "subject_resolution", "movement", "document", "aggregation", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_purchase_provenance",
semantic_data_need: "inventory purchase provenance evidence",
chain_summary:
"Ground the selected item, fetch checked purchase documents, drill into related supplier evidence, then probe coverage before stating purchase provenance.",
fallback_primitives: [
"resolve_entity_reference",
"query_documents",
"drilldown_related_objects",
"probe_coverage",
"explain_evidence_basis"
],
base_required_axes: ["item", "document", "supplier", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_purchase_provenance"],
supported_action_families: ["purchase_provenance"],
planning_tags: ["inventory", "document", "drilldown", "subject_resolution", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "inventory_sale_trace",
semantic_data_need: "inventory sale trace evidence",
chain_summary:
"Ground the selected item, fetch checked sale documents, drill into related buyer evidence, then probe coverage before stating the sale or purchase-to-sale trace.",
fallback_primitives: [
"resolve_entity_reference",
"query_documents",
"drilldown_related_objects",
"probe_coverage",
"explain_evidence_basis"
],
base_required_axes: ["item", "document", "buyer", "coverage_target", "evidence_basis"],
supported_fact_families: ["inventory_sale_trace"],
supported_action_families: ["sale_trace", "purchase_to_sale_chain"],
planning_tags: ["inventory", "document", "drilldown", "subject_resolution", "coverage", "explanation"],
safe_for_model_planning: true,
requires_evidence_gate: true
},
{
chain_id: "value_flow",
semantic_data_need: "counterparty value-flow evidence",
@ -435,6 +564,25 @@ function tagSetFromFactAxisInput(input: AssistantMcpCatalogFactAxisSearchInput):
if (input.business_fact_family === "value_flow") {
tags.add("movement");
}
if (input.business_fact_family?.startsWith("inventory_")) {
tags.add("inventory");
}
if (input.business_fact_family === "inventory_stock_snapshot") {
tags.add("movement");
tags.add("aggregation");
}
if (input.business_fact_family === "inventory_supplier_overlap") {
tags.add("movement");
tags.add("document");
tags.add("aggregation");
}
if (
input.business_fact_family === "inventory_purchase_provenance" ||
input.business_fact_family === "inventory_sale_trace"
) {
tags.add("document");
tags.add("drilldown");
}
if (input.comparison_need) {
tags.add("comparison");
}
@ -662,6 +810,9 @@ export function searchAssistantMcpCatalogPrimitivesByFactAxis(
if (contract.primitive_id === "explain_evidence_basis" && !desiredTags.has("explanation")) {
continue;
}
if (contract.primitive_id === "drilldown_related_objects" && !desiredTags.has("drilldown")) {
continue;
}
if (!factMatch && !actionMatch && tagMatches.length <= 0) {
continue;
}

View File

@ -86,6 +86,40 @@ function businessFactFamilyFor(input: {
if (combined.includes("entity discovery") || combined.includes("entity_resolution")) {
return "entity_grounding";
}
if (
combined.includes("inventory") ||
combined.includes("stock") ||
combined.includes("warehouse") ||
combined.includes("item provenance") ||
combined.includes("purchase provenance")
) {
if (
combined.includes("sale_trace") ||
combined.includes("sale trace") ||
combined.includes("buyer") ||
combined.includes("purchase_to_sale") ||
combined.includes("purchase-to-sale")
) {
return "inventory_sale_trace";
}
if (
combined.includes("supplier_overlap") ||
combined.includes("supplier overlap") ||
combined.includes("supplier stock") ||
combined.includes("stock by supplier")
) {
return "inventory_supplier_overlap";
}
if (
combined.includes("purchase_provenance") ||
combined.includes("purchase provenance") ||
combined.includes("purchase document") ||
combined.includes("supplier provenance")
) {
return "inventory_purchase_provenance";
}
return "inventory_stock_snapshot";
}
if (combined.includes("lifecycle") || combined.includes("activity")) {
return "activity_lifecycle";
}
@ -140,6 +174,12 @@ function timeScopeNeedFor(input: {
if (input.family === "activity_lifecycle") {
return "open_activity_window";
}
if (input.family === "inventory_stock_snapshot" || input.family === "inventory_supplier_overlap") {
return input.explicitDateScope ? "explicit_period" : "as_of_date_required";
}
if (input.family === "inventory_purchase_provenance" || input.family === "inventory_sale_trace") {
return input.explicitDateScope ? "explicit_period" : null;
}
return null;
}
@ -328,6 +368,30 @@ function decompositionCandidatesFor(input: {
pushUnique(result, "fetch_supporting_documents");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
return result;
}
if (input.family === "inventory_stock_snapshot") {
pushUnique(result, "fetch_scoped_movements");
pushUnique(result, "aggregate_checked_amounts");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
return result;
}
if (input.family === "inventory_supplier_overlap") {
pushUnique(result, "resolve_entity_reference");
pushUnique(result, "fetch_scoped_movements");
pushUnique(result, "fetch_scoped_documents");
pushUnique(result, "aggregate_checked_amounts");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
return result;
}
if (input.family === "inventory_purchase_provenance" || input.family === "inventory_sale_trace") {
pushUnique(result, "resolve_entity_reference");
pushUnique(result, "fetch_scoped_documents");
pushUnique(result, "drilldown_related_objects");
pushUnique(result, "probe_coverage");
pushUnique(result, "explain_evidence_basis");
}
return result;
}
@ -346,6 +410,15 @@ function forbiddenOverclaimFlagsFor(family: string | null): string[] {
if (family === "value_flow" || family === "movement_evidence" || family === "document_evidence") {
pushUnique(result, "no_unchecked_fact_totals");
}
if (family === "inventory_stock_snapshot") {
pushUnique(result, "no_unchecked_stock_snapshot");
}
if (family === "inventory_purchase_provenance" || family === "inventory_supplier_overlap") {
pushUnique(result, "no_unproven_supplier_attribution");
}
if (family === "inventory_sale_trace") {
pushUnique(result, "no_unproven_buyer_or_sale_trace");
}
return result;
}
@ -394,6 +467,9 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
family: businessFactFamily,
subjectResolutionOptional
});
const inventoryStockSnapshotWithoutSubject =
subjectCandidates.length === 0 &&
businessFactFamily === "inventory_stock_snapshot";
const clarificationGaps: string[] = [];
if (unsupported === "metadata_lane_choice_clarification" || action === "resolve_next_lane") {
pushUnique(clarificationGaps, "lane_family_choice");
@ -415,7 +491,8 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
subjectCandidates.length === 0 &&
businessFactFamily !== "schema_surface" &&
!openScopeWithoutSubject &&
!metadataScopedOpenLaneWithoutSubject
!metadataScopedOpenLaneWithoutSubject &&
!inventoryStockSnapshotWithoutSubject
) {
pushUnique(clarificationGaps, "subject");
}
@ -427,6 +504,9 @@ export function buildAssistantMcpDiscoveryDataNeedGraph(
if (timeScopeNeed === "period_required" && !explicitDateScope) {
pushUnique(clarificationGaps, "period");
}
if (timeScopeNeed === "as_of_date_required" && !explicitDateScope) {
pushUnique(clarificationGaps, "as_of_date");
}
const decompositionCandidates = decompositionCandidatesFor({
family: businessFactFamily,
action,

View File

@ -199,7 +199,8 @@ export type AssistantMcpDiscoveryPilotScope =
| "counterparty_lifecycle_query_documents_v1"
| "counterparty_value_flow_query_movements_v1"
| "counterparty_supplier_payout_query_movements_v1"
| "counterparty_bidirectional_value_flow_query_movements_v1";
| "counterparty_bidirectional_value_flow_query_movements_v1"
| "inventory_route_template_v1";
export interface AssistantMcpDiscoveryPilotExecutionContract {
schema_version: typeof ASSISTANT_MCP_DISCOVERY_PILOT_EXECUTOR_SCHEMA_VERSION;
@ -2420,6 +2421,11 @@ function pilotScopeForPlanner(planner: AssistantMcpDiscoveryPlannerContract): As
case "metadata_lane_clarification":
case "metadata_inspection":
return "metadata_inspection_v1";
case "inventory_stock_snapshot":
case "inventory_supplier_overlap":
case "inventory_purchase_provenance":
case "inventory_sale_trace":
return "inventory_route_template_v1";
case "movement_evidence":
return "counterparty_movement_evidence_query_movements_v1";
case "value_flow_comparison":
@ -2436,6 +2442,14 @@ function pilotScopeForPlanner(planner: AssistantMcpDiscoveryPlannerContract): As
}
function isLivePilotChainSupported(chainId: AssistantMcpDiscoveryChainId): boolean {
if (
chainId === "inventory_stock_snapshot" ||
chainId === "inventory_supplier_overlap" ||
chainId === "inventory_purchase_provenance" ||
chainId === "inventory_sale_trace"
) {
return false;
}
return true;
}

View File

@ -41,6 +41,10 @@ export type AssistantMcpDiscoveryChainId =
| "metadata_inspection"
| "catalog_drilldown"
| "metadata_lane_clarification"
| "inventory_stock_snapshot"
| "inventory_supplier_overlap"
| "inventory_purchase_provenance"
| "inventory_sale_trace"
| "value_flow"
| "value_flow_comparison"
| "value_flow_ranking"
@ -720,6 +724,104 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
});
}
if (graphFactFamily === "inventory_stock_snapshot") {
pushUnique(axes, "as_of_date");
pushUnique(axes, "organization");
pushUnique(axes, "warehouse");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "quantity");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = getAssistantMcpCatalogChainTemplate("inventory_stock_snapshot");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction,
allowAggregateByAxis: true
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_stock_snapshot",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_stock_snapshot_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "inventory_supplier_overlap") {
pushUnique(axes, "supplier");
pushUnique(axes, "item");
pushUnique(axes, "warehouse");
pushUnique(axes, "as_of_date");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = getAssistantMcpCatalogChainTemplate("inventory_supplier_overlap");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction,
allowAggregateByAxis: true
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_supplier_overlap",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_supplier_overlap_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "inventory_purchase_provenance") {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "supplier");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = getAssistantMcpCatalogChainTemplate("inventory_purchase_provenance");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_purchase_provenance",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_purchase_provenance_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "inventory_sale_trace") {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "buyer");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
const template = getAssistantMcpCatalogChainTemplate("inventory_sale_trace");
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
dataNeedGraph,
fallbackPrimitives: template.fallback_primitives,
requiredAxes: axes,
metadataSurface: input.metadataSurface,
actionFamily: action || graphAction
});
return recipeFromCatalogChainTemplate({
chainId: "inventory_sale_trace",
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_inventory_sale_trace_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
});
}
if (graphFactFamily === "schema_surface") {
pushUnique(axes, "metadata_scope");
const template = getAssistantMcpCatalogChainTemplate("metadata_inspection");
@ -856,6 +958,62 @@ function recipeFor(input: AssistantMcpDiscoveryPlannerInput): PlannerRecipe {
};
}
if (includesAny(combined, ["inventory_sale_trace", "sale_trace", "sale trace", "purchase_to_sale", "purchase-to-sale", "buyer"])) {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "buyer");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_sale_trace",
axes,
reason: "planner_selected_inventory_sale_trace_recipe"
});
}
if (includesAny(combined, ["inventory_supplier_overlap", "supplier overlap", "supplier stock", "stock by supplier"])) {
pushUnique(axes, "supplier");
pushUnique(axes, "item");
pushUnique(axes, "warehouse");
pushUnique(axes, "as_of_date");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_supplier_overlap",
axes,
reason: "planner_selected_inventory_supplier_overlap_recipe"
});
}
if (includesAny(combined, ["inventory_purchase_provenance", "purchase_provenance", "purchase provenance", "supplier provenance"])) {
pushUnique(axes, "item");
pushUnique(axes, "document");
pushUnique(axes, "supplier");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_purchase_provenance",
axes,
reason: "planner_selected_inventory_purchase_provenance_recipe"
});
}
if (includesAny(combined, ["inventory", "stock", "warehouse"])) {
pushUnique(axes, "as_of_date");
pushUnique(axes, "organization");
pushUnique(axes, "warehouse");
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "quantity");
pushUnique(axes, "coverage_target");
pushUnique(axes, "evidence_basis");
return recipeFromCatalogChainTemplate({
chainId: "inventory_stock_snapshot",
axes,
reason: "planner_selected_inventory_stock_snapshot_recipe"
});
}
if (includesAny(combined, ["turnover", "revenue", "payment", "payout", "value", "net", "netting", "balance", "cashflow"])) {
pushUnique(axes, "aggregate_axis");
pushUnique(axes, "amount");

View File

@ -1063,6 +1063,18 @@ function semanticNeedFor(input: {
if (/(?:document|documents|list_documents)/iu.test(combined)) {
return "document evidence";
}
if (/(?:inventory|stock|warehouse|purchase_provenance|purchase provenance|supplier provenance|supplier_overlap|supplier overlap|sale_trace|sale trace|purchase_to_sale|purchase-to-sale)/iu.test(combined)) {
if (/(?:sale_trace|sale trace|purchase_to_sale|purchase-to-sale|buyer)/iu.test(combined)) {
return "inventory sale trace evidence";
}
if (/(?:supplier_overlap|supplier overlap|supplier stock|stock by supplier)/iu.test(combined)) {
return "inventory supplier overlap evidence";
}
if (/(?:purchase_provenance|purchase provenance|supplier provenance|purchase document)/iu.test(combined)) {
return "inventory purchase provenance evidence";
}
return "inventory stock snapshot evidence";
}
return null;
}

View File

@ -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"],

View File

@ -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",

View File

@ -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: {