Закрепить дату складского supplier-overlap follow-up

This commit is contained in:
2026-06-03 12:26:08 +03:00
parent f0b84822d3
commit fdd04abbde
9 changed files with 500 additions and 3 deletions
@@ -534,6 +534,7 @@ function shouldPreferRawFollowupMessage(userMessage, addressInputMessage, carryo
const previousIntent = toNonEmptyString(followupContext?.previous_intent);
const rootIntent = toNonEmptyString(followupContext?.root_intent);
const previousAnchorType = toNonEmptyString(followupContext?.previous_anchor_type);
const previousFilters = toRecordObject(followupContext?.previous_filters);
const hasReferentialDocumentExclusionFollowupCue = /(?:\u043a\u0440\u043e\u043c\u0435|\u043f\u043e\u043c\u0438\u043c\u043e)\s+(?:\u044d\u0442\u043e\u0433\u043e|\u044d\u0442\u043e\u0439|\u044d\u0442\u043e\u0442|\u044d\u0442\u0443|\u044d\u0442\u0438\u0445)(?:\s+(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430|\u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0430|\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442\u0430))?/iu.test(rawMessage);
const hasInventoryItemCarryover = previousAnchorType === "item" && isInventorySelectedObjectOrRootIntent(previousIntent);
const hasInventoryFrameCarryover = isInventorySelectedObjectOrRootIntent(previousIntent) ||
@@ -543,10 +544,11 @@ function shouldPreferRawFollowupMessage(userMessage, addressInputMessage, carryo
const hasInventoryMarginRankingAccountCorrection = hasInventoryMarginRankingCarryover &&
[rawMessage, canonicalMessage].some((message) => hasInventoryMarginRankingAccountCorrectionCue(message));
const hasDocumentCarryover = previousIntent === "list_documents_by_counterparty" || previousIntent === "list_documents_by_contract";
const hasCounterpartyCarryover = previousAnchorType === "counterparty" || Boolean(toNonEmptyString(previousFilters?.counterparty));
if (mode === "unsupported" && intent === "unknown") {
return true;
}
if (hasDocumentCarryover && hasReferentialDocumentExclusionFollowupCue) {
if ((hasDocumentCarryover || hasCounterpartyCarryover) && hasReferentialDocumentExclusionFollowupCue) {
return true;
}
if (hasSameDateFollowupSignal(rawMessage) && hasExplicitCurrentDateSignal(canonicalMessage)) {
@@ -27,6 +27,25 @@ function createAssistantTransitionPolicy(deps) {
return wantsFoundRows || account41Not01;
});
}
function hasInventorySupplierOverlapRootFollowupSignal(userMessage, alternateMessage = null, sourceIntentHint = null, hasInventoryRootFrame = false) {
if (!hasInventoryRootFrame ||
(sourceIntentHint !== "inventory_on_hand_as_of_date" &&
sourceIntentHint !== "inventory_supplier_stock_overlap_as_of_date")) {
return false;
}
return [userMessage, alternateMessage]
.filter((value) => deps.toNonEmptyString(value))
.map((value) => normalizeFollowupText(value))
.some((normalized) => {
if (!normalized) {
return false;
}
const hasSupplierCue = /(?:\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a|supplier|vendor|\u0443\s+\u043a\u0430\u043a\u043e\u0433\u043e|\u0443\s+\u043a\u043e\u0433\u043e|\u043f\u043e\s+\u043a\u0430\u043a\u043e\u043c\u0443)/iu.test(normalized);
const hasStockCue = /(?:\u043e\u0441\u0442\u0430\u0442|\u0441\u043a\u043b\u0430\u0434|\u0442\u043e\u0432\u0430\u0440|\u043f\u043e\u0437\u0438\u0446|\u043b\u0435\u0436|\u0432\u0438\u0441|\u0442\u0435\u043a\u0443\u0449)/iu.test(normalized);
const hasPurchaseCue = /(?:\u043a\u0443\u043f\u0438\u043b|\u043a\u0443\u043f\u043b\u0435\u043d|\u043f\u043e\u043a\u0443\u043f|\u0437\u0430\u043a\u0443\u043f|\u043f\u043e\u0441\u0442\u0443\u043f\u043b|purchase|bought)/iu.test(normalized);
return hasSupplierCue && (hasStockCue || hasPurchaseCue);
});
}
function hasSamePeriodReferenceCue(...values) {
return values
.map((value) => normalizeFollowupText(value))
@@ -866,6 +885,7 @@ function createAssistantTransitionPolicy(deps) {
const hasInventoryRootRestatementAlternate = deps.toNonEmptyString(alternateMessage)
? hasInventoryRootRestatementLikeSignal(String(alternateMessage ?? ""), sourceIntentHint, Boolean(recentInventoryRootFrame))
: false;
const hasInventorySupplierOverlapRootFollowup = hasInventorySupplierOverlapRootFollowupSignal(userMessage, alternateMessage, sourceIntentHint, Boolean(recentInventoryRootFrame));
const hasExplicitInventorySameDatePivotPrimary = hasExplicitInventorySameDatePivotSignal(userMessage);
const hasExplicitInventorySameDatePivotAlternate = deps.toNonEmptyString(alternateMessage)
? hasExplicitInventorySameDatePivotSignal(String(alternateMessage ?? ""))
@@ -882,6 +902,7 @@ function createAssistantTransitionPolicy(deps) {
hasInventoryRootTemporalFollowupAlternate ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
hasInventorySupplierOverlapRootFollowup ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
@@ -907,6 +928,7 @@ function createAssistantTransitionPolicy(deps) {
hasInventoryRootTemporalFollowupAlternate ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
hasInventorySupplierOverlapRootFollowup ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
@@ -938,6 +960,7 @@ function createAssistantTransitionPolicy(deps) {
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!hasInventorySupplierOverlapRootFollowup &&
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!selectedCounterpartyDocumentFollowupSignal &&
@@ -955,6 +978,7 @@ function createAssistantTransitionPolicy(deps) {
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!hasInventorySupplierOverlapRootFollowup &&
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!selectedCounterpartyDocumentFollowupSignal &&
@@ -1037,6 +1061,7 @@ function createAssistantTransitionPolicy(deps) {
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!hasInventorySupplierOverlapRootFollowup &&
!inventoryShortFollowupPrimary &&
!inventoryShortFollowupAlternate &&
!businessOverviewBoundaryFollowupPrimary &&
@@ -1104,6 +1129,7 @@ function createAssistantTransitionPolicy(deps) {
inventoryMarginRankingFollowup ||
explicitSummaryBundleReuseSignal ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventorySupplierOverlapRootFollowup ||
mcpDiscoveryOrganizationClarificationContinuation;
hasAlternateFollowupSignal = deps.toNonEmptyString(alternateMessage)
? deps.hasAddressFollowupContextSignal(alternateMessage) ||
@@ -1116,6 +1142,7 @@ function createAssistantTransitionPolicy(deps) {
inventoryMarginRankingFollowup ||
explicitSummaryBundleReuseSignal ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventorySupplierOverlapRootFollowup ||
mcpDiscoveryOrganizationClarificationContinuation
: false;
hasStrongFollowupReference =
@@ -1129,6 +1156,7 @@ function createAssistantTransitionPolicy(deps) {
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventorySupplierOverlapRootFollowup ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
@@ -1261,7 +1289,8 @@ function createAssistantTransitionPolicy(deps) {
}
const predecomposeIntent = deps.toNonEmptyString(llmPreDecomposeMeta?.predecomposeContract?.intent);
const carryoverTargetIntentPreview = explicitIntent ?? predecomposeIntent ?? previousIntent;
if (shouldClearStaleDateScopeForCounterpartyDocsRoot(carryoverTargetIntentPreview, sourceIntentHint, userMessage, alternateMessage)) {
if (!selectedCounterpartyDocumentFollowupSignal &&
shouldClearStaleDateScopeForCounterpartyDocsRoot(carryoverTargetIntentPreview, sourceIntentHint, userMessage, alternateMessage)) {
delete previousFilters.as_of_date;
delete previousFilters.period_from;
delete previousFilters.period_to;
@@ -1280,6 +1309,7 @@ function createAssistantTransitionPolicy(deps) {
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventorySupplierOverlapRootFollowup ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
hasSelectedObjectInventorySignalPrimary ||
@@ -765,6 +765,7 @@ function shouldPreferRawFollowupMessage(
const previousIntent = toNonEmptyString(followupContext?.previous_intent);
const rootIntent = toNonEmptyString(followupContext?.root_intent);
const previousAnchorType = toNonEmptyString(followupContext?.previous_anchor_type);
const previousFilters = toRecordObject(followupContext?.previous_filters);
const hasReferentialDocumentExclusionFollowupCue = /(?:\u043a\u0440\u043e\u043c\u0435|\u043f\u043e\u043c\u0438\u043c\u043e)\s+(?:\u044d\u0442\u043e\u0433\u043e|\u044d\u0442\u043e\u0439|\u044d\u0442\u043e\u0442|\u044d\u0442\u0443|\u044d\u0442\u0438\u0445)(?:\s+(?:\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430|\u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0430|\u043a\u043e\u043d\u0442\u0440\u0430\u0433\u0435\u043d\u0442\u0430))?/iu.test(
rawMessage
);
@@ -781,12 +782,14 @@ function shouldPreferRawFollowupMessage(
[rawMessage, canonicalMessage].some((message) => hasInventoryMarginRankingAccountCorrectionCue(message));
const hasDocumentCarryover =
previousIntent === "list_documents_by_counterparty" || previousIntent === "list_documents_by_contract";
const hasCounterpartyCarryover =
previousAnchorType === "counterparty" || Boolean(toNonEmptyString(previousFilters?.counterparty));
if (mode === "unsupported" && intent === "unknown") {
return true;
}
if (hasDocumentCarryover && hasReferentialDocumentExclusionFollowupCue) {
if ((hasDocumentCarryover || hasCounterpartyCarryover) && hasReferentialDocumentExclusionFollowupCue) {
return true;
}
@@ -72,6 +72,42 @@ export function createAssistantTransitionPolicy(deps) {
});
}
function hasInventorySupplierOverlapRootFollowupSignal(
userMessage,
alternateMessage = null,
sourceIntentHint = null,
hasInventoryRootFrame = false
) {
if (
!hasInventoryRootFrame ||
(sourceIntentHint !== "inventory_on_hand_as_of_date" &&
sourceIntentHint !== "inventory_supplier_stock_overlap_as_of_date")
) {
return false;
}
return [userMessage, alternateMessage]
.filter((value) => deps.toNonEmptyString(value))
.map((value) => normalizeFollowupText(value))
.some((normalized) => {
if (!normalized) {
return false;
}
const hasSupplierCue =
/(?:\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a|supplier|vendor|\u0443\s+\u043a\u0430\u043a\u043e\u0433\u043e|\u0443\s+\u043a\u043e\u0433\u043e|\u043f\u043e\s+\u043a\u0430\u043a\u043e\u043c\u0443)/iu.test(
normalized
);
const hasStockCue =
/(?:\u043e\u0441\u0442\u0430\u0442|\u0441\u043a\u043b\u0430\u0434|\u0442\u043e\u0432\u0430\u0440|\u043f\u043e\u0437\u0438\u0446|\u043b\u0435\u0436|\u0432\u0438\u0441|\u0442\u0435\u043a\u0443\u0449)/iu.test(
normalized
);
const hasPurchaseCue =
/(?:\u043a\u0443\u043f\u0438\u043b|\u043a\u0443\u043f\u043b\u0435\u043d|\u043f\u043e\u043a\u0443\u043f|\u0437\u0430\u043a\u0443\u043f|\u043f\u043e\u0441\u0442\u0443\u043f\u043b|purchase|bought)/iu.test(
normalized
);
return hasSupplierCue && (hasStockCue || hasPurchaseCue);
});
}
function hasSamePeriodReferenceCue(...values) {
return values
.map((value) => normalizeFollowupText(value))
@@ -1180,6 +1216,12 @@ export function createAssistantTransitionPolicy(deps) {
Boolean(recentInventoryRootFrame)
)
: false;
const hasInventorySupplierOverlapRootFollowup = hasInventorySupplierOverlapRootFollowupSignal(
userMessage,
alternateMessage,
sourceIntentHint,
Boolean(recentInventoryRootFrame)
);
const hasExplicitInventorySameDatePivotPrimary = hasExplicitInventorySameDatePivotSignal(userMessage);
const hasExplicitInventorySameDatePivotAlternate = deps.toNonEmptyString(alternateMessage)
? hasExplicitInventorySameDatePivotSignal(String(alternateMessage ?? ""))
@@ -1197,6 +1239,7 @@ export function createAssistantTransitionPolicy(deps) {
hasInventoryRootTemporalFollowupAlternate ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
hasInventorySupplierOverlapRootFollowup ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
@@ -1223,6 +1266,7 @@ export function createAssistantTransitionPolicy(deps) {
hasInventoryRootTemporalFollowupAlternate ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
hasInventorySupplierOverlapRootFollowup ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
@@ -1259,6 +1303,7 @@ export function createAssistantTransitionPolicy(deps) {
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!hasInventorySupplierOverlapRootFollowup &&
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!selectedCounterpartyDocumentFollowupSignal &&
@@ -1278,6 +1323,7 @@ export function createAssistantTransitionPolicy(deps) {
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!hasInventorySupplierOverlapRootFollowup &&
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!selectedCounterpartyDocumentFollowupSignal &&
@@ -1412,6 +1458,7 @@ export function createAssistantTransitionPolicy(deps) {
!hasInventoryRootTemporalFollowupAlternate &&
!hasInventoryRootRestatementPrimary &&
!hasInventoryRootRestatementAlternate &&
!hasInventorySupplierOverlapRootFollowup &&
!inventoryShortFollowupPrimary &&
!inventoryShortFollowupAlternate &&
!businessOverviewBoundaryFollowupPrimary &&
@@ -1483,6 +1530,7 @@ export function createAssistantTransitionPolicy(deps) {
inventoryMarginRankingFollowup ||
explicitSummaryBundleReuseSignal ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventorySupplierOverlapRootFollowup ||
mcpDiscoveryOrganizationClarificationContinuation;
hasAlternateFollowupSignal = deps.toNonEmptyString(alternateMessage)
? deps.hasAddressFollowupContextSignal(alternateMessage) ||
@@ -1495,6 +1543,7 @@ export function createAssistantTransitionPolicy(deps) {
inventoryMarginRankingFollowup ||
explicitSummaryBundleReuseSignal ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventorySupplierOverlapRootFollowup ||
mcpDiscoveryOrganizationClarificationContinuation
: false;
hasStrongFollowupReference =
@@ -1508,6 +1557,7 @@ export function createAssistantTransitionPolicy(deps) {
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventorySupplierOverlapRootFollowup ||
inventoryPurchaseDateVatBridge ||
explicitSummaryBundleReuseSignal ||
Boolean(debtRoleSwapIntent) ||
@@ -1728,6 +1778,7 @@ export function createAssistantTransitionPolicy(deps) {
const predecomposeIntent = deps.toNonEmptyString(llmPreDecomposeMeta?.predecomposeContract?.intent);
const carryoverTargetIntentPreview = explicitIntent ?? predecomposeIntent ?? previousIntent;
if (
!selectedCounterpartyDocumentFollowupSignal &&
shouldClearStaleDateScopeForCounterpartyDocsRoot(
carryoverTargetIntentPreview,
sourceIntentHint,
@@ -1754,6 +1805,7 @@ export function createAssistantTransitionPolicy(deps) {
inventoryShortFollowupAlternate ||
hasInventoryRootTemporalFollowupPrimary ||
hasInventoryRootTemporalFollowupAlternate ||
hasInventorySupplierOverlapRootFollowup ||
hasInventoryRootRestatementPrimary ||
hasInventoryRootRestatementAlternate ||
hasSelectedObjectInventorySignalPrimary ||
@@ -153,6 +153,133 @@ describe("assistantTransitionPolicy", () => {
expect(carryover?.followupContext?.root_intent).toBe("inventory_on_hand_as_of_date");
});
it("carries inventory root date into supplier-overlap current-stock follow-up", () => {
const organization = "\u041e\u041e\u041e \"\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u041f\u043b\u044e\u0441\"";
const warehouse = "\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043a\u043b\u0430\u0434";
const rootFilters = {
period_from: "2021-09-01",
period_to: "2021-09-30",
as_of_date: "2021-09-30",
organization,
warehouse
};
const policy = buildPolicy({
findLastAddressAssistantItem: () => ({
text: "\u041d\u0430 30.09.2021 \u043f\u043e \u0441\u043a\u043b\u0430\u0434\u0443 \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043a\u043b\u0430\u0434 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u044b \u043e\u0441\u0442\u0430\u0442\u043a\u0438.",
debug: {
detected_intent: "inventory_on_hand_as_of_date",
selected_recipe: "address_inventory_on_hand_as_of_date_v1",
extracted_filters: rootFilters,
anchor_type: "warehouse",
anchor_value_resolved: warehouse
}
}),
findRecentInventoryRootFrame: () => ({
intent: "inventory_on_hand_as_of_date",
filters: rootFilters,
anchorType: "warehouse",
anchorValue: warehouse,
currentFrameKind: "inventory_root"
}),
hasAddressFollowupContextSignal: () => false,
hasStandaloneAddressTopicSignal: () => true,
resolveAddressIntent: () => ({ intent: "inventory_supplier_stock_overlap_as_of_date" }),
resolveAddressIntentFamily: (intent: unknown) =>
String(intent ?? "").startsWith("inventory_") ? "inventory" : null
});
const carryover = policy.resolveAddressFollowupCarryoverContext(
"\u0423 \u043a\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430 \u0431\u044b\u043b\u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u044b \u0442\u043e\u0432\u0430\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043b\u0435\u0436\u0430\u0442 \u043d\u0430 \u0441\u043a\u043b\u0430\u0434\u0435 \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043a\u043b\u0430\u0434",
[],
"\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430 \u0441\u043a\u043b\u0430\u0434\u0435 \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043a\u043b\u0430\u0434 \u0432 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442",
{
predecomposeContract: {
intent: "inventory_supplier_stock_overlap_as_of_date"
}
},
{
session_context: {
date_scope: rootFilters,
organization_scope: organization,
active_focus_object: {
object_type: "organization",
label: organization
}
}
}
);
expect(carryover?.followupContext?.previous_intent).toBe("inventory_on_hand_as_of_date");
expect(carryover?.followupContext?.target_intent).toBe("inventory_supplier_stock_overlap_as_of_date");
expect(carryover?.followupContext?.previous_filters).toMatchObject(rootFilters);
expect(carryover?.followupContext?.root_intent).toBe("inventory_on_hand_as_of_date");
expect(carryover?.followupContext?.root_filters).toMatchObject(rootFilters);
expect(carryover?.followupContext?.current_frame_kind).toBe("inventory_root");
});
it("keeps supplier-overlap date on repeated current-residue supplier wording", () => {
const organization = "\u041e\u041e\u041e \"\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u041f\u043b\u044e\u0441\"";
const warehouse = "\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043a\u043b\u0430\u0434";
const rootFilters = {
period_from: "2021-09-01",
period_to: "2021-09-30",
as_of_date: "2021-09-30",
organization,
warehouse
};
const policy = buildPolicy({
findLastAddressAssistantItem: () => ({
text: "\u041f\u043e \u0441\u043a\u043b\u0430\u0434\u0441\u043a\u043e\u043c\u0443 \u043e\u0441\u0442\u0430\u0442\u043a\u0443 \u043d\u0430 30.09.2021 \u043d\u0430\u0439\u0434\u0435\u043d\u044b \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0438.",
debug: {
detected_intent: "inventory_supplier_stock_overlap_as_of_date",
selected_recipe: "address_inventory_supplier_stock_overlap_as_of_date_v1",
extracted_filters: rootFilters,
anchor_type: "warehouse",
anchor_value_resolved: warehouse
}
}),
findRecentInventoryRootFrame: () => ({
intent: "inventory_on_hand_as_of_date",
filters: rootFilters,
anchorType: "warehouse",
anchorValue: warehouse,
currentFrameKind: "inventory_root"
}),
hasAddressFollowupContextSignal: () => false,
hasStandaloneAddressTopicSignal: () => true,
resolveAddressIntent: () => ({ intent: "inventory_supplier_stock_overlap_as_of_date" }),
resolveAddressIntentFamily: (intent: unknown) =>
String(intent ?? "").startsWith("inventory_") ? "inventory" : null
});
const carryover = policy.resolveAddressFollowupCarryoverContext(
"\u041f\u043e \u043a\u0430\u043a\u043e\u043c\u0443 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0443 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u0432\u0430\u0440\u043d\u044b\u0439 \u043e\u0441\u0442\u0430\u0442\u043e\u043a \u043d\u0430 \u0441\u043a\u043b\u0430\u0434\u0435 \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043a\u043b\u0430\u0434",
[],
"\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u0438 \u0442\u043e\u0432\u0430\u0440\u044b, \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0449\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043e\u0441\u0442\u0430\u0442\u043e\u043a \u043d\u0430 \u0441\u043a\u043b\u0430\u0434\u0435 \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043a\u043b\u0430\u0434",
{
predecomposeContract: {
intent: "inventory_supplier_stock_overlap_as_of_date"
}
},
{
session_context: {
date_scope: rootFilters,
organization_scope: organization,
active_focus_object: {
object_type: "warehouse",
label: warehouse
}
}
}
);
expect(carryover?.followupContext?.previous_intent).toBe("inventory_supplier_stock_overlap_as_of_date");
expect(carryover?.followupContext?.target_intent).toBe("inventory_supplier_stock_overlap_as_of_date");
expect(carryover?.followupContext?.previous_filters).toMatchObject(rootFilters);
expect(carryover?.followupContext?.root_intent).toBe("inventory_on_hand_as_of_date");
expect(carryover?.followupContext?.current_frame_kind).toBe("inventory_root");
});
it("builds continuation contract from extracted root carryover", () => {
const policy = buildPolicy();