textmachine/docs/product-requirements.md

33 KiB
Raw Blame History

Реестр продуктовых требований — «что продукт обязан уметь»

Единый список требований владельца к продукту. Источники: ../START_PROMT.MD (ЖИВОЙ бриф, идеи V0V6; ⚠ V6 от 18.08 разобран сюда только 23.08 оркестратором №19 — до этого секция владельца была в реестре НЕВИДИМА четверо суток, хотя правило реестра требует разбирать V-секцию при первом касании) + владельческие находки H6H18 (architecture/09-target-architecture.md §3). Статусы сверены кодом и D-логом при D39.80 (02.08.2026), освежены свипом D39.101 (04.08.2026) докс-паком №16 (09.08) и свипами №17 (D39.139/146: ПТ-16/18/20/22/24/33/34/35). При конфликте с D-логом побеждает D-лог. Правила: новую V-секцию владельца разбирает сюда оркестратор при первом касании; статус правится при лендинге пака, который его меняет; требование без носителя не оставлять.

Статусы: построено · 🔶 частично · не построено · снято (отменено владельцем ИЛИ закрыто отрицательным замером — с D-ссылкой) · 🔒 открытый вопрос владельца.

Ядро перевода

ID Требование (источник) Статус Носитель / доказательство
ПТ-1 Издательское художественное качество, победить translationese (V0 гл. цель; канон §1) 🔶 пайплайн draft→терминолог→editor→гейты→судья построен, адресная эскалация дорогой моделью есть (pipeline/escalation.go); качество добирается курсом «добор идеала» (D39.62/67, бэклог 24·65; 16 — непрогнанная edit-волна того же курса). Выводы-п.2 брифа (редкий узкий вызов за смыслами вне книги) — поглощён этим курсом, отдельный механизм не строится без замера
ПТ-2 ЛЮБЫЕ пары языков, в любую сторону — движок общий, пара = ДАННЫЕ (канон §2); «бэкенд только под русский» = объявленная антицель. Названные в брифе zh/en/ru/ja (V0-п.11; V4-п.5: в zh→en русский не участвует) — первые, а не полный список: продукт обязан поддержать и языки, которых в репозитории ещё нет (слово владельца 23.08) 🔶 построено только →ru: zh→ru боевая; ja→ru безопасна без правки Go, en→ru — нет (карта D39.60); не-ru target = антицель §0.1 в 09; носители: строки 81 (ja-преп) · 35 (не-CJK майнер) · 34
ПТ-3 Книга ЦЕЛИКОМ (эталон 7,78 млн симв., ~2284 раздела) 🔶 гоняли ≤10 глав; волны/потолки/ETA на сотнях глав = строка 54 (МАСШТАБ)
ПТ-4 Референсы: предыдущие части серии / чужой перевод как контекст (V0-п.1314) 🔶 серийный шаринг банка = строка 48а; импорт «оригинал+чужой перевод» = 48б (юр-сторона — 67)
ПТ-5 Неологизмы/выдуманные автором слова переводятся консистентно (V1-п.6) 🔶 банк+майнер держат термины книги; замер на вне-претрейн тексте = строка 55
ПТ-6 Структурные традиции целевого языка (короткие zh-абзацы → читаемые ru-структуры) (V1-п.4) 🔶 редакторские мандаты в пар-промптах; спец-замера структуры нет — добор идеала
ПТ-7 Слабый оригинал: подправлять ли художественно — вопрос владельца не решён (V1-п.5) 🔒 канал вопросов; сейчас пайплайн верен оригиналу

Память и консистентность

