TZ_Assistant_Mode_vNext.md

## Переход от route-plan ответа к нормальному диалоговому ответу по данным базы

---

## 1. Цель этапа

Превратить текущий Assistant Mode из технического интерфейса, который показывает:

* decomposition,
* route plan,
* trace,
* sandbox-пояснения,

в рабочий диалоговый режим, который:

* принимает вопрос пользователя;
* прогоняет его через normalizer/decomposition;
* выполняет реальный retrieval/query по маршруту;
* получает фактические данные;
* собирает **человекочитаемый ответ на русском языке**;
* показывает debug только как дополнительный раскрываемый слой.

---

## 2. Текущее состояние

Сейчас Assistant Mode работает как **planner/debug shell**:

**что уже есть:**

* ввод вопроса;
* decomposition / route selection;
* trace id;
* debug drawer;
* session-based диалоговая оболочка.

**что отсутствует:**

* реальный factual retrieval по данным базы;
* route-specific execution с возвратом нормальных данных;
* финальный answer composition по результатам retrieval;
* русскоязычный user-facing reply policy;
* разделение user-answer и technical-debug.

Комментарий:
Сейчас пользователь получает “planned routes / sandbox retrieval mode / trace”,
а должен получать ответ по сути вопроса.

---

## 3. Новая целевая архитектура

Нужен полный контур:

**User message → Normalizer → Execution Planner → Route-specific Retrieval → Result Normalization → Final Answer Composer → Assistant Reply**

---

## 4. Что должно происходить после сообщения пользователя

## 4.1. Шаг 1 — Normalization

Оставляем текущий `normalizer_v2.x`:

* scope filter;
* fragments;
* execution readiness;
* route status;
* clarification/out-of-scope detection.

## 4.2. Шаг 2 — Execution planning

Для каждого исполнимого fragment:

* определить маршрут;
* собрать execution plan;
* передать fragment в route-specific executor.

## 4.3. Шаг 3 — Real retrieval / query

Вместо sandbox plan нужно выполнять **реальный вызов backend data layer**:

* к 1С / хранилищу / API / query handlers;
* получать фактические данные;
* нормализовать их в общий result schema.

## 4.4. Шаг 4 — Final answer composition

На основе:

* user message,
* fragments,
* data results,
* fallback state

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

---

# 5. Главный принцип нового режима

## Пользователь не должен видеть:

* planned routes;
* store canonical selected;
* sandbox retrieval mode;
* raw trace explanation;
* транслит;
* служебные внутренние названия маршрутов.

## Пользователь должен видеть:

* нормальный русский ответ;
* если данных нет — понятное объяснение;
* если нужен clarification — уточняющий вопрос;
* если часть вопроса вне контура — вежливое ограничение;
* при желании — кнопку “Показать технический разбор”.

---

# 6. Новый слой: Route-specific factual retrieval

---

## 6.1. Для каждого route нужен executor

Нужно реализовать route executors как отдельные backend handlers.

### A. `hybrid_store_plus_live`

Для causal / cross-entity / chain queries:

* искать связанные сущности;
* возвращать:

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

### B. `store_feature_risk`

Для anomaly / rule-check / suspicious scan:

* искать проблемные объекты/записи;
* возвращать:

  * сущность,
  * причина попадания,
  * риск-признак,
  * релевантные поля.

### C. `batch_refresh_then_store`

Для overview / ranking / top / period risk:

* возвращать агрегаты;
* топы;
* summary blocks;
* приоритеты проверки;
* зоны риска.

### D. `store_canonical`

Для canonical factual path:

* выдавать прямую фактическую информацию по каноническому учётному представлению.

### E. `live_mcp_drilldown` (если уже подключён)

Для точечного drilldown:

* конкретный документ;
* конкретная проводка;
* конкретный объект;
* source-of-record.

---

## 6.2. Все executors должны возвращать unified result schema

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

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

```json
{
  "fragment_id": "F1",
  "route": "hybrid_store_plus_live",
  "status": "ok | empty | partial | error",
  "result_type": "list | summary | object | chain | ranking",
  "items": [],
  "summary": {},
  "evidence": [],
  "errors": []
}
```

---

# 7. Новый слой: Result normalization

Перед финальной генерацией ответа retrieval-результаты нужно привести в нормализованный вид.

Нужен слой:

* `normalize_retrieval_result(fragment, raw_backend_result)`

Задача:

* привести все маршруты к общему формату;
* отдать composer понятный и предсказуемый payload.

---

# 8. Новый слой: Final Answer Composer

Это ключевой этап.

## 8.1. Что он получает

На вход:

* `user_message`
* `normalized_query_v2_x`
* `resolved_fragments`
* `retrieval_results`
* `fallback state`
* `session context`

## 8.2. Что он должен делать

Собирать **один связный user-facing ответ**.

### Если один fragment

Отвечать прямо по вопросу.

### Если несколько fragments

Собирать один ответ с понятной структурой:

* сначала общий вывод;
* потом блоки по подзадачам;
* без ощущения, что это 5 несвязанных кусков.

### Если часть вопроса не выполнима

Отвечать по доступной части и мягко пояснять ограничения.

---

## 8.3. Ответ должен быть на русском

Жёсткое требование:

