TZ_Assistant_Mode_vNext2.md Да, даю уже в формате **жёсткой вставки в ТЗ**. Ниже блок, который логично добавлять как отдельный раздел после текущего `Final Answer Composer / answer policy`, потому что в текущем контуре уже есть правильная базовая архитектура, но composer пока остаётся operational, retrieval — sandbox/stubbed, а пользовательский ответ не обязан доказывать основание отбора и полноту покрытия вопроса. Это прямо следует из текущего vNext ТЗ и архитектурного отчёта. --- # Дополнение к ТЗ: explainable answer layer и контроль полноты декомпозиции ## 1. Цель дополнения Закрыть два критических продуктовых дефекта Assistant Mode: 1. ассистент выдаёт формально человекочитаемый, но смыслово пустой ответ без объяснения, почему именно эти объекты, записи или цепочки были отобраны; 2. ассистент теряет части многосоставного пользовательского запроса на этапе decomposition/routing и отвечает только на отдельный фрагмент, создавая ложное ощущение, что задача решена. Цель этого этапа — сделать так, чтобы Assistant Mode: * отвечал **по смыслу бухгалтерского вопроса**; * объяснял **основания отбора и вывода**; * гарантировал **покрытие всех существенных частей запроса**; * не подменял пользовательский вопрос ближайшим технически доступным маршрутом. --- ## 2. Что фиксируем как обязательный продуктовый контракт Считать ответ ассистента корректным можно только тогда, когда одновременно выполнены четыре условия: 1. ответ относится именно к предмету вопроса пользователя, а не к соседнему маршруту; 2. ответ объясняет, **почему** найденные записи/объекты/контрагенты попали в результат; 3. ответ показывает, **на каких признаках и фактах** основан вывод; 4. ответ закрывает **все существенные части** многосоставного запроса либо явно помечает, что часть вопроса не покрыта. Если хотя бы одно из этих условий не выполнено, ответ считается непригодным даже при технически успешном pipeline. --- ## 3. Новый обязательный слой: Explainable Answer Layer После `Result Normalization` и до финального `Assistant Reply` должен быть отдельный обязательный слой: **Explainable Answer Layer** Новый полный контур: **User message → Normalizer → Requirement Extraction → Execution Planning → Route-specific Retrieval → Result Normalization → Explainable Answer Layer → Final Answer Composer → Assistant Reply** Задача этого слоя: * восстановить пользовательское намерение в нормальной человекочитаемой форме; * проверить полноту покрытия вопроса; * проверить предметную релевантность ответа; * собрать не просто summary, а **объяснимый вывод**. --- ## 4. Новый обязательный контракт декомпозиции ### 4.1. Декомпозиция должна выделять не только fragments, но и requirements Нужно разделить два уровня: ### A. `requirements` Смысловые требования пользователя. Примеры: * найти поставщиков с хвостами; * объяснить, почему они считаются проблемными; * показать, где именно разрыв по цепочке; * отделить аномалии по риску от аномалий по сумме. ### B. `execution_fragments` Технические единицы исполнения, которые маршрутизируются по route. Важно: один `requirement` может порождать несколько `execution_fragments`; несколько fragments могут обслуживать один requirement. Без этого разделения многосоставные вопросы будут и дальше схлопываться в один ближайший route. --- ### 4.2. Для каждого пользовательского сообщения нужен coverage report После decomposition система обязана формировать объект: ```json { "requirements_total": 0, "requirements_covered": 0, "requirements_uncovered": [], "requirements_partially_covered": [], "clarification_needed_for": [], "out_of_scope_requirements": [] } ``` Это внутренний контракт pipeline. Без него нельзя считать, что система поняла вопрос. --- ### 4.3. Запрещён silent loss of intent Если в исходном сообщении было несколько требований, а в execution plan попала только часть, система не имеет права: * молча проигнорировать остальные части; * выдавать ответ так, будто задача полностью выполнена; * считать вопрос закрытым. В этом случае допустимы только три режима: 1. **полный ответ** — если покрыто всё; 2. **partial answer** — если покрыта только часть и это явно сказано; 3. **clarification** — если без уточнения нельзя корректно закрыть все требования. --- ## 5. Новый обязательный контракт retrieval result Текущий unified result schema нужно расширить. Сейчас в нём есть хороший базовый каркас, но для объяснимого ответа его недостаточно. Каждый route executor должен возвращать не только данные, но и признаки, объясняющие включение объекта в ответ. ### Обязательные поля результата ```json { "fragment_id": "F1", "requirement_ids": ["R1"], "route": "store_feature_risk", "status": "ok | empty | partial | error", "result_type": "list | summary | object | chain | ranking", "items": [], "summary": {}, "evidence": [], "why_included": [], "selection_reason": [], "risk_factors": [], "business_interpretation": [], "confidence": "high | medium | low", "limitations": [], "errors": [] } ``` --- ### 5.1. Смысл новых полей `why_included` Почему объект вообще попал в выборку. `selection_reason` По каким конкретным правилам, фильтрам, признакам или сопоставлениям он был отобран. `risk_factors` Какие именно признаки риска, расхождения, аномалии или разрыва цепочки обнаружены. `business_interpretation` Как это интерпретируется в бухгалтерском или операционном смысле. `confidence` Оценка уверенности результата. `limitations` Что система не смогла подтвердить или где данные неполны. --- ## 6. Новый обязательный слой: Answer Grounding Check Перед выдачей финального ответа должен выполняться `Answer Grounding Check`. ### Его задача: проверить, что итоговый ответ действительно опирается на retrieval results и не съехал по предметной области. ### Проверяемые условия: 1. ключевые сущности ответа присутствуют в retrieval results; 2. ключевые выводы ответа подтверждены `evidence` и `selection_reason`; 3. предмет ответа совпадает с предметом вопроса; 4. если пользователь спрашивал про ОС, ответ не может быть собран по НДС; 5. если пользователь спрашивал про 97 счёт, ответ не может уйти в общий рейтинг контрагентов без объяснения связи; 6. если пользователь спрашивал про аномалию, ответ обязан назвать признак аномалии. Если проверка не проходит, ответ не отправляется в user-facing канал и должен перейти в один из fallback-режимов: * clarification; * partial with limitation; * technical error; * no-grounded-answer. --- ## 7. Новый обязательный стандарт user-facing ответа Каждый нормальный factual answer должен содержать не просто summary, а следующие смысловые элементы: ### 7.1. Итоговый вывод Короткий ответ на главный вопрос. ### 7.2. Основание отбора Почему именно эти объекты попали в ответ. ### 7.3. Подтверждающие признаки Какие факты, поля, несоответствия, связи или разрывы обнаружены. ### 7.4. Практический смысл Что это означает для бухгалтера или что именно здесь выглядит проблемным. ### 7.5. Ограничения Что не удалось проверить полностью, если такое есть. ### 7.6. Следующее действие Что стоит посмотреть или проверить дальше. --- ### 7.2. Требование к стилю ответа Ответ должен быть: * на русском; * коротким, но содержательным; * предметным; * без route names; * без debug-лексики; * без пустых формулировок типа “по запросу найдены данные”; * без перечисления ссылок без пояснения, зачем они показаны. --- ## 8. Обязательные шаблоны смысловой структуры ответа ### 8.1. Для anomaly / risk / suspicious scan Ответ обязан содержать: * что именно признано аномалией; * по каким признакам это признано аномалией; * чем запись отличается от нормального поведения; * какие объекты наиболее рискованные; * в чём риск состоит практически. ### 8.2. Для chain / causal / cross-entity explanation Ответ обязан содержать: * какую цепочку система проверяла; * где именно найден разрыв или конфликт; * какие сущности участвуют в цепочке; * почему это считается хвостом, разрывом или зависшей ситуацией. ### 8.3. Для ranking / overview / top Ответ обязан содержать: * принцип ранжирования; * почему верхние позиции оказались наверху; * какие признаки сильнее всего влияли на приоритет. ### 8.4. Для canonical factual reply Ответ обязан содержать: * прямой ответ по объекту; * источник/основание; * при необходимости — уточнение статуса, периода, документа, связанной записи. --- ## 9. Новый обязательный формат partial answer Если закрыта не вся задача, partial reply обязан быть структурирован так: 1. что удалось проверить; 2. что именно не покрыто; 3. почему не покрыто; 4. нужно ли уточнение; 5. можно ли продолжить по оставшейся части. Недопустимо: выдать ответ по одному фрагменту без явной маркировки того, что другие части вопроса потеряны. --- ## 10. Новые reply types К текущему набору reply/fallback типов нужно добавить или закрепить отдельно: * `factual` * `factual_with_explanation` * `partial_coverage` * `clarification_required` * `empty_but_valid` * `no_grounded_answer` * `route_mismatch_blocked` * `backend_error` Это нужно, чтобы различать: просто технически успешный ответ и семантически валидный ответ с объяснимым основанием. --- ## 11. Что нужно изменить в логировании К уже существующим логам надо добавить поля, которые позволят анализировать именно смысловую пригодность ответа, а не только route/fallback. Сейчас логирование уже есть, но его надо расширить для field hardening. ### Добавить в structured log: * `requirements_extracted` * `requirements_total` * `requirements_covered` * `requirements_uncovered` * `coverage_status` * `answer_grounding_status` * `reply_semantic_type` * `why_included_summary` * `selection_reason_summary` * `route_subject_match` * `clarification_target` * `dropped_intent_segments` --- ## 12. Что нужно изменить в UI Debug drawer остаётся, но в основном ответе надо показывать не только итог, а и короткий explainable summary. ### В bubble ответа ассистента показывать: * краткий вывод; * короткий блок “почему это попало в ответ”; * по необходимости — список объектов; * по необходимости — блок “что проверить дальше”. ### В debug drawer переносить: * raw fragments; * route selection; * trace id; * fallback state; * raw retrieval payloads; * coverage report; * grounding check result. --- ## 13. Новые критерии приёмки этапа Этап считается принятым только если выполнены все условия: 1. ассистент отвечает по предмету вопроса, а не по ближайшему соседнему route; 2. каждый factual answer содержит объяснение, почему объект/запись/контрагент попал в ответ; 3. для каждого многосоставного вопроса система фиксирует coverage report; 4. система не теряет части вопроса молча; 5. если покрыта только часть — это явно отмечено в ответе; 6. если предмет ответа съехал — ответ блокируется как `route_mismatch_blocked` или `no_grounded_answer`; 7. anomaly-ответы объясняют признак аномалии, а не только выводят список сущностей; 8. chain-ответы объясняют разрыв цепочки, а не только перечисляют документы; 9. в основном ответе нет route names, trace, sandbox wording и другого внутреннего мусора; 10. debug остаётся доступен отдельно и не ломает основной UX. --- ## 14. Минимальный MVP этого дополнения ### MVP-1 Внедрить: * `requirements` + `coverage report`; * расширенный unified result schema; * `Answer Grounding Check`; * explainable answer contract хотя бы для: * `store_feature_risk` * `hybrid_store_plus_live` ### MVP-2 Добавить explainable templates для: * `batch_refresh_then_store` * `store_canonical` ### MVP-3 Дополировать: * richer explanation formatting; * confidence/limitations; * better partial answer behavior; * трассировку semantic failures. --- ## 15. Что считать провалом этапа Этап не считается выполненным, если сохраняется хотя бы один из сценариев: * пользователь спросил про аномалию, а получил список без признаков аномальности; * пользователь задал многосоставной вопрос, а ассистент ответил только на один фрагмент без явной маркировки; * ответ предметно съехал в другой участок учёта; * ответ содержит ссылки, route names, trace или sandbox-пояснения вместо нормального объяснения; * ассистент дал формально связный, но необоснованный вывод без основания отбора. --- ## 16. Короткий итог для разработчика Задача следующего этапа — не просто улучшить текст ответа. Задача этапа: * сделать декомпозицию **полной**, а не частичной; * сделать ответ **объяснимым**, а не декоративно-человекочитаемым; * заставить ассистента **доказывать**, почему он выбрал именно эти записи; * запретить выдачу ответа, если система не может подтвердить предметную релевантность и полноту покрытия вопроса. --- Если хочешь, следующим сообщением я сразу соберу ещё и **сверхкороткую версию для Codex/разработчика на 1 экран**, без пояснений, только требования и acceptance criteria.