Post-F: закрепить open-scope и bidirectional value-flow integrity
This commit is contained in:
@@ -1954,6 +1954,31 @@ function unicodeBridgeResolution(
|
||||
return { intent, confidence, reasons: [reason] };
|
||||
}
|
||||
|
||||
function hasBidirectionalValueFlowComparisonSignal(text: string): boolean {
|
||||
const normalized = String(text ?? "").trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasIncomingCue = /(?:\u0432\u0445\u043e\u0434\u044f\u0449|\u043f\u043e\u0441\u0442\u0443\u043f|\u043f\u043e\u043b\u0443\u0447|inflow|incoming)/iu.test(
|
||||
normalized
|
||||
);
|
||||
const hasOutgoingCue =
|
||||
/(?:\u0438\u0441\u0445\u043e\u0434\u044f\u0449|\u0441\u043f\u0438\u0441\u0430\u043d|\u0437\u0430\u043f\u043b\u0430\u0442|\u043f\u043b\u0430\u0442\u0438\u043b|\u043e\u043f\u043b\u0430\u0442|outflow|outgoing|payout)/iu.test(
|
||||
normalized
|
||||
);
|
||||
const hasComparisonCue =
|
||||
/(?:\u0431\u043e\u043b\u044c\u0448|\u043c\u0435\u043d\u044c\u0448|\u0441\u0440\u0430\u0432|\u0438\u043b\u0438|\u043d\u0435\u0442\u0442\u043e|\u0441\u0430\u043b\u044c\u0434\u043e|vs|versus)/iu.test(
|
||||
normalized
|
||||
);
|
||||
const hasValueFlowCue =
|
||||
/(?:\u0434\u0435\u043d\u044c\u0433|\u0434\u0435\u043d\u0435\u0433|\u0434\u0435\u043d\u0435\u0436|\u043f\u043e\u0442\u043e\u043a|\u043e\u0431\u043e\u0440\u043e\u0442|money|cash|flow)/iu.test(
|
||||
normalized
|
||||
);
|
||||
|
||||
return hasIncomingCue && hasOutgoingCue && hasComparisonCue && hasValueFlowCue;
|
||||
}
|
||||
|
||||
function resolveUnicodeAddressIntentBridge(text: string): AddressIntentResolution | null {
|
||||
const normalized = String(text ?? "").trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
@@ -2006,6 +2031,14 @@ function resolveUnicodeAddressIntentBridge(text: string): AddressIntentResolutio
|
||||
normalized
|
||||
);
|
||||
|
||||
if (hasBidirectionalValueFlowComparisonSignal(normalized)) {
|
||||
return unicodeBridgeResolution(
|
||||
"unknown",
|
||||
"high",
|
||||
"unicode_bidirectional_value_flow_deferred_to_discovery"
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
/(?:за\s+какие\s+годы|диапазон\s+лет|покрыт(?:ие|ый)\s+период|какой\s+год.*актив|какой\s+месяц.*актив|год.*пассив|месяц.*пассив|минимальн.*док|минимальн.*операц|месяц[\s-]*пик|profile\s+period|top\s*year|top\s*month)/iu.test(
|
||||
normalized
|
||||
|
||||
@@ -56,6 +56,7 @@ import {
|
||||
resolveShadowRouteIntent
|
||||
} from "./addressCapabilityPolicy";
|
||||
import { evaluateAddressRouteExpectation, type AddressRouteExpectationAudit } from "./addressRouteExpectations";
|
||||
import { repairAddressMojibakeText } from "./addressTextRepair";
|
||||
import {
|
||||
mergeKnownOrganizations,
|
||||
normalizeOrganizationScopeSearchText,
|
||||
@@ -1994,6 +1995,31 @@ function isOrganizationScopedInventoryIntent(intent: AddressIntent): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function isOrganizationScopedValueFlowIntent(intent: AddressIntent): boolean {
|
||||
return intent === "customer_revenue_and_payments" || intent === "supplier_payouts_profile";
|
||||
}
|
||||
|
||||
function hasExplicitSingleOrganizationValueFlowScopeRequest(userMessage: string): boolean {
|
||||
const raw = String(userMessage ?? "").toLowerCase();
|
||||
const repaired = repairAddressMojibakeText(raw).toLowerCase();
|
||||
const normalized = `${raw} ${repaired}`;
|
||||
const hasOrganizationCue = /(?:организац|компани|фирм|контур|organization|company)/iu.test(normalized);
|
||||
if (!hasOrganizationCue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasSingleOrganizationCue =
|
||||
/(?:по\s+одн(?:ой|у)\s+(?:организац|компани|фирм)|одн(?:ой|у)\s+(?:организац|компани|фирм)|one\s+(?:organization|company))/iu.test(
|
||||
normalized
|
||||
);
|
||||
const hasClarificationCue =
|
||||
/(?:если[^.?!]*(?:нужн|надо|потреб)[^.?!]*(?:организац|компани|фирм)|(?:уточн|спрос)[^.?!]*(?:организац|компани|фирм|ее|её))/iu.test(
|
||||
normalized
|
||||
);
|
||||
|
||||
return hasSingleOrganizationCue || hasClarificationCue;
|
||||
}
|
||||
|
||||
function shouldDeferInventoryOrganizationClarification(
|
||||
intent: AddressIntent,
|
||||
filters: AddressFilterSet,
|
||||
@@ -3480,6 +3506,29 @@ export class AddressQueryService {
|
||||
});
|
||||
const knownOrganizations = mergeKnownOrganizations(options.knownOrganizations ?? []);
|
||||
const activeOrganization = normalizeOrganizationScopeValue(options.activeOrganization ?? null);
|
||||
if (
|
||||
isOrganizationScopedValueFlowIntent(intent.intent) &&
|
||||
hasExplicitSingleOrganizationValueFlowScopeRequest(userMessage) &&
|
||||
!resolvedOrganizationFromMessage
|
||||
) {
|
||||
const clarificationFilters: AddressFilterSet = { ...filters.extracted_filters };
|
||||
delete clarificationFilters.organization;
|
||||
return buildOrganizationClarificationExecutionResult({
|
||||
mode,
|
||||
shape,
|
||||
intent,
|
||||
filters: clarificationFilters,
|
||||
organizations: knownOrganizations,
|
||||
reasons: [...baseReasons, "organization_clarification_required_from_explicit_value_flow_scope"],
|
||||
semanticFrame,
|
||||
capabilityAudit: buildCapabilityAudit(intent.intent),
|
||||
shadowRouteAudit: buildShadowRouteAudit({
|
||||
intent: intent.intent,
|
||||
requestedResultMode: resolveAddressRequestedResultMode(intent.intent, filters.extracted_filters, semanticFrame) ?? undefined,
|
||||
filters: filters.extracted_filters
|
||||
})
|
||||
});
|
||||
}
|
||||
if (
|
||||
isOrganizationScopedInventoryIntent(intent.intent) &&
|
||||
!toNonEmptyFilterValue(filters.extracted_filters.organization) &&
|
||||
|
||||
Reference in New Issue
Block a user