ID Требование (источник) Статус Носитель / доказательство
ПТ-8 Банк памяти на всю книгу, «крайне точный» (V0-п.78; Выводы-п.1) D39.69/75/77/78; recall банка 0.918/0.980 на холодном прогоне (D39.58). Смежный остаток H6 (running-summary): carryover закрыт замером (D39.7/8), проза-суммарайзер закрыт (D39.69), нарратив-состояние = строка 80 (гейт пилота Ф2.5)
ПТ-9 Глоссарий автосборкой: модель переводит термины с контекстом/жанром (V4-п.4, H15) терминолог пака-20 (D39.4153), KWIC-контексты, подписной цикл. Вход владельца 02.08 (D39.89): банк = центральная ценность, арбитраж перевода термов должен быть консилиумом со скорами уверенности, но не ломать связность системы термов ⇒ качество МЕХАНИЗМА проверено полигоном: заход исполнен и ПРИНЯТ приёмкой №13 (research/24, D39.102): консилиум закрыт КЛАССОМ (равноправный совет · кросс-модельные веса · self-consistency · селекция не окупаются), остаток строки 5 (рецензент спорных кластеров) гейчен ре-пробой 74; статус ПТ-9 «построено» не меняется
ПТ-10 Веб-фетч для терминов без культурного контекста (V0-п.16, V4-п.4) гейт action-security = строка 70 (Ф3); до него — сид/бриф
ПТ-11 Голоса персонажей консистентны на книгу (V1-п.2; канон §1) 🔶 схема голосов построена (пак-19, D39.55/56); оси не подписаны — замер добора (строки 24 · 13б)

Деньги и телеметрия

ID Требование (источник) Статус Носитель / доказательство
ПТ-12 Низкий COGS: дешёвые модели + адресные дорогие вызовы (V0-п.3/12; канон §5) ~$0.85/ранобэ (D30.4); ре-проба исполнена и строка 74 закрыта (замер D39.86/91, закрытие D39.95); пере-калибровка цены — при следующем платном прогоне
ПТ-13 Телеметрия токенов/стоимости с первого вызова, БД (V0-п.25/31) SQLite request_log/леджер/смета; ⚠ леджер = нижняя граница (строка 78)
ПТ-14 Потолки бюджета и явное согласие на пере-оплату (канон §5) 🔶 reserve/settle и потолки (траты защищены). ⚠ Статус понижен с приёмкой №18 (D39.149): само ЧИСЛО согласия неполно и приблизительно — пере-прайс по текущей таблице цен исполнен (строка 181 закрыта), но: деньги банковых ролей в число не входят вовсе (194) · при смене модели стадии считается цена ОТСТАВЛЕННОЙ модели (решено 17.08: прайсить по текущей + округлять вверх и называть оговорку — D39.150) · принадлежность вызова поколению ВЫВОДИТСЯ, а не хранится (195). Щель терминолога = строка 38

Чувствительный контент

ID Требование (источник) Статус Носитель / доказательство
ПТ-15 18+/агрессивный контент при цензуре провайдеров, мультипровайдерность (V0-п.910) 🔶 канал B построен (пак-17), лейблы/ToS-мониторинг (строка 4); per-chunk L3-скрин = строка 8; explicit-редактор = строка 7

Управление прогоном (продукт)

ID Требование (источник) Статус Носитель / доказательство
ПТ-16 Абьюз/misuse-прескрин: дёшево, точно, до трат токенов, минимум false positive (V2-п.1, H8) строка 94; UI-контракт отказа — проект-решение D39.80 к Ф3-брифу (вывод оркестратора, не цитата брифа); форма отказа в API РЕШЕНА владельцем 16.08 (К-9 закрыт, D39.138 п.2б: rejected + ОДИН грубый код на модельный класс, без вариации между попытками — оракула подбора не давать; в каноне 0.3.0 — content_refused)
ПТ-17 Лимит размера входа настройкой (V2-п.3, H7) строка 94
ПТ-18 Стоп и продолжение пайплайна; абьюзивный прогон НЕ продолжать (V2-п.2, H10) 🔶 graceful stop по сигналу (cmd/tmctl/main.go NotifyContext) + чекпойнты/redrive; продукт-кнопки и связка с прескрином = строка 94; API-форма в контракте 14 (D39.99: stop/resume; отказ прескрина — К-9 закрыт D39.138 п.2б)
ПТ-19 Скорость: «очень быстрый перевод книги — киллерфича» (V4-п.1, H9); видимый прогресс/ETA — из Ф3-видения ридер-IDE (цветная полоса статуса), не из V4 🔶 волны параллельны по чанкам; замер скорости и ETA на целой книге = строка 54 (МАСШТАБ); пофазные счётчики draft/edit НА ГЛАВУ построены движком (D39.122 — строка 99 ЗАКРЫТА); ETA ПОКАЗЫВАТЬ — решение владельца 04.08 (D39.100/К-5), eta_seconds в спеке (0.2.0+, D39.115); оценка $/глава движком = строка 166

