TZ_Assistant_Mode_retrievalLAYER.md

Да. Ниже даю **расширенный набор правил для retrieval/execution layer** именно под бухгалтерский контекст, чтобы `executeHybrid` и соседние executors не жили на одном `GUID` и одном `account_hint`, а реально тащили **избыточный набор ограничений и признаков**. Это прямо ложится на ваш текущий контур `route-specific retrieval` и `unified result schema`, который уже зафиксирован в vNext ТЗ.  

Это не замена normalizer, а **расширение retrieval contract**: LLM/normalizer должен отдавать не только route, но и плотный набор бухгалтерских ограничителей, а retrieval обязан их исполнять.

---

# Расширение правил retrieval-слоя под бухгалтерский контекст

## 1. Главный принцип

Для бухгалтерского ассистента **нельзя** строить retrieval только по:

* `guid`
* `account_hint`
* общему route
* одной сущности верхнего уровня

Retrieval должен работать по **многослойному бухгалтерскому профилю запроса**.

Минимальный обязательный набор слоёв:

1. **счета / субсчета**
2. **тип участка учёта**
3. **тип документов**
4. **тип движения**
5. **тип связи между сущностями**
6. **тип аномалии / конфликта**
7. **период**
8. **контрагент / договор / объект / номенклатура / ОС / статья / подразделение**
9. **стадия жизненного цикла**
10. **исключающие условия**
11. **приоритет ранжирования**
12. **ожидаемый тип объяснения**

---

## 2. Новый обязательный retrieval contract

Каждый routed fragment должен передаваться в executor не в виде “route + hints”, а в виде расширенного `semantic_retrieval_profile`.

Примерно так:

```json
{
  "fragment_id": "F1",
  "route": "hybrid_store_plus_live",
  "query_subject": "bank_settlement_mismatch",
  "account_scope": ["51", "60"],
  "subaccount_scope": [],
  "domain_scope": ["bank", "settlements", "supplier_payments"],
  "document_types": ["bank_statement", "payment_order", "receipt", "settlement_document"],
  "entity_types": ["counterparty", "contract", "document", "posting"],
  "period_scope": {
    "from": null,
    "to": null,
    "granularity": "month"
  },
  "relation_patterns": [
    "document_to_posting",
    "payment_to_settlement",
    "statement_to_document"
  ],
  "lifecycle_stage_filters": [
    "created",
    "posted",
    "closed",
    "reconciled"
  ],
  "anomaly_patterns": [
    "missing_link",
    "wrong_document_type",
    "broken_closure",
    "posting_mismatch"
  ],
  "ranking_basis": [
    "financial_impact",
    "repeatability",
    "closure_risk"
  ],
  "excluded_interpretations": [
    "simple_payment_delay",
    "amount_only_anomaly"
  ],
  "explanation_focus": [
    "why_selected",
    "where_chain_breaks",
    "what_business_risk"
  ]
}
```

---

## 3. Общие правила для всех retrieval executor’ов

## 3.1. Поиск всегда строится не по одному измерению, а по пересечению признаков

Использовать одновременно:

* счёт
* тип документа
* статус документа
* связанную проводку
* период
* предметную область
* relation pattern
* anomaly pattern

Недопустимо:
если нет `guid`, снимать ограничения и лить в ответ весь массив.

Если `guid` нет, retrieval должен переходить на **semantic narrowing**, а не на `full scan without accounting discrimination`.

---

## 3.2. Любой account hint должен разворачиваться в бухгалтерский контекст

Если в вопросе или normalizer output есть `51`, этого недостаточно.
Нужно автоматически достраивать:

* bank domain
* возможные документы: выписка, платежное поручение, списание с р/с, поступление на р/с
* возможные связи: банк → документ → проводка → расчётный контур
* возможные конфликты: документ есть / нет, проводка есть / нет, не тот тип документа, неверный контур закрытия

То есть `51` — это не фильтр, а **семантический вход в набор поисковых правил**.

---

## 3.3. Если вопрос про аномалию, нельзя ранжировать только по сумме

Если пользователь не просил explicitly “самые большие суммы”, то anomaly retrieval обязан учитывать не только money magnitude, но и:

