АРЧ АП11 - Архитектура после регресса: Архитектура: протянуть continuity-backed organization authority в session scope bootstrap и удержать phase12 wider replay зелёным

This commit is contained in:
dctouch 2026-04-18 18:26:08 +03:00
parent 12550606bb
commit 09dd0e4513
4 changed files with 61 additions and 0 deletions

View File

@ -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)

View File

@ -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 {

View File

@ -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<ItemType = unknown>(
input: ResolveSessionOrganizationScopeContextRuntimeInput<ItemType>
): 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<ItemType = unknown
const activeOrganization =
selectedOrganization ??
navigationActiveOrganization ??
continuityActiveOrganization ??
input.normalizeOrganizationScopeValue(lastActiveOrganization) ??
(knownOrganizations.length === 1 ? knownOrganizations[0] : null);

View File

@ -90,6 +90,35 @@ describe("assistant organization scope runtime adapter", () => {
});
});
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: {