Фронт (Ф3)

ID Требование (источник) Статус Носитель / доказательство
ПТ-20 Ридер-IDE: VS Code-подобный фронт агентного перевода (V0-п.20/23) research/16 принят (D29); строки 6971; F3-brief — D29 п.3. Ф3 ОТКРЫТА 02.08 (D39.81): фронт-сессия живёт на моках; контракт API ратифицирован (D39.99; ⚠ версии в этой ячейке протухали дважды — испр. 22.08: канон стоит на 0.4.0 (D39.152), батч 0.3.0 отработан целиком (D39.142/143), ⚠ следующий минор ПЕРЕ-ПЛАНИРОВАН D39.156: идёт ПОСЛЕ движкового пака и ОДНИМ куском — снос отменённой пер-термной модели плюс новая дверь приёма правок банка; строки 200/203/206 едут в нём; зеркало ФРОНТА ратифицированно отстаёт на 0.2.3 — D39.135, синк при разморозке); платформа построена до потребительской половины шва: вход/кредиты/квоты (P0P3) + раннер P4 (D39.123) + интейк POST /books со стоп/резюмом (D39.130) + exit-словарь/фолд юнитов/дев-стенд (P6, D39.132); фронт — S3.5S4 приняты (оболочка · слой данных · i18n · путь «файл→прогресс», D39.127/129/135), зона ЗАМОРОЖЕНА, и с 17.08 морозится ДАЛЬШЕ лендинга P7 (D39.136 п.2 + D39.147: сначала движок и платформа до «работает и отдаёт результат», фронт накручивается на готовую функциональность)
ПТ-21 Параллельное чтение двух текстов с выравниванием по смыслам (V0-п.21); выравнивание грубое, по единицам экспорта — принято владельцем 02.08, спаны внутри текста не строятся 🔶 механизм готов: tmctl export --pairs выравнивает пары побайтно по единицам редактуры (internal/pipeline/export.go:89-93); якорь = edit-unit, НЕ чанк (переформулировано D39.84 — финальный текст существует только на уровне юнита, ~1.9 юнита/главу, местами глава = один блок; читалка обязана это выдерживать); UI-читалка = Ф3 (этап S6)
ПТ-22 Настройки от человека: 18+, жанр и т.п. (V0-п.22) 🔶 book.yaml (labels) данными; UI = Ф3. ⚠ ЖАНР из продукта ВЫКИНУТ словом владельца 16.08 (D39.138 п.2в, строка 184: ни на чём не ветвится, влияние не измерено; снимается из промптов/брифа/контракта/формы)
ПТ-23 Веб-ПЕРВЫЙ фронт; SEO/ранжирование Google — куки, страницы-сироты, актуальные алгоритмы (V5-п.2); продукт = SaaS, не локальное приложение (решение владельца 02.08, D39.81 — натив-прицел V0-п.26 СНЯТ этим решением, вернуть только новым словом владельца); SEO только под Google, Яндекс снят; рынок глобальный; десктоп = PWA первым шагом, Tauri по явным триггерам (решения владельца 02.08, D39.84) строка 71 (Ф3-бриф); SEO вошёл в стек-дизайн ДО выбора (D39.84, требование исполнено): двухконтурный деплой — SPA app.<домен> целиком под noindex + статический публичный контур ≤3 кликов от главной (лечение страниц-сирот), frontend/docs/STACK_DECISIONS.md §4; SSR-вопрос закрыт этим решением
ПТ-24 Цикл согласования глоссария с профпереводчиком/редактором (V0-п.23) 🔶 подписной цикл терминолога в бэкенде есть; UI = Ф3. Модель цикла записана словом владельца 16.08 (D39.144 + строка 192): черновой перевод и черновой банк появляются вместе → ОДИН ОК всему банку (не пер-термная масс-подпись) → доработка → пост-ридинговые точечные правки с пере-генерацией по вхождениям (механика — после полигона)
ПТ-33 Интерфейс НЕ раскрывает конвейер: ни моделей, ни стадий, ни внутренней терминологии (решение владельца 02.08; граница пере-читана 15.08 — охранять АЛГОРИТМЫ, не минорную механику, D39.136 п.4а). ⚠ «Лестница» фаз «загрузка → … → финал → готово» — устная фраза владельца, НЕ норма продукта (его слово 16.08, D39.138: finalizing сворачивается) 🔶 инвариант D39.81; словарь статусов принят (D39.100/К-1); карта «вердикт → фраза» — приложение А компаньона (В-3), после D39.138 пишется по словарю машинных кодов Б-1. ⚠ Ревью 28 (Б-0) ОПРОВЕРГЛО исполнением ответ §5 компаньона «сменится стадия — фронт не правится»: волны draft/edit утекали в Progress до React-компонента; снято ИСПОЛНЕННЫМ батчем 0.3.0 (D39.142/143: Progress — один счётчик в каноне, анти-утечка-греп чист); машинный ГЕЙТ на утечку — фронту при разморозке (пинг 16.08). ⚠ ОСТАТОК, названный владельцем 20.08 (D39.153, строка 200): конвейер не утекает СЛОВАМИ, но утекает ФОРМОЙ прогресса — доля считается по отрезкам и обнуляется при снятии стопа, то есть пользователь видит 100% после черновика и старт заново; и фаза, которая глав не заканчивает (сбор банка), сегодня полосой невыразима — знаменателя она не объявляет; может ли объявлять, это открытый вопрос движку в той же строке 200. Требование: ОДНА сквозная доля на всю работу прогона, считает СЕРВЕР (иначе клиент снова узнаёт про фазы), плюс подпись «что делается сейчас» и неопределённый индикатор там, где доли в главах нет; веса не подбираются — знаменатель берётся из объявленного движком плана проходов
ПТ-34 Пользовательский перевод НИКОГДА не попадает на публично индексируемый URL — ни витрин примеров, ни «поделиться главой», ни публичных ссылок чтения (жёсткий продуктовый запрет, решение владельца 02.08; авторское право на исходники + политика Google по масштабируемому машин-контенту действуют на весь домен) инвариант D39.84; носители: двухконтурный деплой frontend/docs/STACK_DECISIONS.md §4 (SPA под X-Robots-Tag: noindex на каждом HTML-ответе; публичный контур без контента переводов) + контракт 14 (architecture/14-api-contract/, D39.99) + платформенный бэклог П-1; правило доступа к экспорт-ссылке (срок/подпись) — батч 183 (research/28 Б-4)
ПТ-35 Лимиты «как в Claude Code» (решение владельца 04.08, D39.100): страница лимитов/использования в настройках (статус, НЕ суммы — запрет денег на экране в силе); стоп по потолку = статус paused + оповещение «перевод остановлен: лимиты исчерпаны» 🔶 контракт К-8 закрыт, спека несёт paused/paused_reason (0.2.0+, D39.115); ручки /v0 — платформа-раннер P4 (D39.123); статус paused по потолку ЧЕСТЕН с P6 (D39.132: exit 4/событие → paused, не failed; дневной потолок оператора различим и из платформенного шаблона убран — решение владельца 15.08); остаток: страница лимитов и оповещение на фронте (после P7) · точное продуктовое слово — В-3 на владельце · К-13 ЗАКРЫТ (D39.132 п.2а: null на проводе; пере-суждён ревью 28 §4 №9 и НЕ опрокинут — с уходом дневной оси различие перестало быть продуктовым)
ПТ-36 Интерфейс МУЛЬТИЯЗЫЧНЫЙ, русский не хардкодится в разметке (слово владельца 10.08; язык интерфейса — отдельная ось от языков перевода). ⚠ До 10.08 требование в реестре отсутствовало — пропуск поймал владелец (D39.127 п.2г) 🔶 ПОСТРОЕНО S3.7 (принят D39.129): каталог frontend/src/i18n/ru.ts (⚠ число ключей здесь НЕ держим — оно росло каждым касанием зоны и уже разошлось: было «157», в дереве 202; счёт снимается командой grep -cE "^\s+'[a-z][a-zA-Z0-9.]*':" frontend/src/i18n/ru.ts; испр. 22.08) · механизм @internationalized/string · ESLint-гейт «текст местом» · стор языка с персистом · <html lang> следует выбору; содержимое — только ru; продуктовый список языков — 🔒 владелец (В-9 зоны фронта)

