# Intent Router Specification (MVP) — v1.1
Version: 1.1  
Scope: Routing + query normalization + anchor extraction for layered RAG (CODE + DOCS)

---

## 1) Цель

Intent Router принимает:
- `user_query: string`
- `conversation_state: object`
- `repo_context: object` (язык/структура репо/доступные слои)

И возвращает:
- `intent`
- `graph_id`
- `conversation_mode`
- `query_plan` (нормализация + якоря)
- `retrieval_spec` (запрос по слоям RAG)
- `evidence_policy`

Router **не делает** retrieval и **не генерирует** ответ.

---

## 2) MVP интенты (строго 4)

- `CODE_QA` — объяснение/поиск по коду
- `DOCS_QA` — объяснение/поиск по документации
- `GENERATE_DOCS_FROM_CODE` — генерация документации по коду
- `PROJECT_MISC` — прочие вопросы по проекту

---

## 3) Диалоговый режим (контекст темы)

### 3.1 Политика
Router обязан сохранять intent в рамках темы.

- Если `conversation_state.active_intent` задан
- и нет явного сигнала смены темы
- то `intent = conversation_state.active_intent` и `conversation_mode = CONTINUE`

Смена intent допускается только если:
- есть явный сигнал смены домена/задачи, или
- новый запрос явно не соответствует текущему intent (жёсткое несоответствие)

---

## 4) Обязательная нормализация запроса и извлечение якорей

Router обязан выполнять:

### 4.1 Query normalization
Выход должен содержать:
- `raw` — исходный запрос
- `normalized` — каноническая, детерминированная и meaning-preserving форма `raw`
- `expansions[]` — добавочные токены для retrieval/rerank
- `keyword_hints[]` — компактные ключевые токены (символы/пути/доменные термины)

Требования:
- `raw` хранит исходную строку пользователя без изменений
- `normalized` строится **только** из `raw` и безопасных правил форматирования
- `normalized` не должен включать appended expansions, синонимы и догаданные keywords
- все enrichment должны жить только в `expansions[]`, `keyword_hints[]`, `anchors[]`

### 4.2 RU→EN mapping (минимальный словарь)
Router обязан поддерживать RU→EN mapping терминов только как `expansions`:

- `класс` → `class`
- `метод` → `method`
- `функция` → `function`, `def`
- `модуль` → `module`
- `пакет` → `package`
- `файл` → `file`
- `тест`, `юнит-тест` → `test`, `unit test`

Словарь должен быть расширяемым, но эти ключи обязательны.

### 4.3 Anchor extraction (якоря)
Router обязан извлекать **явные якоря** из user_query и conversation_state:

Типы якорей:
- `FILE_PATH` — путь/часть пути (`src/...`, `package/module.py`, `README.md`)
- `SYMBOL` — идентификатор (CamelCase, snake_case, dotted path)
- `DOC_REF` — ссылка на doc file/section (если есть явные маркеры)
- `KEY_TERM` — важные термины, влияющие на retrieval (класс/метод/функция и т.п.)

Каждый якорь должен возвращаться структурировано.

---

## 5) Контракт выхода Router

Top-level:

```json
{
  "schema_version": "1.1",
  "intent": "CODE_QA",
  "graph_id": "CodeQAGraph",
  "conversation_mode": "CONTINUE",
  "query_plan": {
    "raw": "",
    "normalized": "",
    "expansions": [],
    "keyword_hints": [],
    "anchors": []
  },
  "retrieval_spec": {
    "domains": [],
    "layer_queries": [],
    "filters": {},
    "rerank_profile": ""
  },
  "evidence_policy": {
    "require_def": false,
    "require_flow": false,
    "require_spec": false,
    "allow_answer_without_evidence": false
  }
}


## 6) query_plan.anchors контракт

{
  "type": "FILE_PATH | SYMBOL | DOC_REF | KEY_TERM",
  "value": "string",
  "subtype": "optional string",
  "span": { "start": 0, "end": 0 },
  "confidence": 0.0
}

Требования:
- FILE_PATH.value хранит путь как в запросе (без попытки “исправить”)
- SYMBOL.value хранит символ как в запросе (с сохранением регистра)
- KEY_TERM используется для выставления expected evidence и выбора слоёв
- anchors может быть пустым, но router должен пытаться извлечь их всегда


## 7) retrieval_spec контракт (слои + фильтры)

### 7.1 Структура

{
  "domains": ["CODE", "DOCS"],
  "layer_queries": [
    { "layer_id": "C1", "top_k": 30 },
    { "layer_id": "C3", "top_k": 15 }
  ],
  "filters": {
    "test_policy": "EXCLUDE",
    "path_scope": [],
    "language": []
  },
  "rerank_profile": "code"
}

## 7.2 Требования по intent

- CODE_QA → domains = ["CODE"], rerank_profile="code"
- DOCS_QA → domains = ["DOCS"], rerank_profile="docs"
- GENERATE_DOCS_FROM_CODE → domains = ["CODE"], rerank_profile="generate"
- PROJECT_MISC → domains = ["CODE","DOCS"], rerank_profile="project"

## 7.3 Требования по якорям

- Если найден FILE_PATH → router обязан добавить filters.path_scope (минимум: этот путь/директория)
- Если найден SYMBOL → router обязан добавить SYMBOL в query_plan.keyword_hints и query_plan.expansions (при необходимости)
- Если найден KEY_TERM (например "класс") → router обязан добавить RU→EN expansions

## 8) evidence_policy (минимальные требования)
{
  "require_def": true,
  "require_flow": true,
  "require_spec": false,
  "allow_answer_without_evidence": false
}

Требования:
- CODE_QA: require_def=true; require_flow=true
- DOCS_QA: require_spec=true
- GENERATE_DOCS_FROM_CODE: require_def=true
- PROJECT_MISC: allow_answer_without_evidence=true

## 9) Минимально обязательные поля (строго)

Router обязан всегда возвращать:
- intent
- graph_id
- conversation_mode
- query_plan.raw
- query_plan.normalized
- query_plan.expansions
- query_plan.anchors
- retrieval_spec.domains
- retrieval_spec.layer_queries
- retrieval_spec.filters.test_policy
- retrieval_spec.rerank_profile
- evidence_policy.*
