АДРЕСНЫЙ РЕЖИМ -ADDRESS: убран ложный factual fallback в open_items при неподтвержденном якоре + добавлен регресс-тест

This commit is contained in:
2026-04-02 13:39:08 +03:00
parent 4dff069ae3
commit cc7fcabf05
32 changed files with 72790 additions and 180 deletions
@@ -315,6 +315,37 @@ describe("address filter extraction for balance drilldown", () => {
expect(result.warnings).toContain("as_of_date_derived_from_period_to");
});
it("extracts dotted account by heuristic for docs-forming phrasing without 'счет' keyword", () => {
const result = extractAddressFilters(
"раскрой остаток 60.01 по документам на конец июля 2020",
"documents_forming_balance"
);
expect(result.extracted_filters.account).toBe("60.01");
expect(result.extracted_filters.as_of_date).toBe("2020-07-31");
expect(result.warnings).toContain("account_anchor_derived_from_heuristic_token");
});
it("extracts dotted account by heuristic for short balance slang", () => {
const result = extractAddressFilters("скока по 60.02 на конец 2020-12", "account_balance_snapshot");
expect(result.extracted_filters.account).toBe("60.02");
expect(result.extracted_filters.as_of_date).toBe("2020-12-31");
expect(result.warnings).toContain("account_anchor_derived_from_heuristic_token");
});
it("drops accidental account for non-account intent without explicit account cue", () => {
const result = extractAddressFilters("покажи банк операции по свк за 2020", "bank_operations_by_counterparty");
expect(result.extracted_filters.account).toBeUndefined();
});
it("extracts leading counterparty token for short bank phrase", () => {
const result = extractAddressFilters("свк списания/поступления за 2020", "bank_operations_by_counterparty");
expect(result.extracted_filters.counterparty).toBe("свк");
expect(
result.warnings.includes("counterparty_anchor_derived_from_leading_token") ||
result.warnings.includes("counterparty_anchor_derived_from_free_text_heuristic")
).toBe(true);
});
it("treats 'за весь период' as all-time hint and does not force 90-day default", () => {
const result = extractAddressFilters(
"Покажи банковские операции по клиенту Бета за весь период",
@@ -467,6 +498,26 @@ describe("address filter extraction for balance drilldown", () => {
expect(result.extracted_filters.period_to).toBe("2020-12-31");
});
it("trims english year tail from contract anchor", () => {
const result = extractAddressFilters(
"docs by contract 15/24 year 2020",
"list_documents_by_contract"
);
expect(result.extracted_filters.contract).toBe("15/24");
expect(result.extracted_filters.period_from).toBe("2020-01-01");
expect(result.extracted_filters.period_to).toBe("2020-12-31");
});
it("trims trailing separated year from contract anchor", () => {
const result = extractAddressFilters(
"docs by contract 15/24 2020",
"list_documents_by_contract"
);
expect(result.extracted_filters.contract).toBe("15/24");
expect(result.extracted_filters.period_from).toBe("2020-01-01");
expect(result.extracted_filters.period_to).toBe("2020-12-31");
});
it("extracts multiline year range period from phrase", () => {
const result = extractAddressFilters(
"Какие документы по СВК за 2000 - 2025\n год?",
@@ -514,6 +565,18 @@ describe("address query limited taxonomy and stage diagnostics", () => {
expect(result?.debug.mcp_call_status).toBe("skipped");
});
it("does not return fallback factual rows for unmatched open-items contract anchor", async () => {
const service = new AddressQueryService();
const result = await service.tryHandle("Покажи открытые позиции по договору 15/24");
expect(result?.handled).toBe(true);
expect(result?.response_type).toBe("LIMITED_WITH_REASON");
expect(result?.reply_type).toBe("partial_coverage");
expect(result?.debug.detected_intent).toBe("open_items_by_counterparty_or_contract");
expect(result?.debug.rows_matched).toBe(0);
expect(["empty_match", "missing_anchor"]).toContain(result?.debug.limited_reason_category);
expect(String(result?.assistant_reply ?? "")).not.toContain("Собраны открытые позиции");
});
it("routes contract document list intent into address recipe", async () => {
const service = new AddressQueryService();
const result = await service.tryHandle("show documents by contract 15/24");