---
name: heuristic_cannot_detect_input_source
description: Эвристика «похоже на пользовательский ввод» не отличает его от собственного служебного текста — источник передавать явным флагом с места вызова
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 0a7ddf2b-508e-45e8-9db2-bfeb94cae09b
  modified: 2026-08-06T15:07:46.192Z
---

Режим «пользователь прислал историю — перескажи её» включался по форме строки (`длина ≥ 350` и много предложений). Служебные **инструкции-промпты рубрик тоже длинные и многофразовые** — в результате в режим пересказа уходили **10 рубрик из 14**, и они генерились инструкцией «перескажи присланную историю», где «историей» был собственный служебный текст.

**Why:** эвристика мерила ФОРМУ текста, а различать надо было ПРОИСХОЖДЕНИЕ. Форма у пользовательского нарратива и у сгенерированного промпта совпадает, поэтому никакой порог длины/пунктуации это не разделит. Баг молчащий: код не падает, тесты на генерацию зелёные, посты выходят — просто не те.

**How to apply:**
- Признак «это пришло от пользователя» передавать **явным параметром с места вызова** (`allow_retell=True` только в хендлере пользовательского ввода), а эвристику оставлять максимум вторым условием.
- То же для любых «умных» автодетектов режима: язык, тип контента, «это код или проза» — если вызывающий знает ответ, он обязан его сказать.
- **Проверять фичу на ВСЕХ путях, а не только на том, ради которого писалась.** Здесь достаточно было прогнать `_looks_like_story` по всем служебным промптам — таблица «рубрика → в какой режим попала» вскрыла всё за один запуск.
- Тест писать на отрицание: «служебная инструкция НИКОГДА не становится пересказом», а не только «история становится».

Родственное: [[antidup_window_larger_than_pool]] (тоже молчащая деградация выбора, не падение), [[ceberspost_overview]].
