ДОМЕНЫ - ВОПРОСЫ - Этап 4: точный маршрут confirmed payables на дату без эвристического фолбэка

This commit is contained in:
2026-04-12 14:14:03 +03:00
parent 1b2ee93176
commit fbd156e58e
19 changed files with 1303 additions and 162 deletions
@@ -1832,7 +1832,7 @@ describe("address intent resolver expansion (M2.3a)", () => {
it("marks 'кому мы должны заплатить' as payables debt lifecycle intent", () => {
const result = resolveAddressIntent("каму мы должны заплатить за май 2020");
expect(result.intent).toBe("list_payables_counterparties");
expect(result.intent).toBe("payables_confirmed_as_of_date");
expect(result.reasons).toContain("payables_debt_lifecycle_signal_detected");
});
@@ -2494,30 +2494,31 @@ describe("address query limited taxonomy and stage diagnostics", { timeout: 1500
expect(result?.debug.limited_reason_category).not.toBe("unsupported");
});
it("routes 'каму мы должны заплатить за май 2020' into confirmed payables flow with explicit fallback contract", async () => {
it("routes 'каму мы должны заплатить за май 2020' into exact confirmed payables flow without heuristic fallback", async () => {
const service = new AddressQueryService();
const result = await service.tryHandle("каму мы должны заплатить за май 2020");
expect(result?.handled).toBe(true);
expect(result?.debug.detected_intent).toBe("list_payables_counterparties");
expect(result?.debug.detected_intent).toBe("payables_confirmed_as_of_date");
expect(result?.debug.requested_result_mode).toBe("confirmed_balance");
expect(result?.debug.as_of_date_basis).toBe("period_range");
expect(result?.debug.result_mode).toBe("confirmed_balance");
expect(result?.debug.as_of_date_basis).toBe("explicit_as_of_date");
expect(result?.debug.selected_recipe).toBe("address_payables_confirmed_as_of_date_v1");
expect(Array.isArray(result?.debug.reasons)).toBe(true);
expect(result?.debug.reasons).not.toContain("confirmed_balance_unavailable_fallback_to_heuristic_candidates");
expect(["FACTUAL_LIST", "FACTUAL_SUMMARY", "LIMITED_WITH_REASON"]).toContain(result?.response_type);
const reply = String(result?.reply_text ?? "");
if (result?.debug.result_mode === "confirmed_balance") {
expect(result?.debug.selected_recipe).toBe("address_movements_payables_v1");
expect(result?.debug.balance_confirmed).toBe(true);
expect(reply).toContain("подтвержденный срез обязательств к оплате");
expect(reply).toContain("Кому нужно заплатить в первую очередь");
} else {
expect(result?.debug.result_mode).toBe("heuristic_candidates");
if (result?.response_type === "LIMITED_WITH_REASON") {
expect(result?.debug.balance_confirmed).toBe(false);
expect(result?.debug.reasons).toContain("confirmed_balance_unavailable_fallback_to_heuristic_candidates");
expect(reply).toContain("эвристический скоринг");
expect(reply).toContain("Контрагентов-кандидатов:");
expect(result?.debug.reasons).toContain("exact_payables_mode_limited_response");
expect(reply.toLowerCase()).not.toContain("эвристич");
} else {
expect(result?.debug.balance_confirmed).toBe(true);
expect(reply).toContain("Блок 1. Статус результата");
expect(reply).toContain("\n\nБлок 2. Как читать результат");
expect(reply).toContain("\n\nБлок 3. Сводка выборки");
expect(reply).not.toContain("Кому нужно заплатить в первую очередь");
expect(reply).toContain("\n\nБлок 2. Что учтено");
expect(reply).toContain("\n\nБлок 3. Сводка");
expect(reply).toContain("\n\nБлок 4. Категории обязательств");
expect(reply).toContain("\n\nБлок 5. Подтвержденные позиции к оплате");
expect(reply).not.toContain("эвристический");
}
});