* отсутствие связанной записи;
* рассогласование между документом и проводкой;
* нарушение жизненного цикла;
* повторяемость отклонения;
* влияние на закрытие периода;
* несоответствие карточки и движения;
* конфликт между участками учёта.

---

## 3.4. Если вопрос про цепочку, retrieval должен искать разрыв, а не просто соседние документы

Для `hybrid_store_plus_live` поиск обязан различать:

* наличие документов в цепочке;
* корректность связей между ними;
* полноту прохождения этапов;
* расхождение статусов;
* конфликт проводки и первички;
* отсутствие ожидаемого продолжения;
* наличие “ложного закрытия” не тем документом.

Это соответствует самой идее `hybrid_store_plus_live` в вашем vNext ТЗ: causal / cross-entity / chain queries должны возвращать связи, документы, оплаты, проводки и признаки разрыва цепочки. 

---

# 4. Расширенные бухгалтерские измерения для retrieval

## 4.1. Слой счетов

Нужно учитывать не только основной счёт, но и:

* корреспондирующие счета;
* типовой соседний контур;
* признак “счёт упомянут явно” vs “счёт выведен косвенно”;
* приоритет основного счёта;
* исключённые счета.

### Примеры:

* `51` → банк, движения ДС, документы банка, платежи, выписки
* `60` → поставщики, расчёты, закрытие обязательств
* `62` → покупатели, выручка, оплаты, задолженность
* `76` → прочие расчёты, подвешенные взаимосвязи, нестандартные хвосты
* `97` → расходы будущих периодов, сроки списания, график, корректность продолжения жизненного цикла
* `01/02/08` → ОС, ввод в эксплуатацию, амортизация, капитальные вложения, карточка объекта
* `19/68` → НДС, принятие к вычету, книга покупок/продаж, закрытие налогового контура
* `10/41/43` → ТМЦ, товар, выпуск, остатки, движение запасов
* `20/23/25/26/44` → затраты, распределение, закрытие, себестоимость

---

## 4.2. Слой участков учёта

Для каждого запроса нужно фиксировать `domain_scope`:

* банк
* поставщики
* покупатели
* склад / запасы
* ОС
* НМА
* РБП
* НДС
* зарплата
* затраты
* закрытие периода
* прочие расчёты
* договорной контур
* авансы
* налоги
* денежные документы
* касса
* производство

Это нужно, чтобы один и тот же счёт не тянул нерелевантный участок.

---

## 4.3. Слой документов

Retrieval обязан учитывать тип документа как first-class filter.

Категории:

* банковская выписка
* платежное поручение
* поступление товаров/услуг
* реализация
* счет-фактура
* корректировка
* акт сверки
* авансовый отчет
* кассовый ордер
* ввод в эксплуатацию ОС
* принятие к учету ОС
* начисление амортизации
* списание РБП
* закрытие месяца
* регламентная операция
* ручная операция
* корректировка долга
* перемещение / списание / оприходование ТМЦ

Если пользователь спрашивает про “не тем документом закрыто”, retrieval обязан искать **ошибочный тип документа в ожидаемой цепочке**, а не просто все связанные документы.

---

## 4.4. Слой сущностей

Поддерживать entity filters:

* контрагент
* договор
* организация
* документ
* проводка
* номенклатура
* склад
* подразделение
* сотрудник
* объект ОС
* статья затрат
* проект
* заказ
* налоговая запись
* регистр/движение
* период закрытия

Если вопрос multi-entity, retrieval обязан различать **главную сущность** и **подтверждающие сущности**.

---

## 4.5. Слой жизненного цикла

Очень важный слой.
Почти все хорошие бухгалтерские аномалии — это не “не та сумма”, а **сломанный lifecycle**.

Для каждой сущности retrieval должен пытаться определить стадию:

* создан
* проведён
* не проведён
* частично связан
* закрыт
* не закрыт
* сторнирован
* отменён
* завис
* повторён
* перенесён
* закрыт не тем документом
* есть продолжение / нет продолжения
* цепочка оборвана
* финальный статус противоречит промежуточным движениям

Это особенно критично для:

* 97
* ОС
* поставщики/авансы
* НДС
* закрытие периода
* расчёты по 60/62/76

