Planner Autonomy: закрепить bounded inference и semantic bridges
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
+21
-10
@@ -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"])) {
|
||||
|
||||
+18
@@ -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) {
|
||||
|
||||
+20
-3
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user