Planner Autonomy: вынести MCP chain templates в route fabric
This commit is contained in:
@@ -6,6 +6,7 @@ exports.searchAssistantMcpCatalogPrimitivesByFactAxis = searchAssistantMcpCatalo
|
||||
exports.searchAssistantMcpCatalogPrimitivesByMetadataSurface = searchAssistantMcpCatalogPrimitivesByMetadataSurface;
|
||||
exports.buildAssistantMcpCatalogIndex = buildAssistantMcpCatalogIndex;
|
||||
exports.getAssistantMcpCatalogPrimitive = getAssistantMcpCatalogPrimitive;
|
||||
exports.getAssistantMcpCatalogChainTemplate = getAssistantMcpCatalogChainTemplate;
|
||||
exports.reviewAssistantMcpDiscoveryPlanAgainstCatalog = reviewAssistantMcpDiscoveryPlanAgainstCatalog;
|
||||
const assistantMcpDiscoveryPolicy_1 = require("./assistantMcpDiscoveryPolicy");
|
||||
exports.ASSISTANT_MCP_CATALOG_INDEX_SCHEMA_VERSION = "assistant_mcp_catalog_index_v1";
|
||||
@@ -183,6 +184,117 @@ const PRIMITIVE_CONTRACTS = [
|
||||
}
|
||||
];
|
||||
const PRIMITIVE_CONTRACT_MAP = new Map(PRIMITIVE_CONTRACTS.map((contract) => [contract.primitive_id, contract]));
|
||||
const CHAIN_TEMPLATES = [
|
||||
{
|
||||
chain_id: "metadata_inspection",
|
||||
semantic_data_need: "1C metadata evidence",
|
||||
chain_summary: "Inspect the 1C metadata surface first, then ground the next safe lane from confirmed schema evidence.",
|
||||
fallback_primitives: ["inspect_1c_metadata"],
|
||||
base_required_axes: ["metadata_scope"],
|
||||
supported_fact_families: ["schema_surface"],
|
||||
supported_action_families: ["inspect_catalog", "inspect_documents", "inspect_registers", "inspect_fields", "inspect_surface"],
|
||||
planning_tags: ["metadata", "surface_inspection"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "catalog_drilldown",
|
||||
semantic_data_need: "catalog drilldown metadata evidence",
|
||||
chain_summary: "Drill deeper into the confirmed catalog-oriented metadata surface, inspect related metadata objects, and keep the next safe lane grounded in checked schema evidence.",
|
||||
fallback_primitives: ["inspect_1c_metadata"],
|
||||
base_required_axes: ["metadata_scope"],
|
||||
supported_fact_families: ["schema_surface"],
|
||||
supported_action_families: ["inspect_catalog", "inspect_surface"],
|
||||
planning_tags: ["metadata", "surface_inspection", "drilldown"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "entity_resolution",
|
||||
semantic_data_need: "entity discovery evidence",
|
||||
chain_summary: "Search candidate business entities, resolve the most relevant 1C reference, and prove whether the entity grounding is stable enough for the next probe.",
|
||||
fallback_primitives: ["search_business_entity", "resolve_entity_reference", "probe_coverage"],
|
||||
base_required_axes: ["business_entity", "coverage_target"],
|
||||
supported_fact_families: ["entity_grounding"],
|
||||
supported_action_families: ["search_business_entity"],
|
||||
planning_tags: ["subject_resolution", "coverage"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "document_evidence",
|
||||
semantic_data_need: "document evidence",
|
||||
chain_summary: "Resolve the business entity, fetch scoped document rows, and probe coverage before stating the checked document evidence.",
|
||||
fallback_primitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
|
||||
base_required_axes: ["coverage_target"],
|
||||
supported_fact_families: ["document_evidence", "activity_lifecycle"],
|
||||
supported_action_families: ["list_documents", "activity_duration"],
|
||||
planning_tags: ["document", "subject_resolution", "coverage"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "movement_evidence",
|
||||
semantic_data_need: "movement evidence",
|
||||
chain_summary: "Resolve the business entity, fetch scoped movement rows, and probe coverage without pretending to have a full movement universe.",
|
||||
fallback_primitives: ["resolve_entity_reference", "query_movements", "probe_coverage"],
|
||||
base_required_axes: ["coverage_target"],
|
||||
supported_fact_families: ["movement_evidence", "value_flow"],
|
||||
supported_action_families: ["list_movements", "turnover", "payout", "net_value_flow"],
|
||||
planning_tags: ["movement", "subject_resolution", "coverage"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "value_flow",
|
||||
semantic_data_need: "counterparty value-flow evidence",
|
||||
chain_summary: "Resolve the business entity, query scoped movements, aggregate checked amounts, then probe coverage before answering.",
|
||||
fallback_primitives: ["resolve_entity_reference", "query_movements", "aggregate_by_axis", "probe_coverage"],
|
||||
base_required_axes: ["aggregate_axis", "amount", "coverage_target"],
|
||||
supported_fact_families: ["value_flow"],
|
||||
supported_action_families: ["turnover", "payout", "net_value_flow"],
|
||||
planning_tags: ["movement", "aggregation", "coverage"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "value_flow_comparison",
|
||||
semantic_data_need: "bidirectional value-flow comparison evidence",
|
||||
chain_summary: "Query incoming and outgoing movements for the checked period and organization, compare the checked sides, and probe coverage before answering a bounded comparison.",
|
||||
fallback_primitives: ["query_movements", "probe_coverage"],
|
||||
base_required_axes: ["amount", "coverage_target"],
|
||||
supported_fact_families: ["value_flow"],
|
||||
supported_action_families: ["net_value_flow"],
|
||||
planning_tags: ["movement", "comparison", "coverage"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "value_flow_ranking",
|
||||
semantic_data_need: "ranked value-flow evidence",
|
||||
chain_summary: "Query scoped movements for the checked period and organization, aggregate checked amounts by counterparty, then probe coverage before answering a bounded ranking.",
|
||||
fallback_primitives: ["query_movements", "aggregate_by_axis", "probe_coverage"],
|
||||
base_required_axes: ["aggregate_axis", "amount", "coverage_target"],
|
||||
supported_fact_families: ["value_flow"],
|
||||
supported_action_families: ["turnover", "payout"],
|
||||
planning_tags: ["movement", "ranking", "aggregation", "coverage"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
},
|
||||
{
|
||||
chain_id: "lifecycle",
|
||||
semantic_data_need: "counterparty lifecycle evidence",
|
||||
chain_summary: "Resolve the business entity, query supporting documents, probe coverage, then explain the evidence basis for the inferred activity window.",
|
||||
fallback_primitives: ["resolve_entity_reference", "query_documents", "probe_coverage", "explain_evidence_basis"],
|
||||
base_required_axes: ["document_date", "coverage_target", "evidence_basis"],
|
||||
supported_fact_families: ["activity_lifecycle"],
|
||||
supported_action_families: ["activity_duration"],
|
||||
planning_tags: ["document", "explanation", "coverage"],
|
||||
safe_for_model_planning: true,
|
||||
requires_evidence_gate: true
|
||||
}
|
||||
];
|
||||
const CHAIN_TEMPLATE_MAP = new Map(CHAIN_TEMPLATES.map((template) => [template.chain_id, template]));
|
||||
function toStringSet(values) {
|
||||
return new Set(values.map((item) => item.trim()).filter((item) => item.length > 0));
|
||||
}
|
||||
@@ -516,10 +628,18 @@ function buildAssistantMcpCatalogIndex() {
|
||||
else {
|
||||
pushReason(reasonCodes, "catalog_covers_all_discovery_primitives");
|
||||
}
|
||||
const unknownChainPrimitives = CHAIN_TEMPLATES.flatMap((template) => template.fallback_primitives.filter((primitive) => !PRIMITIVE_CONTRACT_MAP.has(primitive)));
|
||||
if (unknownChainPrimitives.length > 0) {
|
||||
pushReason(reasonCodes, "catalog_chain_template_references_unknown_primitive");
|
||||
}
|
||||
else {
|
||||
pushReason(reasonCodes, "catalog_chain_templates_reference_reviewed_primitives");
|
||||
}
|
||||
return {
|
||||
schema_version: exports.ASSISTANT_MCP_CATALOG_INDEX_SCHEMA_VERSION,
|
||||
policy_owner: "assistantMcpCatalogIndex",
|
||||
primitives: PRIMITIVE_CONTRACTS,
|
||||
chain_templates: CHAIN_TEMPLATES,
|
||||
reason_codes: reasonCodes
|
||||
};
|
||||
}
|
||||
@@ -530,6 +650,13 @@ function getAssistantMcpCatalogPrimitive(primitive) {
|
||||
}
|
||||
return contract;
|
||||
}
|
||||
function getAssistantMcpCatalogChainTemplate(chainId) {
|
||||
const template = CHAIN_TEMPLATE_MAP.get(chainId);
|
||||
if (!template) {
|
||||
throw new Error(`Missing MCP catalog chain template: ${chainId}`);
|
||||
}
|
||||
return template;
|
||||
}
|
||||
function reviewAssistantMcpDiscoveryPlanAgainstCatalog(plan) {
|
||||
const reasonCodes = [];
|
||||
const axisSet = toStringSet(plan.required_axes);
|
||||
|
||||
+112
-115
@@ -35,6 +35,28 @@ function pushUnique(target, value) {
|
||||
target.push(text);
|
||||
}
|
||||
}
|
||||
function pushAllUnique(target, values) {
|
||||
for (const value of values) {
|
||||
pushUnique(target, value);
|
||||
}
|
||||
}
|
||||
function recipeFromCatalogChainTemplate(input) {
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)(input.chainId);
|
||||
const axes = [...input.axes];
|
||||
pushAllUnique(axes, template.base_required_axes);
|
||||
return {
|
||||
semanticDataNeed: input.semanticDataNeed ?? template.semantic_data_need,
|
||||
chainId: template.chain_id,
|
||||
chainSummary: input.chainSummary ?? template.chain_summary,
|
||||
primitives: input.primitives ?? template.fallback_primitives,
|
||||
axes,
|
||||
reason: input.reason,
|
||||
extraReasons: [
|
||||
`planner_instantiated_catalog_chain_template_${template.chain_id}`,
|
||||
...(input.extraReasons ?? [])
|
||||
]
|
||||
};
|
||||
}
|
||||
function hasEntity(meaning) {
|
||||
return (meaning?.explicit_entity_candidates?.length ?? 0) > 0;
|
||||
}
|
||||
@@ -306,60 +328,60 @@ function recipeFor(input) {
|
||||
const thinSurfaceRouteFamily = routeFamilyFromThinMetadataSurfaceInput(input);
|
||||
if (thinSurfaceRouteFamily === "document_evidence") {
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("document_evidence");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "document evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "document_evidence",
|
||||
chainSummary: "Ground the next checked document lane from the confirmed metadata surface, then fetch scoped document rows and probe coverage before answering.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_document_from_confirmed_metadata_surface_ref",
|
||||
chainSummary: "Ground the next checked document lane from the confirmed metadata surface, then fetch scoped document rows and probe coverage before answering.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (thinSurfaceRouteFamily === "movement_evidence") {
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("movement_evidence");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "movement evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "movement_evidence",
|
||||
chainSummary: "Ground the next checked movement lane from the confirmed metadata surface, then fetch scoped movement rows and probe coverage before answering.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_movement_from_confirmed_metadata_surface_ref",
|
||||
chainSummary: "Ground the next checked movement lane from the confirmed metadata surface, then fetch scoped movement rows and probe coverage before answering.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (thinSurfaceRouteFamily === "catalog_drilldown") {
|
||||
pushUnique(axes, "metadata_scope");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("catalog_drilldown");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["inspect_1c_metadata"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "catalog drilldown metadata evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "catalog_drilldown",
|
||||
chainSummary: "Drill deeper into the confirmed catalog-oriented metadata surface, inspect related metadata objects, and keep the next safe lane grounded in checked schema evidence.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_catalog_drilldown_from_confirmed_metadata_surface_ref",
|
||||
chainSummary: "Drill deeper into the confirmed catalog-oriented metadata surface, inspect related metadata objects, and keep the next safe lane grounded in checked schema evidence.",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (graphFactFamily === "value_flow") {
|
||||
if (dataNeedGraph?.comparison_need === "incoming_vs_outgoing" && !hasSubjectCandidates(dataNeedGraph)) {
|
||||
@@ -368,47 +390,45 @@ function recipeFor(input) {
|
||||
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
|
||||
pushUnique(axes, "calendar_month");
|
||||
}
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("value_flow_comparison");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["query_movements", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action,
|
||||
allowAggregateByAxis: false
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "bidirectional value-flow comparison evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "value_flow_comparison",
|
||||
chainSummary: "Query incoming and outgoing movements for the checked period and organization, compare the checked sides, and probe coverage before answering a bounded comparison.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_bidirectional_value_flow_comparison_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (dataNeedGraph?.ranking_need && !hasSubjectCandidates(dataNeedGraph)) {
|
||||
pushUnique(axes, "aggregate_axis");
|
||||
pushUnique(axes, "amount");
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("value_flow_ranking");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["query_movements", "aggregate_by_axis", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action,
|
||||
allowAggregateByAxis: true
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "ranked value-flow evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "value_flow_ranking",
|
||||
chainSummary: "Query scoped movements for the checked period and organization, aggregate checked amounts by counterparty, then probe coverage before answering a bounded ranking.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: dataNeedGraph.ranking_need === "bottom_asc"
|
||||
? "planner_selected_bottom_ranked_value_flow_from_data_need_graph"
|
||||
: "planner_selected_top_ranked_value_flow_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (openScopeTotalWithoutSubject) {
|
||||
pushUnique(axes, "organization");
|
||||
@@ -425,17 +445,17 @@ function recipeFor(input) {
|
||||
actionFamily: action,
|
||||
allowAggregateByAxis: true
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "organization-scoped value-flow evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "value_flow",
|
||||
chainSummary: "Query scoped movements for the checked period and organization without a preselected counterparty, aggregate checked amounts, then probe coverage before answering a bounded total.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
semanticDataNeed: "organization-scoped value-flow evidence",
|
||||
chainSummary: "Query scoped movements for the checked period and organization without a preselected counterparty, aggregate checked amounts, then probe coverage before answering a bounded total.",
|
||||
reason: requestedAggregationAxis === "month" || graphAggregation === "by_month"
|
||||
? "planner_selected_monthly_open_scope_value_flow_total_from_data_need_graph"
|
||||
: "planner_selected_open_scope_value_flow_total_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
pushUnique(axes, "aggregate_axis");
|
||||
pushUnique(axes, "amount");
|
||||
@@ -443,70 +463,68 @@ function recipeFor(input) {
|
||||
if (requestedAggregationAxis === "month" || graphAggregation === "by_month") {
|
||||
pushUnique(axes, "calendar_month");
|
||||
}
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("value_flow");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "aggregate_by_axis", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action,
|
||||
allowAggregateByAxis: true
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "counterparty value-flow evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "value_flow",
|
||||
chainSummary: "Resolve the business entity, query scoped movements, aggregate checked amounts, then probe coverage before answering.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: requestedAggregationAxis === "month" || graphAggregation === "by_month"
|
||||
? "planner_selected_monthly_value_flow_from_data_need_graph"
|
||||
: "planner_selected_value_flow_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (graphFactFamily === "activity_lifecycle") {
|
||||
pushUnique(axes, "document_date");
|
||||
pushUnique(axes, "coverage_target");
|
||||
pushUnique(axes, "evidence_basis");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("lifecycle");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage", "explain_evidence_basis"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "counterparty lifecycle evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "lifecycle",
|
||||
chainSummary: "Resolve the business entity, query supporting documents, probe coverage, then explain the evidence basis for the inferred activity window.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_lifecycle_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (graphFactFamily === "schema_surface") {
|
||||
pushUnique(axes, "metadata_scope");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("metadata_inspection");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["inspect_1c_metadata"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "1C metadata evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "metadata_inspection",
|
||||
chainSummary: "Inspect the 1C metadata surface first, then ground the next safe lane from confirmed schema evidence.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_metadata_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (graphFactFamily === "movement_evidence") {
|
||||
if (metadataScopedOpenLane) {
|
||||
pushUnique(axes, "organization");
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("movement_evidence");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["query_movements", "probe_coverage"],
|
||||
@@ -514,38 +532,38 @@ function recipeFor(input) {
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "movement evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "movement_evidence",
|
||||
chainSummary: "Keep the metadata-scoped movement lane, ask only for the remaining business scope, then fetch scoped movement rows and probe coverage without pretending there is a grounded counterparty.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_metadata_scoped_movement_from_data_need_graph",
|
||||
chainSummary: "Keep the metadata-scoped movement lane, ask only for the remaining business scope, then fetch scoped movement rows and probe coverage without pretending there is a grounded counterparty.",
|
||||
semanticDataNeed: template.semantic_data_need,
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("movement_evidence");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["resolve_entity_reference", "query_movements", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "movement evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "movement_evidence",
|
||||
chainSummary: "Resolve the business entity, fetch scoped movement rows, and probe coverage without pretending to have a full movement universe.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_movement_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (graphFactFamily === "document_evidence") {
|
||||
if (metadataScopedOpenLane) {
|
||||
pushUnique(axes, "organization");
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("document_evidence");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["query_documents", "probe_coverage"],
|
||||
@@ -553,55 +571,53 @@ function recipeFor(input) {
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "document evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "document_evidence",
|
||||
chainSummary: "Keep the metadata-scoped document lane, ask only for the remaining business scope, then fetch scoped document rows and probe coverage without pretending there is a grounded counterparty.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_metadata_scoped_document_from_data_need_graph",
|
||||
chainSummary: "Keep the metadata-scoped document lane, ask only for the remaining business scope, then fetch scoped document rows and probe coverage without pretending there is a grounded counterparty.",
|
||||
semanticDataNeed: template.semantic_data_need,
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("document_evidence");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "document evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "document_evidence",
|
||||
chainSummary: "Resolve the business entity, fetch scoped document rows, and probe coverage before stating the checked document evidence.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: "planner_selected_document_from_data_need_graph",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (graphFactFamily === "entity_grounding" || (!graphFactFamily && (dataNeedGraph?.subject_candidates.length ?? 0) > 0)) {
|
||||
pushUnique(axes, "business_entity");
|
||||
pushUnique(axes, "coverage_target");
|
||||
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)("entity_resolution");
|
||||
const primitiveSelection = selectPrimitivesFromGraphAndCatalog({
|
||||
dataNeedGraph,
|
||||
fallbackPrimitives: ["search_business_entity", "resolve_entity_reference", "probe_coverage"],
|
||||
fallbackPrimitives: template.fallback_primitives,
|
||||
requiredAxes: axes,
|
||||
metadataSurface: input.metadataSurface,
|
||||
actionFamily: action
|
||||
});
|
||||
return {
|
||||
semanticDataNeed: "entity discovery evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "entity_resolution",
|
||||
chainSummary: "Search candidate business entities, resolve the most relevant 1C reference, and prove whether the entity grounding is stable enough for the next probe.",
|
||||
primitives: primitiveSelection.primitives,
|
||||
axes,
|
||||
primitives: primitiveSelection.primitives,
|
||||
reason: graphAction === "search_business_entity"
|
||||
? "planner_selected_entity_resolution_from_data_need_graph"
|
||||
: "planner_selected_entity_resolution_recipe",
|
||||
extraReasons: primitiveSelection.reasonCodes
|
||||
};
|
||||
});
|
||||
}
|
||||
if (includesAny(combined, ["metadata_lane_choice_clarification", "resolve_next_lane"])) {
|
||||
pushUnique(axes, "lane_family_choice");
|
||||
@@ -621,83 +637,64 @@ function recipeFor(input) {
|
||||
if (requestedAggregationAxis === "month") {
|
||||
pushUnique(axes, "calendar_month");
|
||||
}
|
||||
return {
|
||||
semanticDataNeed: "counterparty value-flow evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "value_flow",
|
||||
chainSummary: "Resolve the business entity, query scoped movements, aggregate checked amounts, then probe coverage before answering.",
|
||||
primitives: ["resolve_entity_reference", "query_movements", "aggregate_by_axis", "probe_coverage"],
|
||||
axes,
|
||||
reason: requestedAggregationAxis === "month"
|
||||
? "planner_selected_monthly_value_flow_recipe"
|
||||
: "planner_selected_value_flow_recipe"
|
||||
};
|
||||
});
|
||||
}
|
||||
if (includesAny(combined, ["lifecycle", "activity", "duration", "age"])) {
|
||||
pushUnique(axes, "document_date");
|
||||
pushUnique(axes, "coverage_target");
|
||||
pushUnique(axes, "evidence_basis");
|
||||
return {
|
||||
semanticDataNeed: "counterparty lifecycle evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "lifecycle",
|
||||
chainSummary: "Resolve the business entity, query supporting documents, probe coverage, then explain the evidence basis for the inferred activity window.",
|
||||
primitives: ["resolve_entity_reference", "query_documents", "probe_coverage", "explain_evidence_basis"],
|
||||
axes,
|
||||
reason: "planner_selected_lifecycle_recipe"
|
||||
};
|
||||
});
|
||||
}
|
||||
if (includesAny(combined, ["metadata", "schema", "catalog"])) {
|
||||
pushUnique(axes, "metadata_scope");
|
||||
return {
|
||||
semanticDataNeed: "1C metadata evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "metadata_inspection",
|
||||
chainSummary: "Inspect the 1C metadata surface first, then ground the next safe lane from confirmed schema evidence.",
|
||||
primitives: ["inspect_1c_metadata"],
|
||||
axes,
|
||||
reason: "planner_selected_metadata_recipe"
|
||||
};
|
||||
});
|
||||
}
|
||||
if (includesAny(combined, ["movement", "movements", "bank_operations", "movement_evidence", "list_movements"])) {
|
||||
pushUnique(axes, "coverage_target");
|
||||
return {
|
||||
semanticDataNeed: "movement evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "movement_evidence",
|
||||
chainSummary: "Resolve the business entity, fetch scoped movement rows, and probe coverage without pretending to have a full movement universe.",
|
||||
primitives: ["resolve_entity_reference", "query_movements", "probe_coverage"],
|
||||
axes,
|
||||
reason: "planner_selected_movement_recipe"
|
||||
};
|
||||
});
|
||||
}
|
||||
if (includesAny(combined, ["document", "documents"])) {
|
||||
pushUnique(axes, "coverage_target");
|
||||
return {
|
||||
semanticDataNeed: "document evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "document_evidence",
|
||||
chainSummary: "Resolve the business entity, fetch scoped document rows, and probe coverage before stating the checked document evidence.",
|
||||
primitives: ["resolve_entity_reference", "query_documents", "probe_coverage"],
|
||||
axes,
|
||||
reason: "planner_selected_document_recipe"
|
||||
};
|
||||
});
|
||||
}
|
||||
if (hasEntity(meaning)) {
|
||||
pushUnique(axes, "business_entity");
|
||||
pushUnique(axes, "coverage_target");
|
||||
return {
|
||||
semanticDataNeed: "entity discovery evidence",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "entity_resolution",
|
||||
chainSummary: "Search candidate business entities, resolve the most relevant 1C reference, and prove whether the entity grounding is stable enough for the next probe.",
|
||||
primitives: ["search_business_entity", "resolve_entity_reference", "probe_coverage"],
|
||||
axes,
|
||||
reason: "planner_selected_entity_resolution_recipe"
|
||||
};
|
||||
});
|
||||
}
|
||||
return {
|
||||
semanticDataNeed: "unclassified 1C discovery need",
|
||||
return recipeFromCatalogChainTemplate({
|
||||
chainId: "metadata_inspection",
|
||||
semanticDataNeed: "unclassified 1C discovery need",
|
||||
chainSummary: "Start with metadata inspection instead of guessing a deeper fact route when the business need is still under-specified.",
|
||||
primitives: ["inspect_1c_metadata"],
|
||||
axes,
|
||||
reason: "planner_selected_clarification_recipe"
|
||||
};
|
||||
});
|
||||
}
|
||||
function statusFrom(plan, review) {
|
||||
if (plan.plan_status === "blocked" || review.review_status === "catalog_blocked") {
|
||||
|
||||
Reference in New Issue
Block a user