---

# 5. Набор anomaly patterns, которые надо заложить в retrieval

Ниже даю именно как **словарь аномалий**, который можно использовать в `semantic_retrieval_profile.anomaly_patterns`.

## 5.1. Missing link

Ожидаемая связь между сущностями отсутствует.

Примеры:

* документ есть, проводки нет;
* платёж есть, закрывающего документа нет;
* ОС есть, начисления есть/нет, но карточка не бьётся;
* запись в одном контуре есть, в смежном нет.

## 5.2. Wrong document type

Закрытие, отражение или продолжение прошло не тем типом документа.

## 5.3. Broken lifecycle

Объект застрял между стадиями.

## 5.4. Posting mismatch

Проводка не соответствует документу, счёту, участку или ожидаемому направлению движения.

## 5.5. Cross-domain inconsistency

Один участок говорит одно, другой — другое.

Примеры:

* банк подтверждает движение, расчётный контур не закрылся;
* документ прихода есть, складское движение не совпадает;
* ОС в карточке в одном статусе, амортизационный контур в другом.

## 5.6. Closure risk

Запись влияет на корректность закрытия периода.

## 5.7. Repeated anomaly

Одна и та же проблема повторяется серийно.

## 5.8. Silent orphan

Запись выглядит спокойной по сумме, но сиротская по связям и жизненному циклу.

## 5.9. Amount-independent risk

Риск не по величине суммы, а по структуре нарушения.

## 5.10. Manual intervention suspicion

Есть признаки ручной коррекции, нестандартной операции или обходного закрытия.

---

# 6. Правила дифференциации по ключевым бухгалтерским зонам

## 6.1. Банк / 51

Если запрос касается 51, retrieval должен автоматически учитывать:

* банковские документы;
* платежные поручения;
* выписки;
* приход/расход ДС;
* связанный расчётный контур;
* закрытие обязательства;
* аванс / оплата / зачет;
* корреспондирующие счета;
* совпадение назначения платежа и учетного отражения;
* факт отражения в выписке;
* факт проведения документа;
* разрыв между движением денег и закрытием расчета.

### Специальные паттерны:

* оплата есть, закрытия обязательства нет;
* выписка есть, документ-основание не найден;
* движение пошло не в тот договор / не в того контрагента;
* банк закрылся, а расчеты зависли;
* проблема не в платеже, а в документе, который интерпретировал платёж.

---

## 6.2. Поставщики / 60

Учитывать:

* контрагент;
* договор;
* документ поступления;
* оплата;
* зачет аванса;
* закрытие обязательства;
* просроченный хвост;
* расхождение по актам/счётам/поступлению/оплате;
* зависшие незакрытые позиции;
* повторяемость по контрагенту;
* влияние на закрытие периода.

### Специальные паттерны:

* хвост без движения после оплаты;
* поступление есть, расчёт не закрылся;
* аванс есть, поставка не бьётся;
* несколько документов спорят за одну оплату;
* один контрагент серийно создаёт одинаковый дефект.

---

## 6.3. Покупатели / 62

Учитывать:

* реализация;
* оплата;
* аванс;
* зачет;
* дебиторка;
* договор;
* закрытие выручки;
* документ основания;
* банковое подтверждение;
* НДС-связка.

### Паттерны:

* оплата есть, реализация не закрылась;
* аванс завис;
* дебиторка выглядит искусственно живой;
* проводка есть, но цепочка первички неполна.

---

## 6.4. Прочие расчёты / 76

Зона повышенного риска.
Retrieval должен относиться к 76 как к зоне, где часто лежат:

* нестандартные хвосты;
* временные костыли;
* переходные записи;
* плохо закрытые взаимосвязи.

Нужны более жёсткие правила на:

* давность;
* отсутствие продолжения;
* слабую связанность;
* нетипичный тип документа;
* ручные операции;
* странные корреспонденции.

---

## 6.5. РБП / 97

Если запрос про 97, retrieval обязан смотреть не только остаток и сумму, но и:

* дату возникновения;
* срок списания;
* график списания;
* факт начала списания;
* факт завершения списания;
* разрыв между сроком и поведением записи;
* документ-источник;
* связанный объект/основание;
* продолжение жизненного цикла.

