ARCH: удержать contracts pivot после payments follow-up

This commit is contained in:
2026-04-23 20:40:09 +03:00
parent 7e1a2edadb
commit d7ee95286d
5 changed files with 185 additions and 0 deletions
@@ -554,6 +554,7 @@ function createAssistantTransitionPolicy(deps) {
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!hasImplicitContinuationSignal &&
!hasSuggestedIntentPivotSignal &&
!hasOrganizationClarificationContinuation &&
!hasIndexReferenceSignal) {
return null;
@@ -567,6 +568,7 @@ function createAssistantTransitionPolicy(deps) {
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!hasImplicitContinuationSignal &&
!hasSuggestedIntentPivotSignal &&
!hasOrganizationClarificationContinuation &&
!hasIndexReferenceSignal) {
return null;
@@ -683,6 +685,7 @@ function createAssistantTransitionPolicy(deps) {
}
hasPrimaryFollowupSignal =
deps.hasAddressFollowupContextSignal(userMessage) ||
hasSuggestedIntentPivotSignal ||
Boolean(debtRoleSwapPrimary) ||
shortValueFlowRetargetPrimary ||
inventoryShortFollowupPrimary ||
@@ -690,6 +693,7 @@ function createAssistantTransitionPolicy(deps) {
hasInventoryRootTemporalFollowupPrimary;
hasAlternateFollowupSignal = deps.toNonEmptyString(alternateMessage)
? deps.hasAddressFollowupContextSignal(alternateMessage) ||
hasSuggestedIntentPivotSignal ||
Boolean(debtRoleSwapAlternate) ||
shortValueFlowRetargetAlternate ||
inventoryShortFollowupAlternate ||
@@ -700,6 +704,7 @@ function createAssistantTransitionPolicy(deps) {
hasPrimaryIndexReferenceSignal ||
hasAlternateIndexReferenceSignal ||
hasOrganizationClarificationContinuation ||
hasSuggestedIntentPivotSignal ||
hasImplicitContinuationSignal ||
inventoryShortFollowupPrimary ||
inventoryShortFollowupAlternate ||
@@ -751,6 +751,7 @@ export function createAssistantTransitionPolicy(deps) {
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!hasImplicitContinuationSignal &&
!hasSuggestedIntentPivotSignal &&
!hasOrganizationClarificationContinuation &&
!hasIndexReferenceSignal
) {
@@ -766,6 +767,7 @@ export function createAssistantTransitionPolicy(deps) {
!shortValueFlowRetargetPrimary &&
!shortValueFlowRetargetAlternate &&
!hasImplicitContinuationSignal &&
!hasSuggestedIntentPivotSignal &&
!hasOrganizationClarificationContinuation &&
!hasIndexReferenceSignal
) {
@@ -944,6 +946,7 @@ export function createAssistantTransitionPolicy(deps) {
}
hasPrimaryFollowupSignal =
deps.hasAddressFollowupContextSignal(userMessage) ||
hasSuggestedIntentPivotSignal ||
Boolean(debtRoleSwapPrimary) ||
shortValueFlowRetargetPrimary ||
inventoryShortFollowupPrimary ||
@@ -951,6 +954,7 @@ export function createAssistantTransitionPolicy(deps) {
hasInventoryRootTemporalFollowupPrimary;
hasAlternateFollowupSignal = deps.toNonEmptyString(alternateMessage)
? deps.hasAddressFollowupContextSignal(alternateMessage) ||
hasSuggestedIntentPivotSignal ||
Boolean(debtRoleSwapAlternate) ||
shortValueFlowRetargetAlternate ||
inventoryShortFollowupAlternate ||
@@ -961,6 +965,7 @@ export function createAssistantTransitionPolicy(deps) {
hasPrimaryIndexReferenceSignal ||
hasAlternateIndexReferenceSignal ||
hasOrganizationClarificationContinuation ||
hasSuggestedIntentPivotSignal ||
hasImplicitContinuationSignal ||
inventoryShortFollowupPrimary ||
inventoryShortFollowupAlternate ||
@@ -737,6 +737,52 @@ describe("assistantTransitionPolicy", () => {
expect(contract.decision_reasons).toContain("suggested_intent_followup_pivot");
});
it("switches from payments to suggested contracts on a pronoun follow-up even when generic follow-up signal is weak", () => {
const policy = buildPolicy({
findLastAddressAssistantItem: () => ({
text: "Собран список банковских операций по контрагенту ТСЖ \\Жуковка 51\\.",
debug: {
detected_intent: "bank_operations_by_counterparty",
extracted_filters: {
counterparty: "ТСЖ \\Жуковка 51\\"
},
anchor_type: "counterparty",
anchor_value_resolved: "ТСЖ \\Жуковка 51\\"
}
}),
buildAddressFollowupOffer: () => ({
enabled: true,
source_intent: "bank_operations_by_counterparty",
suggested_intents: ["list_documents_by_counterparty", "list_contracts_by_counterparty"]
}),
hasAddressFollowupContextSignal: () => false,
hasReferentialPointer: () => true
});
const carryover = policy.resolveAddressFollowupCarryoverContext("А по нему договоры?", [], null, null, null);
expect(carryover?.followupContext?.previous_intent).toBe("list_contracts_by_counterparty");
expect(carryover?.followupContext?.target_intent).toBe("list_contracts_by_counterparty");
expect(carryover?.followupContext?.previous_anchor_type).toBe("counterparty");
expect(carryover?.hasSuggestedIntentPivotSignal).toBe(true);
expect(carryover?.followupSelectionMode).toBe("switch_to_suggested_intent");
const contract = policy.buildAddressDialogContinuationContractV2(
"А по нему договоры?",
"Покажи договоры, связанные с указанным объектом",
carryover,
{
predecomposeContract: {
intent: "unknown"
}
}
);
expect(contract.decision).toBe("switch_to_suggested");
expect(contract.target_intent).toBe("list_contracts_by_counterparty");
expect(contract.decision_reasons).toContain("suggested_intent_followup_pivot");
});
it("keeps root-scoped carryover for foreign accounting pivot over inventory drilldown", () => {
const policy = buildPolicy({
findLastAddressAssistantItem: () => ({