Planner Autonomy: закрепить bounded inference и semantic bridges

This commit is contained in:
2026-05-01 12:53:21 +03:00
parent 3634404b1c
commit c7c85e9b42
26 changed files with 3496 additions and 55 deletions
@@ -283,13 +283,13 @@ const CHAIN_TEMPLATES = [
},
{
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.",
semantic_data_need: "counterparty lifecycle evidence with bounded activity-window inference",
chain_summary: "Resolve the business entity, query supporting documents, probe coverage, then explain the evidence basis for the inferred activity window without presenting it as legal registration age.",
fallback_primitives: ["resolve_entity_reference", "query_documents", "probe_coverage", "explain_evidence_basis"],
base_required_axes: ["document_date", "coverage_target", "evidence_basis"],
base_required_axes: ["document_date", "coverage_target", "evidence_basis", "activity_window", "legal_fact_boundary"],
supported_fact_families: ["activity_lifecycle"],
supported_action_families: ["activity_duration"],
planning_tags: ["document", "explanation", "coverage"],
planning_tags: ["document", "explanation", "coverage", "bounded_inference", "activity_window", "legal_fact_boundary"],
safe_for_model_planning: true,
requires_evidence_gate: true
}
@@ -1596,8 +1596,8 @@ function buildLifecycleConfirmedFacts(result, counterparty) {
}
return [
counterparty
? `1C activity rows were found for counterparty ${counterparty}`
: "1C activity rows were found for the requested counterparty scope"
? `1C activity rows were found for counterparty ${counterparty}; matched_rows=${result.matched_rows}`
: `1C activity rows were found for the requested counterparty scope; matched_rows=${result.matched_rows}`
];
}
function checkedCounterpartySuffixRu(counterparty) {
@@ -1667,7 +1667,15 @@ function buildLifecycleInferredFacts(result) {
if (result.error || result.fetched_rows <= 0) {
return [];
}
return ["Business activity duration may be inferred from first and latest confirmed 1C activity rows"];
const period = deriveActivityPeriod(result);
if (!period) {
return ["Business activity duration may be inferred only when confirmed 1C activity row dates are available"];
}
return [
"Business activity duration may be inferred from first and latest confirmed 1C activity rows",
`Activity window is bounded by first=${period.first_activity_date}, latest=${period.latest_activity_date}, matched_rows=${period.matched_rows}`,
"Activity-window inference is not legal registration age"
];
}
function buildDocumentInferredFacts(result, counterparty, periodScope) {
if (result.error || result.fetched_rows <= 0) {
@@ -1707,7 +1715,7 @@ function buildValueFlowInferredFacts(derived) {
facts.push("Counterparty value-flow total was calculated from confirmed 1C movement rows");
}
if (derived.coverage_recovered_by_period_chunking && derived.period_chunking_granularity === "month") {
facts.push("Requested period coverage was recovered through monthly 1C value-flow probes after the broad probe hit the row limit");
facts.push("Requested period coverage was recovered through monthly 1C value-flow probes");
}
if (derived.aggregation_axis === "month" && derived.monthly_breakdown.length > 0) {
facts.push("Counterparty monthly value-flow breakdown was grouped by month over confirmed 1C movement rows");
@@ -1720,7 +1728,7 @@ function buildRankedValueFlowInferredFacts(derived) {
}
const facts = ["Counterparty ranking was calculated from confirmed 1C movement rows grouped by counterparty"];
if (derived.coverage_recovered_by_period_chunking && derived.period_chunking_granularity === "month") {
facts.push("Requested period coverage for counterparty ranking was recovered through monthly 1C probes after a broad probe hit the row limit");
facts.push("Requested period coverage for counterparty ranking was recovered through monthly 1C probes");
}
return facts;
}
@@ -1730,7 +1738,7 @@ function buildBidirectionalValueFlowInferredFacts(derived) {
}
const facts = ["Counterparty net value-flow was calculated as incoming confirmed 1C rows minus outgoing confirmed 1C rows"];
if (derived.coverage_recovered_by_period_chunking && derived.period_chunking_granularity === "month") {
facts.push("Requested period coverage for bidirectional value-flow was recovered through monthly 1C side probes after a broad probe hit the row limit");
facts.push("Requested period coverage for bidirectional value-flow was recovered through monthly 1C side probes");
}
if (derived.aggregation_axis === "month" && derived.monthly_breakdown.length > 0) {
facts.push("Counterparty monthly net value-flow breakdown was grouped by month over confirmed incoming and outgoing 1C rows");
@@ -1738,7 +1746,10 @@ function buildBidirectionalValueFlowInferredFacts(derived) {
return facts;
}
function buildLifecycleUnknownFacts() {
return ["Legal registration date is not proven by this MCP discovery pilot"];
return [
"Legal registration date is not proven by this MCP discovery pilot",
"Business activity before the first confirmed 1C activity row is not proven by this MCP discovery pilot"
];
}
function buildDocumentUnknownFacts(periodScope, counterparty) {
return [
@@ -1753,7 +1764,7 @@ function buildMovementUnknownFacts(periodScope, counterparty) {
function buildValueFlowUnknownFacts(periodScope, direction, derived) {
const unknownFacts = [];
if (derived?.coverage_limited_by_probe_limit) {
unknownFacts.push("Complete requested-period coverage is not proven because the MCP discovery probe row limit was reached");
unknownFacts.push("Complete requested-period coverage is not proven by the available checked rows");
}
if (direction === "outgoing_supplier_payout") {
unknownFacts.push(periodScope
@@ -1769,7 +1780,7 @@ function buildValueFlowUnknownFacts(periodScope, direction, derived) {
function buildRankedValueFlowUnknownFacts(periodScope, derived) {
const unknownFacts = [];
if (derived?.coverage_limited_by_probe_limit) {
unknownFacts.push("Complete requested-period ranking coverage is not proven because the MCP discovery probe row limit was reached");
unknownFacts.push("Complete requested-period ranking coverage is not proven by the available checked rows");
}
unknownFacts.push(periodScope
? "Full ranking outside the checked period is not proven by this MCP discovery pilot"
@@ -1779,7 +1790,7 @@ function buildRankedValueFlowUnknownFacts(periodScope, derived) {
function buildBidirectionalValueFlowUnknownFacts(periodScope, derived) {
const unknownFacts = [];
if (derived?.coverage_limited_by_probe_limit) {
unknownFacts.push("Complete requested-period coverage for bidirectional value-flow is not proven because at least one MCP discovery probe row limit was reached");
unknownFacts.push("Complete requested-period coverage for bidirectional value-flow is not proven by the available checked rows");
}
unknownFacts.push(periodScope
? "Full bidirectional value-flow outside the checked period is not proven by this MCP discovery pilot"
@@ -40,6 +40,10 @@ function pushAllUnique(target, values) {
pushUnique(target, value);
}
}
const LIFECYCLE_BOUNDED_INFERENCE_REASON_CODES = [
"planner_lifecycle_bounded_activity_window_template",
"planner_lifecycle_legal_fact_boundary_required"
];
function recipeFromCatalogChainTemplate(input) {
const template = (0, assistantMcpCatalogIndex_1.getAssistantMcpCatalogChainTemplate)(input.chainId);
const axes = [...input.axes];
@@ -523,7 +527,7 @@ function recipeFor(input) {
axes,
primitives: primitiveSelection.primitives,
reason: "planner_selected_lifecycle_from_data_need_graph",
extraReasons: primitiveSelection.reasonCodes
extraReasons: [...primitiveSelection.reasonCodes, ...LIFECYCLE_BOUNDED_INFERENCE_REASON_CODES]
});
}
if (graphFactFamily === "schema_surface") {
@@ -676,7 +680,8 @@ function recipeFor(input) {
return recipeFromCatalogChainTemplate({
chainId: "lifecycle",
axes,
reason: "planner_selected_lifecycle_recipe"
reason: "planner_selected_lifecycle_recipe",
extraReasons: LIFECYCLE_BOUNDED_INFERENCE_REASON_CODES
});
}
if (includesAny(combined, ["metadata", "schema", "catalog"])) {
@@ -245,6 +245,24 @@ function localizeLine(value) {
if (/^Requested period coverage for bidirectional value-flow was recovered through monthly 1C side probes after a broad probe hit the row limit$/i.test(value)) {
return "Покрытие запрошенного периода по двустороннему денежному потоку восстановлено помесячными проверками 1С после того, как общая выборка уперлась в лимит строк хотя бы по одной стороне.";
}
if (/^Requested period coverage was recovered through monthly 1C value-flow probes$/i.test(value)) {
return "Покрытие запрошенного периода восстановлено помесячными проверками 1С.";
}
if (/^Requested period coverage for counterparty ranking was recovered through monthly 1C probes$/i.test(value)) {
return "Покрытие запрошенного периода для рейтинга контрагентов восстановлено помесячными проверками 1С.";
}
if (/^Requested period coverage for bidirectional value-flow was recovered through monthly 1C side probes$/i.test(value)) {
return "Покрытие запрошенного периода по двустороннему денежному потоку восстановлено помесячными проверками 1С.";
}
if (/^Complete requested-period coverage is not proven by the available checked rows$/i.test(value)) {
return "Полное покрытие запрошенного периода не подтверждено доступными проверенными строками.";
}
if (/^Complete requested-period ranking coverage is not proven by the available checked rows$/i.test(value)) {
return "Полное покрытие рейтинга за запрошенный период не подтверждено доступными проверенными строками.";
}
if (/^Complete requested-period coverage for bidirectional value-flow is not proven by the available checked rows$/i.test(value)) {
return "Полное покрытие запрошенного периода по двустороннему денежному потоку не подтверждено доступными проверенными строками.";
}
return value;
}
function section(title, lines) {
@@ -514,6 +514,9 @@ function hasLifecycleSignal(text) {
function hasValueFlowSignal(text) {
return /(?:оборот|выручк|оплат|плат[её]ж|заплат|перечисл|списан|расход|исходящ|входящ|получ(?:ил|ено|ен)|поступил|поступлен|денежн[а-яёa-z0-9_-]*\s+поток|(?<!\p{L})заработ(?:ал|али|ало|аем|ает|ать|ано|ок)(?!\p{L})|supplier|value[-\s]?flow|turnover|revenue|payment|payout|outflow|cash\s+flow|\bearn(?:ed|ing|ings)?\b)/iu.test(text);
}
function hasValueFlowAggregateQuestionSignal(text) {
return /(?:\u0441\u043a\u043e\u043b\u044c\u043a\u043e|\u0441\u0443\u043c\u043c|\u0438\u0442\u043e\u0433|\u0440\u0430\u0441\u0441\u0447\u0438\u0442|\u043d\u0435\u0442\u0442\u043e|\u0441\u0430\u043b\u044c\u0434\u043e|how\s+much|total|sum|net)/iu.test(text);
}
function hasPayoutSignal(text) {
return /(?:\bмы\s+(?:за)?плат|(?:за)?платил|оплатил|перечисл|списан|расход|поставщик|исходящ|supplier|payout|outflow|paid\s+to|payment\s+to)/iu.test(text);
}
@@ -836,6 +839,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
hasMetadataSignal(rawText);
const rawEntityResolutionSignal = !rawLifecycleSignal && !rawValueFlowSignal && !rawMetadataSignal && hasEntityResolutionSignal(rawText);
const rawPayoutSignal = rawValueFlowSignal && !rawBidirectionalValueFlowSignal && hasPayoutSignal(rawText);
const rawValueFlowAggregateQuestionSignal = rawValueFlowSignal && hasValueFlowAggregateQuestionSignal(rawText);
const monthlyAggregationSignal = hasMonthlyAggregationSignal(rawText);
const rawAllTimeScopeSignal = hasAllTimeScopeHint(rawText);
const explicitDateScopeLiteralDetected = hasExplicitDateScopeLiteral(rawText);
@@ -853,6 +857,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
const rawAction = toNonEmptyString(assistantTurnMeaning?.asked_action_family);
const rawAggregationAxis = toNonEmptyString(assistantTurnMeaning?.asked_aggregation_axis);
const unsupported = toNonEmptyString(assistantTurnMeaning?.unsupported_but_understood_family);
const broadBusinessEvaluationUnsupported = unsupported === "broad_business_evaluation";
const explicitIntentCandidate = toNonEmptyString(assistantTurnMeaning?.explicit_intent_candidate);
const currentTurnDocumentLaneSignal = rawAction === "list_documents";
const currentTurnMovementLaneSignal = rawAction === "list_movements";
@@ -1179,7 +1184,7 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
: semanticNeedFor({
domain: rawDomain ?? seededDomain,
action: rawAction ?? seededAction,
unsupported: unsupported ?? seededUnsupported,
unsupported: broadBusinessEvaluationUnsupported ? seededUnsupported : unsupported ?? seededUnsupported,
lifecycleSignal,
valueFlowSignal,
metadataSignal: rawMetadataSignal || effectiveMetadataFollowupSeedApplicable,
@@ -1444,8 +1449,13 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
if (turnMeaning.stale_replay_forbidden) {
cleanTurnMeaning.stale_replay_forbidden = true;
}
const currentTurnValueFlowExactOverrideApplicable = Boolean(valueFlowSignal &&
explicitIntentCandidate &&
rawValueFlowAggregateQuestionSignal &&
semanticDataNeed &&
(entityCandidates.length > 0 || explicitOrganizationScope || openScopeValueFlowWithoutResolvedCounterparty));
const runDiscovery = shouldRunDiscovery({
unsupported: unsupported ?? seededUnsupported,
unsupported: broadBusinessEvaluationUnsupported ? seededUnsupported : unsupported ?? seededUnsupported,
lifecycleSignal,
valueFlowSignal,
metadataSignal: rawMetadataSignal || effectiveMetadataFollowupSeedApplicable,
@@ -1465,7 +1475,8 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
metadataAmbiguityLaneClarificationApplicable ||
metadataGroundedMovementLaneApplicable ||
metadataGroundedDocumentLaneApplicable ||
groundedValueFlowFollowupApplicable
groundedValueFlowFollowupApplicable ||
currentTurnValueFlowExactOverrideApplicable
});
const hasTurnMeaning = Object.keys(cleanTurnMeaning).length > 0;
const sourceSignal = rawEntitySearchOverridesStaleScope
@@ -1576,6 +1587,9 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
if (groundedValueFlowFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_grounded_value_flow_followup");
}
if (currentTurnValueFlowExactOverrideApplicable) {
pushReason(reasonCodes, "mcp_discovery_current_turn_value_flow_overrides_supported_exact");
}
if (documentEvidenceGroundedMovementFollowupApplicable) {
pushReason(reasonCodes, "mcp_discovery_document_evidence_grounded_movement_followup");
}
@@ -1606,6 +1620,9 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
if (unsupported) {
pushReason(reasonCodes, "mcp_discovery_unsupported_but_understood_turn");
}
if (broadBusinessEvaluationUnsupported) {
pushReason(reasonCodes, "mcp_discovery_broad_business_evaluation_kept_in_living_chat");
}
if (!(valueFlowOrganizationStaysScope && normalizedPredecomposeCounterparty === explicitOrganizationScope) &&
normalizedPredecomposeCounterparty) {
pushReason(reasonCodes, "mcp_discovery_counterparty_from_predecompose");