# MVP: процесс v2

## 1. Общее описание

Процесс v2 в текущем MVP ориентирован в первую очередь на **документацию проекта**, но роутер также поддерживает `GENERAL / GENERAL_QA / SUMMARY` для общих обзорных вопросов. Для документных веток нужна активная RAG-сессия с проиндексированными документами.

Это **узкий MVP**, а не полная target architecture. Поддерживаются три маршрута:

- `GENERAL`
- `GENERAL_QA`
- `SUMMARY`
- `DOCS`
- `DOC_EXPLAIN`
- `SUMMARY`
- `FIND_FILES`

Запрос проходит следующие смысловые этапы:

1. проверка готовности сессии;
2. intent routing;
3. формирование retrieval-параметров;
4. retrieval из `DOCS RAG`;
5. минимальная сборка evidence;
6. запуск task-focused workflow нужной ветки;
7. формирование ответа.

```mermaid
flowchart TB
  subgraph api [API]
    RS[RequestService]
  end
  subgraph runtime [Agent runtime]
    AR[AgentRuntime]
    PR[ProcessRunner]
  end
  subgraph v2 [Процесс v2]
    P2[V2Process]
    IR[V2IntentRouter]
    POL[V2RetrievalPolicyResolver]
    AD[V2RagRetrievalAdapter]
    RSR[RagSessionRetriever]
    ASM[DocsEvidenceAssembler]
  end
  subgraph rag [Пакет rag]
    RR[RagRepository]
  end
  subgraph wf [Workflow]
    SUM[DocsExplainSummaryGraph]
    FF[DocsExplainFindFilesGraph]
  end
  LLM[AgentLlmService]
  RS --> AR --> PR --> P2
  P2 --> IR --> POL --> AD --> RSR --> RR
  AD --> ASM
  ASM --> SUM
  ASM --> FF
  SUM --> LLM
```

Клиент указывает `process_version: v2`. Без `active_rag_session_id` в сессии процесс возвращает сообщение об ошибке. Иначе выполняется цепочка:

маршрутизация → `RetrievalPlan` → retrieval строк из `DOCS RAG` → минимальная сборка evidence → ветвление по `subintent` → запуск workflow.

### Реализованные домены, интенты и сабинтенты

В коде заданы константы `V2Domain`, `V2Intent`, `V2Subintent`. Сейчас процесс intentionally ограничен одной рабочей областью.

| Уровень | Значение (строка) | Реализация |
|--------|-------------------|------------|
| **Домен (routing_domain)** | `DOCS` | Единственный поддерживаемый домен: документация проекта. |
| **Интент** | `DOC_EXPLAIN` | Единственный интент: объяснение по документации. |
| **Сабинтент** | `SUMMARY` | Объяснение темы по SUMMARY-блокам документации. |
| **Сабинтент** | `FIND_FILES` | Поиск путей к документам, где описана нужная сущность или тема. |

Итого в текущем MVP реализована **одна** рабочая тройка домен×интент: `DOCS` + `DOC_EXPLAIN`, с **двумя** ветками по сабинтенту.

---

## 2. Этапы вне workflow (внутри `V2Process.run`)

### 2.1. `V2IntentRouter.route`

| | |
|--|--|
| **Название** | Маршрутизация запроса (v2) |
| **Задача** | Определить домен, интент, subintent и извлечь якоря из текста. |
| **Вход** | `user_query: str` (текст сообщения пользователя). |
| **Выход** | `V2RouteResult`: `routing_domain`, `intent`, `subintent`, `user_query`, `normalized_query`, `target_terms`, `anchors` (`V2RouteAnchors`), `confidence`. |
| **Как работает** | Router реализован по схеме **LLM-first**: `normalization` → `target_terms`/`anchors extraction` → `LLM router` → `deterministic validator` → `fallback`. LLM является **основным селектором маршрута**. Deterministic-слой больше не выбирает маршрут по умолчанию: он отвечает только за extraction, валидацию enum/комбинаций и fallback при сломанном или невалидном ответе LLM. В trace пишется событие `intent_routed`. |

Код: `src/app/core/agent/processes/v2/intent_router/router.py`, `modules/normalizer.py`, `modules/target_terms.py`, `modules/anchors.py`, `routers/llm.py`, `routers/validator.py`, `routers/fallback.py`.

---

### 2.2. `V2RetrievalPolicyResolver.resolve`

| | |
|--|--|
| **Название** | Политика retrieval для v2 |
| **Задача** | По результату роутинга выбрать профиль, список слоёв RAG и лимит строк выдачи. |
| **Вход** | `V2RouteResult`. |
| **Выход** | `RetrievalPlan`: `profile`, `layers`, `limit`, опционально `filters`. |
| **Как работает** | Это отдельный смысловой шаг между routing и retrieval. Он не ходит в БД и не извлекает данные, а только подготавливает параметры поиска. Для `FIND_FILES` выбирается один профиль слоёв и лимит, для `SUMMARY` — другой. Лог: `retrieval_plan_resolved`. |

Код: `src/app/core/agent/processes/v2/retrieval/policy_resolver.py`.

---

### 2.3. `V2RagRetrievalAdapter` → `RagSessionRetriever.retrieve`

| | |
|--|--|
| **Название** | Загрузка сырых строк из RAG по плану |
| **Задача** | Делегировать поиск в единственную реализацию retrieval в пакете `rag`. |
| **Вход** | `rag_session_id`, `query_text` (нормализованный запрос), `RetrievalPlan`. |
| **Выход** | `list[dict]` — строки чанков в формате `RagRepository.retrieve` (поля `path`, `layer`, `metadata`, и т.д.). |
| **Как работает** | Выполняется retrieval по уже сформированному плану: профиль, список слоёв и лимит. На этом шаге происходит только извлечение сырых строк из `DOCS RAG`. Лог: `rag_rows_fetched`. |

