Open-World: закрепить границу просрочки долгов

This commit is contained in:
2026-05-05 12:05:11 +03:00
parent c6024f52eb
commit 264cbcee12
14 changed files with 215 additions and 9 deletions
@@ -1577,6 +1577,7 @@ describe("address compose stage utf8 headers", () => {
expect(reply.responseType).toBe("FACTUAL_LIST");
expect(reply.text).toContain("Проверил должников по сроку жизни задолженности");
expect(reply.text).toContain("Дата среза: 11.04.2026.");
expect(reply.text).toContain("не подтвержденная договорная просрочка или due-date aging");
expect(reply.text).toContain("Приоритет ручной проверки (по возрасту долга, по убыванию):");
expect(reply.text).toContain("1. Контрагент А | договоры:");
expect(reply.text).toContain("2. Контрагент Б | договоры:");
@@ -2752,6 +2753,14 @@ describe("address intent resolver expansion (M2.3a)", () => {
expect(result.intent).toBe("list_receivables_counterparties");
});
it("defers organization-level overdue debt wording to business overview discovery", () => {
const result = resolveAddressIntent(
"\u043a\u0430\u043a\u0430\u044f \u0443 \u043d\u0430\u0441 \u043f\u0440\u043e\u0441\u0440\u043e\u0447\u043a\u0430 \u043f\u043e \u0434\u043e\u043b\u0433\u0430\u043c \u0437\u0430 2020?"
);
expect(result.intent).toBe("unknown");
expect(result.reasons).toContain("unicode_business_overview_debt_due_date_deferred_to_discovery");
});
it("routes reconciliation mismatch wording into open contracts intent", () => {
const result = resolveAddressIntent(
"Покажи контрагентов, по которым сальдо скорее всего не совпадет с их актом сверки. Может, стоит поторопиться и запросить сверку?"
@@ -1992,6 +1992,37 @@ describe("assistant MCP discovery turn input adapter", () => {
expect(result.data_need_graph?.clarification_gaps).toEqual([]);
});
it("routes organization-level overdue debt wording to business overview instead of exact receivables recipes", () => {
const orgName = "\u041e\u041e\u041e \u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u041f\u043b\u044e\u0441";
const result = buildAssistantMcpDiscoveryTurnInput({
userMessage:
"\u043a\u0430\u043a\u0430\u044f \u0443 \u043d\u0430\u0441 \u043f\u0440\u043e\u0441\u0440\u043e\u0447\u043a\u0430 \u043f\u043e \u0434\u043e\u043b\u0433\u0430\u043c \u0437\u0430 2020?",
followupContext: {
previous_discovery_pilot_scope: "open_items_by_counterparty_or_contract",
previous_filters: {
organization: orgName,
as_of_date: "2026-04-23"
}
}
});
expect(result.adapter_status).toBe("ready");
expect(result.should_run_discovery).toBe(true);
expect(result.semantic_data_need).toBe("business overview evidence with bounded analyst interpretation");
expect(result.data_need_graph?.business_fact_family).toBe("business_overview");
expect(result.turn_meaning_ref).toMatchObject({
asked_domain_family: "business_overview",
asked_action_family: "broad_evaluation",
explicit_organization_scope: orgName,
explicit_date_scope: "2020",
unsupported_but_understood_family: "broad_business_evaluation",
stale_replay_forbidden: true
});
expect(result.reason_codes).toContain("mcp_discovery_broad_business_evaluation_route_candidate");
expect(result.reason_codes).not.toContain("mcp_discovery_date_scope_from_followup_context");
expect(result.data_need_graph?.clarification_gaps).toEqual([]);
});
it("resumes an open-scope total clarification loop from saved state when the user resolves the pending period with all-time wording", () => {
const orgName = "ООО Альтернатива Плюс";
const result = buildAssistantMcpDiscoveryTurnInput({
@@ -177,5 +177,15 @@ describe("assistantTurnMeaningPolicy", () => {
expect(profitMargin.asked_action_family).toBe("broad_evaluation");
expect(profitMargin.unsupported_but_understood_family).toBe("broad_business_evaluation");
expect(profitMargin.reason_codes).toContain("broad_business_evaluation_current_turn_signal");
const overdueDebt = policy.resolveAssistantTurnMeaning({
rawUserMessage:
"\u043a\u0430\u043a\u0430\u044f \u0443 \u043d\u0430\u0441 \u043f\u0440\u043e\u0441\u0440\u043e\u0447\u043a\u0430 \u043f\u043e \u0434\u043e\u043b\u0433\u0430\u043c \u0437\u0430 2020?"
});
expect(overdueDebt.explicit_intent_candidate).toBeNull();
expect(overdueDebt.asked_domain_family).toBe("business_summary");
expect(overdueDebt.asked_action_family).toBe("broad_evaluation");
expect(overdueDebt.unsupported_but_understood_family).toBe("broad_business_evaluation");
expect(overdueDebt.reason_codes).toContain("broad_business_evaluation_current_turn_signal");
});
});