* никакого транслита;
* никаких англоязычных route names в тексте;
* никаких внутренних служебных формулировок.

---

## 8.4. Ответ не должен быть “сухой отладкой”

Нельзя выводить пользователю:

* `planned routes`
* `trace`
* `store canonical selected`
* `fallback_type=...`

Это всё — только в debug drawer.

---

# 9. Типы user-facing ответов

---

## 9.1. Normal factual reply

Когда данные найдены.

Пример:

* перечисление поставщиков с хвостами;
* список проблемных объектов;
* summary по рискам;
* ranking.

## 9.2. Empty result reply

Когда запрос корректен, но ничего не найдено.

Пример:

> По текущим данным явных проблемных записей по этому условию не найдено.

## 9.3. Partial reply

Когда по части вопроса данные найдены, по части — нет.

## 9.4. Clarification reply

Когда нужно уточнение.

## 9.5. Out-of-scope reply

Когда вопрос не про базу компании.

## 9.6. Backend error reply

Когда retrieval сломался технически.

Пример:

> Не удалось получить данные из контура. Попробуйте повторить запрос или уточнить формулировку.

---

# 10. Нужно разделить два уровня ответа

---

## 10.1. User Reply

То, что человек видит в чате.

## 10.2. Debug Payload

То, что раскрывается по кнопке:

* fragments
* execution readiness
* route status
* no_route_reason
* retrieval status
* trace id

Это должно жить отдельно.

---

# 11. Что изменить в GUI

---

## 11.1. Assistant message bubble

В ответе ассистента должен отображаться:

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

## 11.2. Debug toggle

Кнопка:

* `Показать разбор`
  или
* `Технические детали`

Внутри:

* decomposition;
* routes;
* fragments;
* trace id;
* backend status;
* fallback state.

## 11.3. Loading states

Во время выполнения:

* `Разбираю запрос`
* `Ищу данные`
* `Собираю ответ`

---

# 12. Что изменить в backend API

Нужен нормальный assistant endpoint, который возвращает уже готовый user reply.

## Пример

`POST /api/assistant/message`

### Request

```json
{
  "session_id": "...",
  "message": "...",
  "mode": "assistant",
  "period_hint": "...",
  "business_context": "..."
}
```

### Response

```json
{
  "ok": true,
  "assistant_reply": "человекочитаемый ответ",
  "reply_type": "factual | clarification | out_of_scope | partial | empty | error",
  "debug": {
    "trace_id": "...",
    "fragments": [...],
    "routes": [...],
    "retrieval_status": [...]
  }
}
```

---

# 13. Что логировать

Для каждого сообщения логировать:

* `session_id`
* `message_id`
* `user_message`
* `normalizer_output`
* `execution_plan`
* `retrieval_calls`
* `retrieval_results_raw`
* `retrieval_results_normalized`
* `assistant_reply`
* `reply_type`
* `trace_id`

Это пригодится потом для field-based hardening.

---

# 14. Минимальный MVP этого этапа

Чтобы не расползтись, можно сделать MVP так:

### Этап MVP-1

Сделать хотя бы 2 полноценных route executor:

* `hybrid_store_plus_live`
* `store_feature_risk`

И уже через них показать нормальный user-facing reply.

### Этап MVP-2

Добавить:

* `batch_refresh_then_store`
* `store_canonical`

### Этап MVP-3

Дополировать:

* partial replies
* better formatting
* richer debug drawer

---

# 15. Формат ответа ассистента

Ответ должен быть:

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

### Пример плохого ответа

> Planned routes: store canonical. Sandbox mode. Trace...

### Пример допустимого ответа

> По текущему запросу найдены проблемные хвосты по нескольким поставщикам.
> Основные расхождения связаны с оплатами без корректного закрытия и неполной связкой документов.
> Ниже показаны контрагенты и проблемные цепочки.

---

# 16. Что НЕ делать на этом этапе

Не надо сейчас:

* строить суперсложную агентную систему;
* делать память на долгий диалог;
* пытаться решить все типы route сразу идеально;
* снова уходить в synthetic eval hardening;
* показывать пользователю внутреннюю кухню как основной результат.

---

# 17. Критерии приёмки

Этап считается принятым, если:

1. Assistant Mode возвращает **русский человекочитаемый ответ**, а не route plan;
2. debug остаётся доступен, но вынесен отдельно;
3. хотя бы для 2 route’ов работает полный factual loop:

   * question → retrieval → factual reply;
4. out-of-scope / clarification / partial fallback корректно отображаются в чате;
5. decomposition mode не сломан;
6. транслит и технический мусор исчезли из основного ответа.

---

# 18. Артефакты, которые должен выдать Codex

1. `docs/assistant_mode_vnext_spec.md`
2. `docs/route_executor_contracts.md`
3. `docs/final_answer_composer_spec.md`
4. backend endpoint для assistant reply
5. unified retrieval result schema
6. GUI update для user-facing reply + debug drawer
7. `docs/known_limits_current_routes.md`

---

# 19. Короткий итог

Следующий шаг — это уже **не normalizer**, а:

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

Если хочешь, я следующим сообщением сделаю ещё **короткую жёсткую версию этого ТЗ для вставки в Codex**.