Код адаптера: `src/app/core/agent/processes/v2/retrieval/v2_rag_adapter.py`.  
Код API: `src/app/core/rag/retrieval/session_retriever.py`.

---

### 2.4. `DocsEvidenceAssembler`

| | |
|--|--|
| **Название** | Сборка evidence для задачи |
| **Задача** | Превратить сырые строки retrieval в списки summary или кандидатов файлов с дедупом и скорингом. |
| **Вход** | Список строк `rows`, `V2RouteResult` (для `target_terms`). |
| **Выход** | `list[RetrievedSummary]` или `list[RetrievedFile]`. |
| **Как работает** | Это **минимальная evidence-проверка**, достаточная для MVP. Для `SUMMARY` отбрасываются записи без summary-текста и summary-like секции, затем применяется дедуп и простой скоринг по терминам. Для `FIND_FILES` остаются только релевантные пути документов, также с дедупом и простым скорингом. Здесь нет сложной многоступенчатой валидации: задача шага — отфильтровать очевидный шум и передать в workflow компактное evidence. Лог: `evidence_assembled`. |

Код: `src/app/core/agent/processes/v2/evidence/assembler.py`.

---

## 3. Шаги workflow

Текущие workflow являются **task-focused**: каждая ветка решает одну узкую прикладную задачу и не содержит общей универсальной логики для всех типов вопросов.

### 3.1. Ветка `SUMMARY`: `GenerateSummaryAnswerStep`

| | |
|--|--|
| **Название** | Сборка ответа по summary |
| **Задача** | Сформировать ответ пользователю по найденным SUMMARY-блокам или сообщить об отсутствии. |
| **Вход** | `DocsExplainSummaryContext`: `runtime`, `route`, `rag_session_id`, `prompt_name`, `documents` (список `RetrievedSummary`). |
| **Выход** | Контекст с `answer: str`, `prompt_input` при успешном вызове LLM. |
| **Как работает** | Workflow получает уже отобранные summary-документы. Если документов нет — возвращает честный fallback-ответ. Иначе собирает prompt input из запроса пользователя и найденных summary-блоков и вызывает LLM. Workflow не занимается retrieval и не строит retrieval-план: он решает только задачу генерации ответа по уже подготовленному evidence. |

Код: `src/app/core/agent/processes/v2/workflows/docs_explain_summary/steps/generate_summary_answer_step.py`.  
Граф: `DocsExplainSummaryGraph` (`V2WorkflowGraph`).

---

### 3.2. Ветка `FIND_FILES`: `FinalizeFindFilesAnswerStep`

| | |
|--|--|
| **Название** | Сборка списка файлов |
| **Задача** | Вывести пользователю markdown-список путей к файлам документации. |
| **Вход** | `DocsExplainFindFilesContext`: `runtime`, `route`, `rag_session_id`, `files` (`RetrievedFile`). |
| **Выход** | Контекст с `answer: str`. |
| **Как работает** | Workflow получает уже собранный список файлов и формирует финальный ответ. Если файлов нет — возвращает fallback. Если файлы есть — отдает детерминированный список путей. Эта ветка intentionally не использует LLM, потому что задача сводится к выдаче путей, а не к генерации объяснения. |

Код: `src/app/core/agent/processes/v2/workflows/docs_explain_find_files/steps/finalize_find_files_answer_step.py`.  
Граф: `DocsExplainFindFilesGraph` (`V2WorkflowGraph`).

---

### 3.3. Транспорт: `V2WorkflowGraph`

| | |
|--|--|
| **Название** | Workflow v2 с буфером trace |
| **Задача** | Выполнить шаги без пошаговых `step_started`/`step_completed` в trace; один раз сбросить сводку. |
| **Вход** | Контекст workflow (`DocsExplainSummaryContext` или `DocsExplainFindFilesContext`). |
| **Выход** | Обновлённый контекст. |
| **Как работает** | Для каждого шага: `trace_input` до `run`, затем `run`, затем `trace_output`; записи копятся в список. В trace уходят `workflow_started`, затем `workflow_trace_flushed` с массивом шагов, затем `workflow_completed`. Статусы пользователю публикуются через `publisher` как и раньше. |

Код: `src/app/core/agent/processes/v2/workflows/v2_workflow_graph.py`.

---

## 4. Сборка в приложении

В `ModularApplication` создаются `RagSessionRetriever`, `V2RagRetrievalAdapter`, `V2RetrievalPolicyResolver`, `DocsEvidenceAssembler` и передаются в `V2Process` (см. `src/app/core/application.py`).

---

## 5. Итоговая концептуальная схема текущего MVP

В концептуальном виде текущий `v2` работает так:

1. **Session check**
   Проверка, что есть активная RAG-сессия проекта.

2. **LLM-first intent routing**
   Нормализация, extraction (`target_terms`, `anchors`), затем основной выбор маршрута через LLM.

3. **Deterministic validation + fallback**
   Проверка enum/комбинации маршрута и fallback только если LLM не ответил или вернул невалидный маршрут.

4. **Retrieval parameter planning**
   Формирование профиля поиска, слоёв и лимитов.

5. **RAG retrieval**
   Загрузка сырых строк из `DOCS RAG`.

6. **Minimal evidence assembly**
   Дедуп, базовый скоринг, отбор полезных summary или файлов.

7. **Task-focused workflow**
   Узкая ветка `SUMMARY` или `FIND_FILES`.

8. **Final response**
   Либо explanation через LLM, либо детерминированный список файлов.

Это и есть актуальная архитектура **узкого MVP**, синхронизированная с текущей реализацией.
