ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Спека exact-маршрута payables на дату: confirmed_balance без эвристического финала

This commit is contained in:
2026-04-12 13:46:14 +03:00
parent ca2feab893
commit 1b2ee93176
19 changed files with 2453 additions and 252 deletions
@@ -0,0 +1,254 @@
# Address Query Spec: Confirmed Payables As Of Date
## 1. Контекст проблемы
Запросы вида:
- `кому мы должны на май 2020`
- `кому должны заплатить на 31.05.2020`
- `по кому кредиторка на дату`
относятся к классу **балансных бухгалтерских запросов** и требуют детерминированного расчета открытых обязательств на дату среза.
Текущее поведение в части сценариев использует эвристический shortlist по движениям, что допустимо только как внутренний аварийный режим и не должно быть финальным пользовательским ответом для этого класса запросов.
## 2. Цель
Ввести для payables-вопросов на дату строгий маршрут `payables_confirmed_as_of_date_v1`, который:
- строит подтвержденный реестр обязательств к оплате на дату,
- возвращает только доказуемые позиции,
- не отдает `heuristic_candidates` как финальный ответ,
- при невозможности точного расчета возвращает технически честный `LIMITED_WITH_REASON` с причинами.
## 3. Scope
Входит в scope:
- интенты payables на дату (`кому должны`, `кому заплатить`, `кредиторка на дату`);
- расчет остатка по контрагенту/договору/объекту расчетов;
- категоризация обязательств;
- evidence chain по каждой строке ответа;
- контракт ответа и debug-поля.
Не входит в scope:
- прогнозный cash-flow и приоритизация оплат по бизнес-правилам;
- оптимизация платежного календаря;
- юридическая интерпретация договорных сроков оплаты.
## 4. Канонизация запроса
Пользовательская формулировка должна переводиться в канонический контракт:
- `intent = payables_confirmed_as_of_date`
- `as_of_date = <дата среза>` (например `2020-05-31`)
- `group_by = counterparty`
- `detail_level = contract + settlement_object + source_refs`
- `output_mode = confirmed_balance_only`
Правило периода:
- если задан месяц/год (`май 2020`) и нет явной даты, то `as_of_date = конец_месяца`.
## 5. Архитектурный pipeline
`normalize -> route -> evidence acquisition -> balance calculation -> admissibility gate -> response compose`
### 5.1 Route
Для `payables_confirmed_as_of_date` запрещен прямой пользовательский выход в эвристику.
Разрешенные вычислительные режимы:
1. `direct_balance` (предпочтительно)
2. `reconstructed_balance` (fallback расчета)
3. `limited_exact_unavailable` (честный отказ exact)
### 5.2 Evidence acquisition
Собираемые данные (минимум):
- организация;
- контрагент;
- договор;
- объект расчетов/документ расчетов;
- счет учета;
- сумма;
- период движения;
- связи возникновения/погашения.
### 5.3 Balance calculation
При `direct_balance`:
- используются остатки/регистры на дату среза.
При `reconstructed_balance`:
- рассчитывается:
`balance_as_of = opening + accrued - paid +/- adjustments` на дату среза;
- расчет ведется по ключу:
`organization + counterparty + contract + settlement_object + account`.
### 5.4 Admissibility gate
Позиция включается в confirmed-ответ только если:
- есть идентифицированный контрагент;
- рассчитан остаток на дату;
- остаток `> 0` (для payables);
- есть source refs достаточной силы;
- нет противоречащего сигнала полного закрытия на дату.
Иначе позиция исключается из confirmed output.
## 6. Доменные сущности
### 6.1 `payable_position`
- `organization`
- `counterparty`
- `contract`
- `settlement_object`
- `account`
- `category`
- `currency`
- `opening_amount`
- `accrued_amount`
- `paid_amount`
- `adjusted_amount`
- `balance_as_of`
- `as_of_date`
- `source_refs[]`
### 6.2 `payable_source_ref`
- `source_type`
- `document_ref`
- `register_ref`
- `movement_ref`
- `period`
- `amount`
- `role_in_chain` (`origin|payment|adjustment|reclass|balance_snapshot`)
### 6.3 `payable_evidence_bundle`
- `position_id`
- `evidence_strength` (`weak|medium|strong`)
- `balance_confirmed` (`true|false`)
- `balance_derivation_mode` (`direct_balance|reconstructed_balance`)
- `missing_fields[]`
- `conflicting_signals[]`
### 6.4 `payable_category`
- `supplier_contractor`
- `bank_credit`
- `tax_state`
- `payroll_related`
- `other`
## 7. Политика fallback
Для `payables_confirmed_as_of_date`:
- запрещено возвращать `heuristic_candidates` как финальный пользовательский ответ;
- если exact не собран, вернуть `LIMITED_WITH_REASON` с перечислением:
- каких полей/связок не хватило,
- на каком шаге не пройдена доказуемость,
- что нужно для точного ответа.
Допускается внутренний heuristic-pass только для диагностики, без публикации как фактического ответа.
## 8. Контракт ответа
### 8.1 Confirmed ответ (`FACTUAL_LIST`)
Обязательные блоки:
1. Статус результата (`confirmed_balance`)
2. Дата среза и basis расчета
3. Сводка (контрагентов, общая сумма)
4. Категории обязательств
5. Реестр подтвержденных позиций
6. Source refs (минимум по top-N)
### 8.2 Exact недоступен (`LIMITED_WITH_REASON`)
Обязательные блоки:
1. Что именно не удалось доказать
2. Какие поля/связки отсутствуют
3. На каком этапе сорвался расчет
4. Что нужно для подтвержденного ответа
## 9. Debug/Telemetry требования
Добавить/соблюдать поля:
- `requested_result_mode = confirmed_balance`
- `result_mode = confirmed_balance | limited_exact_unavailable`
- `balance_confirmed = true | false`
- `balance_derivation_mode = direct_balance | reconstructed_balance | unavailable`
- `selected_recipe_effective`
- `evidence_strength`
- `admissibility_gate_outcome`
- `missing_required_evidence[]`
Инвариант:
- если `balance_confirmed = false`, то `response_type != FACTUAL_LIST` для данного интента.
## 10. Acceptance criteria
Кейс:
- запрос: `кому мы должны на май 2020`
- ожидаемая дата среза: `31.05.2020`
Критерии приемки:
1. Запрос маршрутизируется в `payables_confirmed_as_of_date`.
2. Финальный ответ либо `confirmed_balance`, либо `LIMITED_WITH_REASON` exact-недоступности.
3. Нет финального эвристического shortlist для этого интента.
4. По каждой подтвержденной строке есть evidence chain.
5. Категории обязательств разделены и не смешиваются в неразмеченный “общий топ”.
6. В ответе явно указана дата среза и способ расчета.
## 11. Тестовый контур (минимум)
Unit:
- канонизация месяца в `as_of_date`;
- route lock на `payables_confirmed_as_of_date`;
- запрет heuristic final output;
- admissibility gate.
Integration:
- `direct_balance` happy path;
- `reconstructed_balance` fallback path;
- `limited_exact_unavailable` path с понятной причиной.
Regression:
- сценарии с сокращениями контрагентов;
- follow-up после списков;
- кейсы с банками/депозитами/госорганами.
## 12. Rollout
1. Feature flag: `FEATURE_PAYABLES_CONFIRMED_AS_OF_V1`.
2. Shadow mode (сравнение старого/нового результата без выдачи пользователю).
3. Limited pilot на продукционных диалогах.
4. Полный switch при достижении приемочных метрик.
## 13. Запреты
Для `payables_confirmed_as_of_date` запрещено:
- возвращать “кандидаты на проверку” как финальный factual-answer;
- использовать формулировки платежной рекомендации при `balance_confirmed=false`;
- подменять расчет обязательств простым списком движений.