From 09dd0e45130bae426914f582f561079ac15b4fdb Mon Sep 17 00:00:00 2001 From: dctouch Date: Sat, 18 Apr 2026 18:26:08 +0300 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=A0=D0=A7=20=D0=90=D0=9F11=20-=20?= =?UTF-8?q?=D0=90=D1=80=D1=85=D0=B8=D1=82=D0=B5=D0=BA=D1=82=D1=83=D1=80?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D1=80=D0=B5=D0=B3?= =?UTF-8?q?=D1=80=D0=B5=D1=81=D1=81=D0=B0:=20=D0=90=D1=80=D1=85=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BA=D1=82=D1=83=D1=80=D0=B0:=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=82=D1=8F=D0=BD=D1=83=D1=82=D1=8C=20continuity-backed?= =?UTF-8?q?=20organization=20authority=20=D0=B2=20session=20scope=20bootst?= =?UTF-8?q?rap=20=D0=B8=20=D1=83=D0=B4=D0=B5=D1=80=D0=B6=D0=B0=D1=82=D1=8C?= =?UTF-8?q?=20phase12=20wider=20replay=20=D0=B7=D0=B5=D0=BB=D1=91=D0=BD?= =?UTF-8?q?=D1=8B=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ontinuity_stabilization_plan_2026-04-17.md | 6 ++++ ...ssistantOrganizationScopeRuntimeAdapter.js | 12 ++++++++ ...ssistantOrganizationScopeRuntimeAdapter.ts | 14 +++++++++ ...antOrganizationScopeRuntimeAdapter.test.ts | 29 +++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/docs/ARCH/11 - architecture_turnaround/11 - continuity_stabilization_plan_2026-04-17.md b/docs/ARCH/11 - architecture_turnaround/11 - continuity_stabilization_plan_2026-04-17.md index 91f36bf..84565da 100644 --- a/docs/ARCH/11 - architecture_turnaround/11 - continuity_stabilization_plan_2026-04-17.md +++ b/docs/ARCH/11 - architecture_turnaround/11 - continuity_stabilization_plan_2026-04-17.md @@ -309,6 +309,12 @@ Still open after the accepted phase12 replay: - more saved-session and multi-trajectory replay breadth; - less duplicated state reconstruction in route / transition / living-chat glue; - controlled expansion only after those broader proofs stay green. +- the next authority-convergence pass now also removes one more duplicate scope builder at the very start of the turn: + - `assistantOrganizationScopeRuntimeAdapter` no longer reconstructs `knownOrganizations / selectedOrganization / activeOrganization` only from its own local history helpers; + - the same session-scope bootstrap now consumes the shared continuity-backed organization authority first and only then falls back to older helper outputs and navigation-state overrides; + - this matters because route, living-chat, data-scope, and early session-scope bootstrap are now closer to the same organization merge order instead of keeping a separate pre-route branch with its own drift risk; + - targeted tests now explicitly protect the case where assistant-side continuity authority is present in prior assistant debug even when legacy history helpers are empty; + - live replay `address_truth_harness_phase12_wider_saved_session_pool_live_20260418_rerun4` remains accepted `20/20`, which is the critical proof that this authority convergence did not reopen the wider saved-session path. ## Next Execution Slice (2026-04-18) diff --git a/llm_normalizer/backend/dist/services/assistantOrganizationScopeRuntimeAdapter.js b/llm_normalizer/backend/dist/services/assistantOrganizationScopeRuntimeAdapter.js index 179f608..d883193 100644 --- a/llm_normalizer/backend/dist/services/assistantOrganizationScopeRuntimeAdapter.js +++ b/llm_normalizer/backend/dist/services/assistantOrganizationScopeRuntimeAdapter.js @@ -2,6 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveSessionOrganizationScopeContextRuntime = resolveSessionOrganizationScopeContextRuntime; exports.mergeFollowupContextWithOrganizationScopeRuntime = mergeFollowupContextWithOrganizationScopeRuntime; +const assistantContinuityPolicy_1 = require("./assistantContinuityPolicy"); function extractOrganizationsFromNavigationState(addressNavigationState, normalizeOrganizationScopeValue) { if (!addressNavigationState || typeof addressNavigationState !== "object") { return []; @@ -26,7 +27,17 @@ function resolveActiveOrganizationFromNavigationState(addressNavigationState, no return normalizeOrganizationScopeValue(addressNavigationState.session_context?.organization_scope); } function resolveSessionOrganizationScopeContextRuntime(input) { + const continuityAuthority = (0, assistantContinuityPolicy_1.resolveAssistantOrganizationAuthority)({ + sessionItems: Array.isArray(input.items) ? input.items : [], + toNonEmptyString: input.normalizeOrganizationScopeValue, + normalizeOrganizationScopeValue: input.normalizeOrganizationScopeValue + }); + const continuityKnownOrganizations = Array.isArray(continuityAuthority.knownOrganizations) + ? continuityAuthority.knownOrganizations + : []; + const continuityActiveOrganization = input.normalizeOrganizationScopeValue(continuityAuthority.activeOrganization); const knownOrganizations = Array.from(new Map([ + ...continuityKnownOrganizations, ...extractOrganizationsFromNavigationState(input.addressNavigationState, input.normalizeOrganizationScopeValue), ...input.extractKnownOrganizationsFromHistory(input.items) ].map((value) => [String(value).toLowerCase(), value])).values()); @@ -35,6 +46,7 @@ function resolveSessionOrganizationScopeContextRuntime(input) { const navigationActiveOrganization = resolveActiveOrganizationFromNavigationState(input.addressNavigationState, input.normalizeOrganizationScopeValue); const activeOrganization = selectedOrganization ?? navigationActiveOrganization ?? + continuityActiveOrganization ?? input.normalizeOrganizationScopeValue(lastActiveOrganization) ?? (knownOrganizations.length === 1 ? knownOrganizations[0] : null); return { diff --git a/llm_normalizer/backend/src/services/assistantOrganizationScopeRuntimeAdapter.ts b/llm_normalizer/backend/src/services/assistantOrganizationScopeRuntimeAdapter.ts index cdb5309..0e844de 100644 --- a/llm_normalizer/backend/src/services/assistantOrganizationScopeRuntimeAdapter.ts +++ b/llm_normalizer/backend/src/services/assistantOrganizationScopeRuntimeAdapter.ts @@ -1,4 +1,5 @@ import type { AddressNavigationState } from "../types/addressNavigation"; +import { resolveAssistantOrganizationAuthority } from "./assistantContinuityPolicy"; export interface AssistantSessionOrganizationScopeContext { knownOrganizations: string[]; @@ -57,9 +58,21 @@ function resolveActiveOrganizationFromNavigationState( export function resolveSessionOrganizationScopeContextRuntime( input: ResolveSessionOrganizationScopeContextRuntimeInput ): AssistantSessionOrganizationScopeContext { + const continuityAuthority = resolveAssistantOrganizationAuthority({ + sessionItems: Array.isArray(input.items) ? input.items : [], + toNonEmptyString: input.normalizeOrganizationScopeValue, + normalizeOrganizationScopeValue: input.normalizeOrganizationScopeValue + }); + const continuityKnownOrganizations = Array.isArray(continuityAuthority.knownOrganizations) + ? continuityAuthority.knownOrganizations + : []; + const continuityActiveOrganization = input.normalizeOrganizationScopeValue( + continuityAuthority.activeOrganization + ); const knownOrganizations = Array.from( new Map( [ + ...continuityKnownOrganizations, ...extractOrganizationsFromNavigationState(input.addressNavigationState, input.normalizeOrganizationScopeValue), ...input.extractKnownOrganizationsFromHistory(input.items) ].map((value) => [String(value).toLowerCase(), value]) @@ -77,6 +90,7 @@ export function resolveSessionOrganizationScopeContextRuntime { }); }); + it("reuses assistant continuity authority from prior assistant debug when legacy helpers are empty", () => { + const normalizeOrganizationScopeValue = vi.fn((value: unknown) => + typeof value === "string" && value.trim() ? value.trim() : null + ); + + const context = resolveSessionOrganizationScopeContextRuntime({ + userMessage: "просто продолжай", + items: [ + { + role: "assistant", + debug: { + assistant_known_organizations: ["Org C", "Org D"], + assistant_active_organization: "Org C" + } + } + ] as any[], + extractKnownOrganizationsFromHistory: () => [], + resolveOrganizationSelectionFromMessage: () => null, + findLastAssistantActiveOrganization: () => null, + normalizeOrganizationScopeValue + }); + + expect(context).toEqual({ + knownOrganizations: ["Org C", "Org D"], + selectedOrganization: null, + activeOrganization: "Org C" + }); + }); + it("merges organization into followup previous filters when organization is missing", () => { const merged = mergeFollowupContextWithOrganizationScopeRuntime({ followupContext: {