Качество процесса и самоулучшение

ID Требование (источник) Статус Носитель / доказательство
ПТ-25 Валидация влияния каждого решения на качество, вкл. пагубное (V1-п.3, V3-п.1; Выводы) методология полигона (exp0121 приняты, 22/23 живые; labels, судья, пре-рег); держится нормами D39.46/47
ПТ-25а Онлайн- и оффлайн-замер КАЧЕСТВА прогона (V0-п.31, H5 in-loop signal) 🔶 детерминированный $0-слой в петле построен (гейты/чекеры, телеметрия качества — слой 5 в 09); семантический in-loop сигнал = Ф2 (судья, строки 33 · 13а · 90-метрики)
ПТ-26 Самоулучшение пайплайна по данным больших прогонов (V3-п.2, H16) строка 90 (дизайн петли по данным судьи — при пилот-препе Ф2.5); AB-способность бэкенда — дальний хвост V1 (двойное хеджирование владельца), тем же дизайном
ПТ-27 Без-LLM анализ книги в помощь переводу/валидации (V1-п.1/п.9) майнер, $0-гейты/чекеры, экраны, KWIC — весь детерминированный слой
ПТ-28 Фронтир-модель внутри пайплайна / «судья над судьёй» (V3-п.3) отменено владельцем (V4-п.2)
ПТ-29 Полный проход книги наперёд перед переводом (V0-п.33) отклонено брифом V4-п.3 (вопросительная форма, отдельной ратификации в D-логе нет); контекст-вперёд несут сид/банк/бриф
ПТ-30 Язык промптов = язык цели/оригинала (V4-п.5) ru/en-срез закрыт отрицательно ЗАМЕРОМ (D39.61; там же оговорка «не закрыт окончательно», N=12); реопен только с новой парой по данным
ПТ-31 Локальная модель ради экономии (V0-п.6) 🔶 стенд есть (ollama/llama.cpp; ⚠ носителем доказательства прежде была названа авто-память оркестратора — её в проекте больше НЕТ, распущена по решению владельца 21.08; репо-носители — eval/local_bench.py, eval/ollama-up.sh, docs/experiments/03-local-stand.md, 06-local-extraction.md); в пайплайне не задействована = строка 90 (llama-server)
ПТ-32 Рынок/юридика: анализ рынка, право на перевод и распространение (V0-п.29, преамбула) 🔶 ToS-мониторинг (строка 4, D39.57); юр-пакет к проду = строка 67; рыночный анализ — ресёрчи 04.07

