ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Архитектура маршрутизации: зафиксирован baseline-контракт и добавлен anti-regression контроль
This commit is contained in:
parent
c10260dedf
commit
bd1fbbdb67
|
|
@ -91,6 +91,14 @@ Tests:
|
|||
- `llm_normalizer/backend/tests/addressCapabilityPolicy.test.ts`
|
||||
- `llm_normalizer/backend/tests/addressNavigationState.test.ts`
|
||||
- `llm_normalizer/backend/tests/sessionBackwardCompat.test.ts` (extended)
|
||||
- `llm_normalizer/backend/tests/addressRouteBaseline.test.ts`
|
||||
|
||||
Route baseline contract:
|
||||
|
||||
- `docs/TECH/address_route_baseline_v1.json`
|
||||
- loader: `llm_normalizer/backend/src/services/addressRouteBaseline.ts`
|
||||
|
||||
This baseline freezes capability mapping for key intents and acts as anti-regression control when routing evolves.
|
||||
|
||||
## Why This Is a Foundation, Not a Patch
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"schema_version": "address_route_baseline_v1",
|
||||
"updated_at": "2026-04-12T12:00:00.000Z",
|
||||
"entries": [
|
||||
{
|
||||
"intent": "payables_confirmed_as_of_date",
|
||||
"capability_id": "confirmed_payables_as_of_date",
|
||||
"capability_layer": "compute",
|
||||
"capability_route_mode": "exact"
|
||||
},
|
||||
{
|
||||
"intent": "list_payables_counterparties",
|
||||
"capability_id": "payables_candidates_list",
|
||||
"capability_layer": "compute",
|
||||
"capability_route_mode": "heuristic"
|
||||
},
|
||||
{
|
||||
"intent": "list_receivables_counterparties",
|
||||
"capability_id": "receivables_candidates_list",
|
||||
"capability_layer": "compute",
|
||||
"capability_route_mode": "heuristic"
|
||||
},
|
||||
{
|
||||
"intent": "account_balance_snapshot",
|
||||
"capability_id": "account_balance_exact",
|
||||
"capability_layer": "compute",
|
||||
"capability_route_mode": "exact"
|
||||
},
|
||||
{
|
||||
"intent": "documents_forming_balance",
|
||||
"capability_id": "account_balance_exact",
|
||||
"capability_layer": "compute",
|
||||
"capability_route_mode": "exact"
|
||||
},
|
||||
{
|
||||
"intent": "list_documents_by_counterparty",
|
||||
"capability_id": "documents_drilldown",
|
||||
"capability_layer": "navigation",
|
||||
"capability_route_mode": "exact"
|
||||
},
|
||||
{
|
||||
"intent": "list_documents_by_contract",
|
||||
"capability_id": "documents_drilldown",
|
||||
"capability_layer": "navigation",
|
||||
"capability_route_mode": "exact"
|
||||
},
|
||||
{
|
||||
"intent": "list_contracts_by_counterparty",
|
||||
"capability_id": "contracts_drilldown",
|
||||
"capability_layer": "navigation",
|
||||
"capability_route_mode": "exact"
|
||||
},
|
||||
{
|
||||
"intent": "bank_operations_by_counterparty",
|
||||
"capability_id": "bank_operations_drilldown",
|
||||
"capability_layer": "navigation",
|
||||
"capability_route_mode": "exact"
|
||||
},
|
||||
{
|
||||
"intent": "bank_operations_by_contract",
|
||||
"capability_id": "bank_operations_drilldown",
|
||||
"capability_layer": "navigation",
|
||||
"capability_route_mode": "exact"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.loadAddressRouteBaselineContract = loadAddressRouteBaselineContract;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const BASELINE_FILE = path_1.default.resolve(__dirname, "..", "..", "..", "..", "docs", "TECH", "address_route_baseline_v1.json");
|
||||
function toObject(value) {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function toNonEmptyString(value) {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
function parseEntry(value) {
|
||||
const object = toObject(value);
|
||||
if (!object) {
|
||||
return null;
|
||||
}
|
||||
const intent = toNonEmptyString(object.intent);
|
||||
const capabilityId = toNonEmptyString(object.capability_id);
|
||||
const layer = toNonEmptyString(object.capability_layer);
|
||||
const routeMode = toNonEmptyString(object.capability_route_mode);
|
||||
if (!intent || !capabilityId || !layer || !routeMode) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
intent,
|
||||
capability_id: capabilityId,
|
||||
capability_layer: layer,
|
||||
capability_route_mode: routeMode
|
||||
};
|
||||
}
|
||||
function loadAddressRouteBaselineContract() {
|
||||
const raw = fs_1.default.readFileSync(BASELINE_FILE, "utf-8");
|
||||
const parsed = JSON.parse(raw);
|
||||
const root = toObject(parsed);
|
||||
if (!root) {
|
||||
throw new Error("address_route_baseline_v1: invalid root payload");
|
||||
}
|
||||
const schemaVersion = toNonEmptyString(root.schema_version);
|
||||
if (schemaVersion !== "address_route_baseline_v1") {
|
||||
throw new Error(`address_route_baseline_v1: unexpected schema version '${schemaVersion ?? "null"}'`);
|
||||
}
|
||||
const updatedAt = toNonEmptyString(root.updated_at) ?? new Date().toISOString();
|
||||
const entriesRaw = Array.isArray(root.entries) ? root.entries : [];
|
||||
const entries = entriesRaw.map(parseEntry).filter((entry) => entry !== null);
|
||||
if (entries.length === 0) {
|
||||
throw new Error("address_route_baseline_v1: no valid entries");
|
||||
}
|
||||
return {
|
||||
schema_version: "address_route_baseline_v1",
|
||||
updated_at: updatedAt,
|
||||
entries
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import type { AddressCapabilityLayer, AddressCapabilityRouteMode, AddressIntent } from "../types/addressQuery";
|
||||
|
||||
export interface AddressRouteBaselineEntry {
|
||||
intent: AddressIntent;
|
||||
capability_id: string;
|
||||
capability_layer: AddressCapabilityLayer;
|
||||
capability_route_mode: AddressCapabilityRouteMode;
|
||||
}
|
||||
|
||||
export interface AddressRouteBaselineContract {
|
||||
schema_version: "address_route_baseline_v1";
|
||||
updated_at: string;
|
||||
entries: AddressRouteBaselineEntry[];
|
||||
}
|
||||
|
||||
const BASELINE_FILE = path.resolve(__dirname, "..", "..", "..", "..", "docs", "TECH", "address_route_baseline_v1.json");
|
||||
|
||||
function toObject(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toNonEmptyString(value: unknown): string | null {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
|
||||
function parseEntry(value: unknown): AddressRouteBaselineEntry | null {
|
||||
const object = toObject(value);
|
||||
if (!object) {
|
||||
return null;
|
||||
}
|
||||
const intent = toNonEmptyString(object.intent) as AddressIntent | null;
|
||||
const capabilityId = toNonEmptyString(object.capability_id);
|
||||
const layer = toNonEmptyString(object.capability_layer) as AddressCapabilityLayer | null;
|
||||
const routeMode = toNonEmptyString(object.capability_route_mode) as AddressCapabilityRouteMode | null;
|
||||
if (!intent || !capabilityId || !layer || !routeMode) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
intent,
|
||||
capability_id: capabilityId,
|
||||
capability_layer: layer,
|
||||
capability_route_mode: routeMode
|
||||
};
|
||||
}
|
||||
|
||||
export function loadAddressRouteBaselineContract(): AddressRouteBaselineContract {
|
||||
const raw = fs.readFileSync(BASELINE_FILE, "utf-8");
|
||||
const parsed = JSON.parse(raw) as unknown;
|
||||
const root = toObject(parsed);
|
||||
if (!root) {
|
||||
throw new Error("address_route_baseline_v1: invalid root payload");
|
||||
}
|
||||
const schemaVersion = toNonEmptyString(root.schema_version);
|
||||
if (schemaVersion !== "address_route_baseline_v1") {
|
||||
throw new Error(`address_route_baseline_v1: unexpected schema version '${schemaVersion ?? "null"}'`);
|
||||
}
|
||||
const updatedAt = toNonEmptyString(root.updated_at) ?? new Date().toISOString();
|
||||
const entriesRaw = Array.isArray(root.entries) ? root.entries : [];
|
||||
const entries = entriesRaw.map(parseEntry).filter((entry): entry is AddressRouteBaselineEntry => entry !== null);
|
||||
if (entries.length === 0) {
|
||||
throw new Error("address_route_baseline_v1: no valid entries");
|
||||
}
|
||||
return {
|
||||
schema_version: "address_route_baseline_v1",
|
||||
updated_at: updatedAt,
|
||||
entries
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { loadAddressRouteBaselineContract } from "../src/services/addressRouteBaseline";
|
||||
import { resolveAddressCapabilityRouteDecision } from "../src/services/addressCapabilityPolicy";
|
||||
|
||||
describe("address route baseline contract", () => {
|
||||
it("keeps capability route mapping aligned with frozen baseline", () => {
|
||||
const baseline = loadAddressRouteBaselineContract();
|
||||
expect(baseline.schema_version).toBe("address_route_baseline_v1");
|
||||
expect(Array.isArray(baseline.entries)).toBe(true);
|
||||
expect(baseline.entries.length).toBeGreaterThan(0);
|
||||
|
||||
for (const entry of baseline.entries) {
|
||||
const decision = resolveAddressCapabilityRouteDecision(entry.intent);
|
||||
expect(decision.capability_id).toBe(entry.capability_id);
|
||||
expect(decision.capability_layer).toBe(entry.capability_layer);
|
||||
expect(decision.capability_route_mode).toBe(entry.capability_route_mode);
|
||||
}
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue