АРЧ АП11 - Архитектура после регресса: Архитектура: протянуть continuity snapshot в route arbitration и убрать non-domain drift при выборе организации

This commit is contained in:
2026-04-18 14:47:53 +03:00
parent cd734f568c
commit 21738f8662
6 changed files with 100 additions and 12 deletions
@@ -219,6 +219,11 @@ function createAssistantDataScopePolicy(deps) {
return (0, assistantOrganizationMatcher_1.mergeKnownOrganizations)(collected, 20);
}
function findLastAssistantActiveOrganization(items) {
const continuitySnapshot = (0, assistantContinuityPolicy_1.resolveAssistantContinuitySnapshot)({
sessionItems: items,
toNonEmptyString: assistantOrganizationMatcher_1.normalizeOrganizationScopeValue
});
const continuityOrganization = (0, assistantOrganizationMatcher_1.normalizeOrganizationScopeValue)(continuitySnapshot.activeOrganization);
for (let index = (Array.isArray(items) ? items.length : 0) - 1; index >= 0; index -= 1) {
const item = Array.isArray(items) ? items[index] : null;
if (!item || typeof item !== "object" || item.role !== "assistant") {
@@ -243,7 +248,7 @@ function createAssistantDataScopePolicy(deps) {
}
}
}
return null;
return continuityOrganization;
}
function extractOrganizationFactsFromRows(rows) {
const names = [];
@@ -2,6 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAssistantRoutePolicy = createAssistantRoutePolicy;
// @ts-nocheck
const assistantContinuityPolicy_1 = require("./assistantContinuityPolicy");
const ADDRESS_INTENTS_KEEP_ADDRESS_LANE = new Set([
"period_coverage_profile",
"document_type_and_account_section_profile",
@@ -71,17 +72,26 @@ function createAssistantRoutePolicy(deps) {
const sessionOrganizationScope = input?.sessionOrganizationScope && typeof input.sessionOrganizationScope === "object"
? input.sessionOrganizationScope
: null;
const lastGroundedAddressDebug = findLastGroundedAddressAnswerDebug(sessionItems);
const continuitySnapshot = (0, assistantContinuityPolicy_1.resolveAssistantContinuitySnapshot)({
sessionItems,
toNonEmptyString
});
const continuityActiveOrganization = normalizeOrganizationScopeValue(sessionOrganizationScope?.activeOrganization) ??
normalizeOrganizationScopeValue(continuitySnapshot.activeOrganization);
const lastGroundedAddressDebug = findLastGroundedAddressAnswerDebug(sessionItems) ??
continuitySnapshot.lastGroundedAddressDebug;
const lastOrganizationClarificationDebug = findLastOrganizationClarificationAddressDebug(sessionItems);
const organizationClarificationCandidates = Array.isArray(lastOrganizationClarificationDebug?.organization_candidates)
? mergeKnownOrganizations([
...lastOrganizationClarificationDebug.organization_candidates,
...((Array.isArray(sessionOrganizationScope?.knownOrganizations)
? sessionOrganizationScope.knownOrganizations
: []))
: [])),
continuityActiveOrganization
])
: [];
const organizationClarificationSelectionFromScope = normalizeOrganizationScopeValue(sessionOrganizationScope?.selectedOrganization);
const organizationClarificationSelectionFromScope = normalizeOrganizationScopeValue(sessionOrganizationScope?.selectedOrganization) ??
continuityActiveOrganization;
const organizationClarificationSelection = resolveOrganizationSelectionFromMessage(rawUserMessage, organizationClarificationCandidates) ??
resolveOrganizationSelectionFromMessage(repairedRawUserMessage, organizationClarificationCandidates) ??
resolveOrganizationSelectionFromMessage(effectiveAddressUserMessage, organizationClarificationCandidates) ??
@@ -194,7 +204,7 @@ function createAssistantRoutePolicy(deps) {
hasShortInventoryObjectFollowupSignal(repairedRawUserMessage) ||
hasShortInventoryObjectFollowupSignal(effectiveAddressUserMessage) ||
hasShortInventoryObjectFollowupSignal(repairedEffectiveAddressUserMessage)));
const organizationClarificationContinuationDetected = Boolean(followupContext &&
const organizationClarificationContinuationDetected = Boolean((followupContext || continuitySnapshot.hasGroundedAddressContext) &&
lastOrganizationClarificationDebug &&
organizationClarificationSelection &&
!dataScopeMetaQuery &&
@@ -691,7 +701,9 @@ function createAssistantRoutePolicy(deps) {
repairedEffectiveAddressUserMessage,
sessionItems
}));
const hasPriorAddressAnswerContext = Boolean(lastGroundedAddressDebug || toNonEmptyString(followupContext?.previous_intent));
const hasPriorAddressAnswerContext = Boolean(lastGroundedAddressDebug ||
continuitySnapshot.hasGroundedAddressContext ||
toNonEmptyString(followupContext?.previous_intent));
const metaFollowupOverGroundedAnswer = isMetaFollowupOverGroundedAnswer({
followupContext,
hasPriorAddressAnswerContext,
@@ -4,6 +4,7 @@ import {
normalizeOrganizationScopeValue
} from "./assistantOrganizationMatcher";
import {
resolveAssistantContinuitySnapshot,
isGroundedAddressDebug,
readAddressDebugOrganization
} from "./assistantContinuityPolicy";
@@ -296,6 +297,12 @@ export function createAssistantDataScopePolicy(deps: AssistantDataScopePolicyDep
}
function findLastAssistantActiveOrganization(items: unknown[]): string | null {
const continuitySnapshot = resolveAssistantContinuitySnapshot({
sessionItems: items,
toNonEmptyString: normalizeOrganizationScopeValue
});
const continuityOrganization = normalizeOrganizationScopeValue(continuitySnapshot.activeOrganization);
for (let index = (Array.isArray(items) ? items.length : 0) - 1; index >= 0; index -= 1) {
const item = Array.isArray(items) ? items[index] : null;
if (!item || typeof item !== "object" || (item as { role?: string }).role !== "assistant") {
@@ -323,7 +330,7 @@ export function createAssistantDataScopePolicy(deps: AssistantDataScopePolicyDep
}
}
return null;
return continuityOrganization;
}
function extractOrganizationFactsFromRows(rows: unknown[]): AssistantOrganizationFacts {
@@ -1,4 +1,6 @@
// @ts-nocheck
import { resolveAssistantContinuitySnapshot } from "./assistantContinuityPolicy";
const ADDRESS_INTENTS_KEEP_ADDRESS_LANE = new Set([
"period_coverage_profile",
"document_type_and_account_section_profile",
@@ -107,17 +109,26 @@ export function createAssistantRoutePolicy(deps) {
const sessionOrganizationScope = input?.sessionOrganizationScope && typeof input.sessionOrganizationScope === "object"
? input.sessionOrganizationScope
: null;
const lastGroundedAddressDebug = findLastGroundedAddressAnswerDebug(sessionItems);
const continuitySnapshot = resolveAssistantContinuitySnapshot({
sessionItems,
toNonEmptyString
});
const continuityActiveOrganization = normalizeOrganizationScopeValue(sessionOrganizationScope?.activeOrganization) ??
normalizeOrganizationScopeValue(continuitySnapshot.activeOrganization);
const lastGroundedAddressDebug = findLastGroundedAddressAnswerDebug(sessionItems) ??
continuitySnapshot.lastGroundedAddressDebug;
const lastOrganizationClarificationDebug = findLastOrganizationClarificationAddressDebug(sessionItems);
const organizationClarificationCandidates = Array.isArray(lastOrganizationClarificationDebug?.organization_candidates)
? mergeKnownOrganizations([
...lastOrganizationClarificationDebug.organization_candidates,
...((Array.isArray(sessionOrganizationScope?.knownOrganizations)
? sessionOrganizationScope.knownOrganizations
: []))
: [])),
continuityActiveOrganization
])
: [];
const organizationClarificationSelectionFromScope = normalizeOrganizationScopeValue(sessionOrganizationScope?.selectedOrganization);
const organizationClarificationSelectionFromScope = normalizeOrganizationScopeValue(sessionOrganizationScope?.selectedOrganization) ??
continuityActiveOrganization;
const organizationClarificationSelection = resolveOrganizationSelectionFromMessage(rawUserMessage, organizationClarificationCandidates) ??
resolveOrganizationSelectionFromMessage(repairedRawUserMessage, organizationClarificationCandidates) ??
resolveOrganizationSelectionFromMessage(effectiveAddressUserMessage, organizationClarificationCandidates) ??
@@ -230,7 +241,7 @@ export function createAssistantRoutePolicy(deps) {
hasShortInventoryObjectFollowupSignal(repairedRawUserMessage) ||
hasShortInventoryObjectFollowupSignal(effectiveAddressUserMessage) ||
hasShortInventoryObjectFollowupSignal(repairedEffectiveAddressUserMessage)));
const organizationClarificationContinuationDetected = Boolean(followupContext &&
const organizationClarificationContinuationDetected = Boolean((followupContext || continuitySnapshot.hasGroundedAddressContext) &&
lastOrganizationClarificationDebug &&
organizationClarificationSelection &&
!dataScopeMetaQuery &&
@@ -727,7 +738,9 @@ export function createAssistantRoutePolicy(deps) {
repairedEffectiveAddressUserMessage,
sessionItems
}));
const hasPriorAddressAnswerContext = Boolean(lastGroundedAddressDebug || toNonEmptyString(followupContext?.previous_intent));
const hasPriorAddressAnswerContext = Boolean(lastGroundedAddressDebug ||
continuitySnapshot.hasGroundedAddressContext ||
toNonEmptyString(followupContext?.previous_intent));
const metaFollowupOverGroundedAnswer = isMetaFollowupOverGroundedAnswer({
followupContext,
hasPriorAddressAnswerContext,
@@ -364,4 +364,46 @@ describe("assistantRoutePolicy", () => {
expect(decision.toolGateReason).toBe("address_signal_detected");
expect(decision.livingMode).toBe("address_data");
});
it("does not mark organization selection after grounded continuity as non-domain noise", () => {
const policy = buildPolicy({
findLastGroundedAddressAnswerDebug: () => null,
findLastOrganizationClarificationAddressDebug: () => ({
organization_candidates: ["Org A", "Org B"]
}),
resolveOrganizationSelectionFromMessage: (userMessage: unknown, knownOrganizations: unknown) => {
const normalized = String(userMessage ?? "").trim().toLowerCase();
const candidates = Array.isArray(knownOrganizations) ? knownOrganizations.map((item) => String(item)) : [];
return candidates.find((candidate) => candidate.toLowerCase() === normalized) ?? null;
}
});
const decision = policy.resolveAssistantOrchestrationDecision({
rawUserMessage: "Org A",
effectiveAddressUserMessage: "Org A",
followupContext: null,
llmPreDecomposeMeta: null,
sessionItems: [
{
role: "assistant",
debug: {
execution_lane: "address_query",
answer_grounding_check: { status: "grounded" },
extracted_filters: {
organization: "Org A",
as_of_date: "2021-03-31"
},
detected_intent: "receivables_confirmed_as_of_date"
}
}
],
useMock: false
});
expect(decision.runAddressLane).toBe(false);
expect(decision.toolGateReason).toBe("no_address_signal_after_l0");
expect(decision.livingMode).toBe("chat");
expect(decision.orchestrationContract?.hard_meta_mode).toBeNull();
expect(decision.orchestrationContract?.followup_context_detected).toBe(false);
});
});