### Паттерны:

* запись давно живёт, но логика списания не выполняется;
* срок наступил, движения нет;
* объект уже должен был перейти в другой статус;
* карточка/основание есть, но дальше жизни нет;
* запись выглядит закрытой формально, но по связанным движениям не завершена.

---

## 6.6. ОС / 01 / 02 / 08

Retrieval обязан учитывать:

* карточку ОС;
* документ принятия к учету;
* ввод в эксплуатацию;
* инвентарный объект;
* амортизацию;
* счет 08 как источник;
* корректность перехода 08 → 01;
* статус эксплуатации;
* списание/выбытие;
* соответствие карточки и начислений.

### Паттерны:

* объект заведен, но lifecycle не доведён;
* амортизация идет/не идет в противоречии со статусом;
* карточка есть, движений недостаточно;
* ввод в эксплуатацию и отражение по счетам не совпадают;
* объект сиротский по связям.

---

## 6.7. НДС / 19 / 68

Учитывать:

* счёт-фактура;
* поступление/реализация;
* принятие к вычету;
* книга покупок/продаж;
* период вычета;
* отражение в налоговом контуре;
* связь с первичкой;
* расхождение между бухгалтерским и налоговым отражением.

### Паттерны:

* НДС висит без нормального продолжения;
* документ есть, вычет не бьётся;
* вычет попал не в тот период;
* запись живёт без подтверждающей цепочки;
* топ по НДС не должен подменять вопросы про ОС или банк.

---

## 6.8. Закрытие периода

Если пользователь спрашивает о проблемах, “ломающих период”, retrieval должен повышать вес признаков:

* незакрытый хвост;
* конфликт между участками;
* документ/движение в граничных датах;
* сиротские остатки;
* серия однотипных нарушений;
* объекты, затрагивающие регламентные операции;
* следы ручных коррекций;
* зависшие авансы/расчёты/РБП/ОС.

---

# 7. Правила relation patterns для hybrid / chain retrieval

Для `executeHybrid` нужны предопределённые relation patterns.

## 7.1. payment_to_settlement

Платёж ↔ расчёт ↔ закрытие обязательства

## 7.2. document_to_posting

Документ ↔ проводка

## 7.3. statement_to_document

Банковская выписка ↔ внутренний документ

## 7.4. asset_card_to_depreciation

Карточка ОС ↔ начисление амортизации

## 7.5. deferred_expense_to_writeoff

РБП ↔ график/списание

## 7.6. invoice_to_vat

Первичка ↔ счёт-фактура ↔ НДС

## 7.7. receipt_to_stock_movement

Поступление ↔ складское движение

## 7.8. contract_to_documents

Договор ↔ серия документов / хвостов / закрытий

Если route chain-based, executor должен явно понимать, **какой relation pattern проверяет**, а не просто тянуть “всё около темы”.

---

# 8. Правила ранжирования

Нужен не один ranking score, а составной.

## 8.1. Базовые факторы ранжирования

* финансовое влияние
* давность
* повторяемость
* степень незавершённости lifecycle
* количество сломанных связей
* влияние на закрытие периода
* пересечение с несколькими участками учёта
* типовая/нетиповая проводка
* ручное вмешательство
* наличие противоречащих документов
* отсутствие ожидаемого продолжения

## 8.2. Важное правило

Если пользователь спрашивает “не по сумме, а по риску”, то фактор суммы не должен быть доминирующим.

---

# 9. Excluded interpretations — обязательный блок

Очень полезный слой.
Чтобы retrieval не ехал в ближайшую похожую тему, надо явно передавать, **что нельзя считать ответом**.

Примеры:

* не считать любую большую сумму аномалией;
* не сводить вопрос про ОС к НДС;
* не сводить вопрос про 51 к рейтингу контрагентов вообще;
* не считать любой незакрытый документ доказательством хвоста без проверки связи;
* не отвечать на вопрос про lifecycle просто списком документов;
* не подменять “не тем документом закрыто” на “есть документы по контрагенту”.

---

# 10. Что добавить в executeHybrid прямо практически