Архитектура пайплайна — идеи V6 (бриф владельца 18.08.2026)

Разобрано 23.08 (№19). Статусы поставлены по КОДУ, а не по докам. V6 предлагает переделку пайплайна; часть его пунктов уже наполовину построена, часть не построена вовсе, и один измеримо оспорен замером — это названо в строках, а не сглажено.

ID Требование (источник) Статус Носитель / доказательство
ПТ-37 Нарезка по границам СЦЕН, а не по объёму: «граница сцены — удобная порция, где не теряется смысл; сцены можно склеить, крупная должна вмещаться в контекст» (V6-1/V6-3) не построено. Книга режется бюджетом ОЦЕНЁННЫХ ВЫХОДНЫХ токенов: пакуются целые абзацы, при переполнении спуск до границ предложений, предложение не разрывается (backend/internal/chunk/chunker.go:324-330=prefer paragraph boundaries). Сцены как семантической единицы нет; ближайшее — «инерция сцены» A5, где границей сцены считается граница ГЛАВЫ (backend/internal/pipeline/wave.go:72=a new chapter is a scene change). Полигон отдельно фиксирует, что требование «не исполнено ни разу»
ПТ-38 Майнинг ВСЕХ терминов дешёвой моделью с явной JSON-схемой и КООРДИНАТАМИ вхождений (V6-1) 🔶 майнер и фокус-классификатор построены; KWIC-контексты вхождений персистятся и едут терминологу. Чего нет: ответ терминолога — не JSON, а три поля через табуляцию (backend/prompts/zh-ru/terminologist.md), офсетов/координат в нём нет вовсе. Служебная инфа о книге (нарезка по главам) построена; поиск идиом и прочего — не начат
ПТ-39 Решение по термину С ОБОСНОВАНИЕМ от дорогой модели, с контекстом первого появления (V6-2) терминолог возвращает РОВНО три поля — термин, перевод, уверенность 0100 — и уверенность явно НЕ арбитр, она только сортирует лист ревью. Обоснования нет ни в промпте, ни в парсере. ⚠ Формат его примет аддитивно: поле Note в схеме сида существует (backend/internal/seed/seed.go:78=Note), то есть строить надо ПРОИЗВОДИТЕЛЯ, а не формат — тот же паттерн, что у оси рода (строка 210)
ПТ-40 Раздельные правила перевода по классам сущностей — имена отдельно, магические предметы отдельно (V6-2, ПРЯМОЙ вопрос владельца «мы кстати так и делаем или нет?») 🔶 Наполовину да. Отдельный фокус-классификатор построен, со своей ролью, промптом и осью цены, и раскладывает термины по ЧЕТЫРЁМ закрытым классам name/place/title/term, где имена и топонимы транскрибируются, а титулы и реалии переводятся по смыслу (backend/prompts/zh-ru/classifier.md). Заведён 01.08, потому что черновой тип врал в 1222%. Чего нет: отдельных ВЫЗОВОВ и отдельных наборов правил на класс — терминолог получает один смешанный список; отдельного класса «магические предметы» не существует, они лежат в term вместе с материалами, веществами и классами существ. Окупается ли разделение — не мерено
ПТ-41 Литературный критик: фиксирует расхождение, НЕ предлагает решений, классифицирует проблему; МАЙНИНГ ЗАМЕЧАНИЙ как отдельный банк (V6-4) в движке роли нет. Полигон критика мерил и назвал два факта, которые дизайн обязан учесть: критик НЕ видит удалённого целого абзаца, при том что снятую частицу «не» ловит; реальный дефект в черновике удорожает критика в 14 раз. ⇒ полноту обязан ловить детерминированный гейт, а не критик
ПТ-42 Точечный edit-редактор: получает строку банка замечаний, чинит названное место, фиксы инжектятся в текст; НЕ переписывальщик (V6-5) в движке нет. Смежный механизм существует и его стоит переиспользовать: точечная пере-редактура юнитов с $0-репином незатронутых (backend/internal/pipeline/stagerun.go:88-107=POINTWISE RE-EDIT) — но она срабатывает на сдвиг БАНКА, а не на строку замечаний
ПТ-43 «Не подсовывать хорошей модели дешёвый черновой вариант» (V6-3) 🔒 вопрос владельца с ЗАМЕРЕННЫМ контр-доводом, решения нет. Замер полигона трейсом: у deepseek-v4-pro медиана 96% предложений финального текста встречается в трейсе размышления дословно ⇒ отказ от дешёвого черновика черновик НЕ убирает, а переносит его в канал размышления дорогой модели, где за него платят по цене ВЫХОДА и где он невидим и непереиспользуем. Действующая топология дешёвого черновика этим и оправдана. ⚠ Это данные полигона, НЕ ратифицированный канон; решение — за владельцем после фазы Д