Ниже уже почти как техзадание на реализацию.

## 10.1. Если GUID нет, не брать весь набор данных

Вместо этого строить фильтрацию по пересечению:

* `account_scope`
* `domain_scope`
* `document_types`
* `entity_types`
* `relation_patterns`
* `anomaly_patterns`
* `period_scope`
* `excluded_interpretations`

## 10.2. Ввести `query_subject`

Категории верхнего уровня, например:

* `bank_settlement_mismatch`
* `supplier_tail_analysis`
* `customer_closure_gap`
* `deferred_expense_lifecycle_anomaly`
* `fixed_asset_card_mismatch`
* `vat_chain_conflict`
* `period_closure_risk`
* `cross_entity_breakage`
* `document_posting_conflict`

## 10.3. Ввести `explanation_focus`

Чтобы retrieval сразу собирал evidence под тип ответа:

* `why_selected`
* `where_chain_breaks`
* `why_risky`
* `why_not_closed`
* `why_ranked_high`
* `what_conflicts_with_what`

## 10.4. Ввести `evidence pack`

На каждый top item возвращать не только сущность, но и:

* ключевой счёт
* документ
* статус
* связанная проводка
* отсутствующая связь
* lifecycle gap
* period impact
* selection_reason
* business_interpretation

---

# 11. Что добавить в result schema

Расширить unified result schema, чтобы answer composer мог собирать нормальный ответ по сути, а не по name/count/id. Это согласуется с вашим целевым слоем `Result normalization` и `Final Answer Composer`.

```json
{
  "fragment_id": "F1",
  "route": "hybrid_store_plus_live",
  "status": "ok",
  "result_type": "chain",
  "items": [
    {
      "entity_type": "counterparty",
      "entity_id": "....",
      "label": "ООО ...",
      "account_context": ["51", "60"],
      "document_context": ["bank_statement", "payment_order"],
      "selection_reason": [
        "оплата отражена",
        "закрывающий документ не подтвержден",
        "цепочка расчета оборвана"
      ],
      "risk_factors": [
        "broken_lifecycle",
        "missing_link",
        "closure_risk"
      ],
      "business_interpretation": "деньги прошли, но обязательство не закрылось корректно",
      "evidence": [],
      "confidence": "medium"
    }
  ],
  "summary": {
    "ranking_basis": ["closure_risk", "repeatability", "financial_impact"]
  },
  "errors": []
}
```

---

# 12. Минимальный набор бухгалтерских правил, который я бы считал must-have

Если прямо урезать до ядра, то retrieval должен обязательно учитывать:

1. `account_scope`
2. `domain_scope`
3. `document_types`
4. `entity_types`
5. `relation_patterns`
6. `anomaly_patterns`
7. `lifecycle_stage_filters`
8. `period_scope`
9. `excluded_interpretations`
10. `ranking_basis`
11. `explanation_focus`

Без этого вы снова получите:
нормализатор понял вопрос,
route выбрали правильно,
а retrieval принёс один и тот же массив “вокруг темы”.

---

# 13. Короткая формулировка для команды

Если тебе нужен короткий месседж в работу, то вот он:

**Нужно расширить executeHybrid и соседние retrieval executors от модели “GUID-or-full-scan” к модели “semantic retrieval profile”.
Фильтрация должна строиться не только по счету, но и по участку учёта, типам документов, типам сущностей, relation patterns, lifecycle stage, anomaly patterns, excluded interpretations и ranking basis.
Если GUID отсутствует, executor не имеет права брать весь датасет; он обязан делать semantic narrowing по бухгалтерскому профилю запроса.**

---

# 14. Что я бы добавил ещё сверх этого

Отдельно заложить в retrieval слой:

* транслит-нормализацию бухгалтерских терминов до исполнения;
* словарь синонимов по участкам учёта;
* бухгалтерские alias-паттерны: “хвост”, “зависло”, “не бьётся”, “не тем закрылось”, “жизни не случилось”, “сломало период”, “сирота”, “висит”, “криво пошло”;
* map “бытовой язык → retrieval constraints”.

Это уже не про answer composer, а про то, чтобы retrieval получал нормальный предметный профиль даже из кривого человеческого запроса.


