diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index a8dcf461..e34a314b 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1,9 +1,9 @@ # Журнал прогресса -> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-07-25, пак-17 закрыт, право по ToS подписано, пак-18 принят — долгов контракта нет, D39.26–D39.31). **Источник истины по РЕШЕНИЯМ — `architecture/05-decisions-log.md` (D1–D39.38); этот файл — ЖУРНАЛ.** +> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-07-25, пак-17 закрыт, право по ToS подписано, пак-18 принят — долгов контракта нет, D39.26–D39.31). **Источник истины по РЕШЕНИЯМ — `architecture/05-decisions-log.md` (D1–D39.39); этот файл — ЖУРНАЛ.** > - **Фазы/курс:** Ф0 ✅ · Ф1-инфра ✅ (D20–D28; golden = инвариант №8) · арка «качество-первым» D26→D38.5 закрыта · **арх-ресет D39 исполнен ЦЕЛИКОМ** (7 слоёв → программа D39.1–D39.10 → паки 11–16, D39.13–D39.24; статус слоёв — шапка-таблица `architecture/09-target-architecture.md`) · пере-прогон rerun2 прочитан (D39.20: операционка живьём, $0-резюм ×3 арма, $6.63<$15; планка ≤2 НЕ пройдена; анти-корреляция гладкость↔верность ×3 → mistral-редактор вон) · эксп ЗАКРЫТ (D39.22), итерация №2 отложена · **курс = разработка бэкенда: пак-17 «канал B вживую» ЗАКРЫТ ЦЕЛИКОМ (дизайн D39.26 · стройка D39.27 · дельта `allow` D39.28, 25.07); вокабуляр = ПАРА `violence`/`sexually-explicit`, остаток — ФАКТЫ ToS в зоне полигона (fail-closed до них)** (D39.25: в движке НЕТ понятия «18+» — generic content-labels × provider-capabilities; лейблы вне хешей · резолв до валидации · один хоп `chain[0]` · гранулярность = книга) → **КУРС АМЕНДИРОВАН ВЛАДЕЛЬЦЕМ 25.07 (D39.33): МАСШТАБ — ПОСЛЕДНИМ, после достройки алгоритмического идеала; доказательство эффективности крупных изменений — МИНИ-ПРОГОНЫ ~10 глав (детерминированные чекеры и скан остатка первыми, судья — только когда от него зависит решение).** **ОЧЕРЕДЬ ИСПРАВЛЕНА ЗАМЕРОМ (D39.35): $0-резюм драфта на стенде УЖЕ МЁРТВ** (снапшот разошёлся по трём осям — cheapgate v3→v4, renderfmt v2→v3, langpack 09974d6→a7d4be2), поэтому срочности «гнать, пока жив» НЕТ, а ниты перестали быть условными: **(1) микро-пак «предпрогонная гигиена» ($0-код): два нита общности + ОБЯЗАТЕЛЬНЫЙ флип `Gates.RegressionGuard.Enabled` (невыполненное обязательство D38.4 п.5) + опц. проекция пере-оплаты в `tmctl status`** · **(2) мини-прогон-замер ~10 глав** (драфт ≈$0.02, редактура ≈$0.08–0.15/арм, судья НЕ зовётся ⇒ один арм ≈$0.10–0.17, два ≈$0.20–0.32; перед прогоном бэкап `rerun2/*.db`, БД на схеме v9 против v10 бинаря) · **(3) параллельно $0 — сид/банк-дельта** (元 · 赤城 · 学堂家老 · 春秋蝉; два терма ждут подписи владельца) · **(4) пак-19 в урезанном скоупе** · (4) далее слой-2 извлечение из тел промтов · ru-target · native-Gemini судья. Затем — сид-дельта (元 · 赤城 · 学堂家老 · 春秋蝉), МАСШТАБ целой книги (7,78 млн символов, ~2284 раздела) и пилот Ф2.5. Хроника треков A/B, exp15/16 и стройки паков — архивы ниже + D-лог. > - **Стек:** draft deepseek-v4-flash (thinking ON) → **editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (D39.22; glm-5 резерв, mistral вон D39.20)**, промпт v3-discourse (P1a+чэнъюй+few_shot-тумблер) → судья gemini-3.1-pro-preview; канал B Mistral+grok; 7 ключей; ~$0.85/ранобэ (D30.4). -> - **ОТКРЫТЫЕ ПЕТЛИ (норма 25.07, перепись 180 инцидентов: класс NEVER_CLOSED больше не копим — каждая петля обязана получить диспозицию решено/отложено-с-записью/отклонено; ведёт оркестратор).** *Владелец:* ~~вокабуляр content-лейблов~~ **РЕШЕНО 25.07: ПАРА `violence`/`sexually-explicit`** (D39.27 п.5 — сохраняет D14 п.1 и dspro-редактора на violence) ⇒ следствие в работе: assert-only `action` (дельта пака-17) · ~~Q2 редактор под лейблом~~ **ОТЛОЖЕН С ЗАПИСЬЮ** (D39.27 п.7: при паре связывает только `sexually-explicit`-книги, которых нет; возвращается вместе с предусловием D22.7 перед первой explicit-книгой; кандидаты — grok-4.3 интерим, glm-5 только после сверки ToS Z.AI по первоисточнику, mistral отвергнут D39.20) · ~~ToS-факты + три решения по ним~~ **ЗАКРЫТЫ 25.07 (D39.29 факты + D39.30 подписи владельца):** лейбл `violence` НЕ заводится, интерпретация «нейтральное изображение ≠ пропаганда» зафиксирована письменно · риск Z.AI (плоский запрет «violent content»; экспозиция состоялась в rerun2 через glm-арм) ПРИНЯТ сознательно с условиями пересмотра · две строки `accepts_labels: [sexually-explicit]` (`xai`, `mistral`) ПОДПИСАНЫ и ПРИМЕНЕНЫ в `models.yaml`. **Остаток ToS-вопросов ЗАКРЫТ владельцем 25.07 (D39.32):** local = «политик нет, переводим всё» ⇒ строка применена · Gemini-оговорка читается СУЖЕНИЕМ ⇒ вердикт `FORBIDDEN`→`UNCLEAR`, но по доктрине это НЕ разрешение: строку Gemini не получает, **ждёт одного слова, если владелец хочет подписать интерпретацию как разрешение** · причину пустоты в конфиг НЕ выносим (живёт в quirks-доке) · **ре-чек политик стал ПРАВИЛОМ** (триггеры: Google ToS 30.07.2026 · квартал 25.10.2026 · любая правка `accepts_labels`) · дата аккаунта OpenAI — открыта, приоритет низкий (OpenAI вне цепочки). **Продуктовое (Ф3):** Gemini API Additional ToS запрещает клиентов, «likely to be accessed by individuals under 18» — обязательство на конечный продукт, независимо от лейблов · **промпт-слой под лейблом (НОВОЕ, вскрыто вопросом владельца): лейбл сегодня НЕ доезжает до промпта** (чистые данные маршрутизации + load-time гарантия); нужно ли, чтобы переводчик/редактор ЗНАЛИ о свойстве контента — отдельное решение промпт-слоя · ~~мини-каноны сид-дельты~~ ЗАКРЫТО 26.07: все четыре пункта решены, правок сида ноль; книжные канон-решения живут С КНИГОЙ (`books/gu-zhenren/CANON-NOTES.md`), НЕ в D-логе — урок владельца: движок не строится вокруг одной книги · ~~включение платной петли ремонта~~ **РЕШЕНО 26.07 (D39.38): НЕ включается** — замер 0 в её классах; вернуться при расширении классов и ненулевом остатке · ja→ru-реплика §B5 (тайминг) · старые Ф2.5-блокеры (билингв-якорь — D25 п.9 Q1 · контаминация корпуса — D27 п.4 · судья-дублёр D22.6 · планка запуска · publishable/waiver — D25 п.1 · FN-bound L3 — D25 п.4 · юр-пакет · провенанс 12-*-доков · xAI-ключ off перед продом D27 · residual-тачпойнты exp16, не влитые в сид-дельту: мини-голд алиасов · precision@30, `books/gu-zhenren/exp16/`). *Оркестратор:* ~~ратификация дизайна пака-16~~ РЕШЕНО D39.24 (25.07) · фантом-гард D-ссылок в чек-листе лендинга (действует) · ~~doc-sync pass~~ **ИСПОЛНЕН 25.07** (запись ниже: оба puml перерисованы под пост-пак-16 · баннеры на 01/02/03/04/06/07/08/09 · ресёрч-свип 18/18c/19/20/21/22 · README/POLYGON_PACKAGE4 освежены; residual — пинги полигону в его зоне) · ~~приёмка пака-17 фаза 1~~ **РЕШЕНО D39.26 (25.07: принято в редакции §14, три добора приёмки, фаза 2 размечена)** · **`escalation_model` = ОТВЕТИВШАЯ модель (НОВОЕ, вынесено из пака-17): вердикт-изменение** — golden пинит `esc_model` на ОТКАЗАВШЕМ хопе, маскировка не скрывает ⇒ отдельная ратификация с санкционированным пере-капчером · **`--accept-rebill[=usd]` с порогом `min($0.50, 5%×ProjectedBookUSD)` РАТИФИЦИРОВАН D20.2-Q2, но в коде/CLI ОТСУТСТВУЕТ (НОВОЕ)** — живёт только в спеке `backend/docs/D15.2-*.md`; `--resnapshot` пере-пиннит без суммы · **D22.7 (пер-чанковый L3-скрин) — предусловие первой erotica-книги в проде НЕ снято паком-17 (НОВОЕ, держать отдельным гейтом)** · фантом-гард D-ссылок в чек-листе лендинга (действует). *Бэкенд:* **ХВОСТЫ МИНИ-ПРОГОНА (D39.37, 26.07, по убыванию веса):** (1) **размеченный набор для чекеров** — топ-выбор сессии и оркестратора: без него цифры качества держатся на глазомере · (2) **тест-пин джойна WHAT↔WHICH** (мутация оркестратора выжила — фикс-лист №1 следующего касания) · (3) покрытие WHAT↔WHICH (0/2 и 1/2) + флаговый майнинг-стоп (семантика владельца озвучена, D39.36 п.2; стоп очищается РАУНДАМИ) · (4) `dialogue_dash` мерить только на невиданном тексте (подогнан под 蛊真人) · (5) генеральность нарезки: кана/ханьцзи один класс ⇒ ja `est_out` ~1.7× завышен МОЛЧА; `EstimateTokens` недосчитывает кириллицу (резервации занижены) · (6) golden второй фикстурой С langpack · (7) `prompt_override` — честная формулировка гарантии слоя-2 · (8) майнер/банк не-CJK (едет с ja→ru) · (9) `request_log` скоуп/ретеншен + `first_flag_reason` третье представление истории · (10) флор-16000 без модели · (11) `max_tokens`-упоры вернутся на en · ~~пак-17 (фазы 1–2 + дельта)~~ **ЗАКРЫТ ЦЕЛИКОМ 25.07 (D39.26/27/28)** · ~~ПАК-18 «долги контракта»~~ **ПРИНЯТ И ЗАЛЕНДЕН 25.07 (D39.31) — долгов контракта не осталось**; выдавался (`BACKEND_PACK18_DEBTS_SESSION_PROMPT.md`: `--accept-rebill` на снапшотной гранулярности — `guard_hash` в коде нет и не строим · `escalation_model` = авторитетная модель с САНКЦИОНИРОВАННЫМ пере-капчером golden под этот дифф · два нита общности условно-байт-нейтрально) · **ru-target долг (слой 7, `isRuTarget`×11 прод-сайтов · `TokenizeCyrillic`×6 · ключ «ru» в санитайзере) — ЖДЁТ СВОЕГО ДИЗАЙН-ПАКА** (связывает только не-русский таргет, по текущей карте zh/ja/en→ru не срочен) · **ПАК-19 «голос и состояние» ВЫДАН 25.07** (`BACKEND_PACK19_VOICE_STATE_SESSION_PROMPT.md`, двухфазный; ниты общности едут ЕГО лендингом — D39.31 п.5) · **проекция пере-оплаты в `tmctl status` (НОВОЕ, из отчёта пака-18): спека §9 предлагает заменить булев `ConfigDrift` числом «N чанков, ~$X» — дёшево, `omitempty`, не сделано сознательно** · **не-долги, следующие несущие:** масштаб целой книги (волны/каденс/потолки/ETA на сотнях глав — гоняли максимум 5) · Ф2-механизмы (голос/состояние D21 · native-Gemini судья) · извлечение дискурс-норм/few-shot из ТЕЛ промтов (слой 2, форсинг = ja→ru) · ~~пак-16 ф.2~~ ЗАЛЕНДЕНА 25.07 · per-class исходы ремонта — схемное решение (класс не durable), принимается ВМЕСТЕ с включением петли · ниты общности (владелец 25.07) — **ОТЛОЖЕНЫ ПО ЗАМЕРУ (D39.31 п.5): едут на ближайший ПОЛНЫЙ `--resnapshot`**; для Detail-строк байт-нейтральной формы не существует определительно (дефолт шаблона обязан рендерить текущую строку). Прежняя формулировка: только в байт-нейтральной форме с доказательством исполнением (иначе `CheapGateVersion`/`pack.Version()` двигают снапшот стендовых книг и убивают $0-резюм драфта под замер остатка пака-16): Detail-строки чекеров → шаблоны/цитаты из данных (статический 时辰-текст в generic-файле соврёт второй паре) · множитель ×2 `lintTimeUnits` (`checkers.go:174`) → ключ данных. *Полигон:* ~~пакет 5 (факты ToS + 8 пингов)~~ **ОТРАБОТАН ЦЕЛИКОМ И ПРИНЯТ 25.07 (D39.29); все восемь пингов закрыты; полигон-очереди НЕТ.** Исторический список закрытых пингов: (1) `00-provider-quirks.md:13,73` — катовер deepseek-chat 24.07 ПРОШЁЛ, пост-катовер факт (жив ли алиас, цены) не внесён — live-проба `/models` + вендор-дока; (2) `00-provider-quirks.md:69` — оговорка «mistral-editor-арм до guard» superseded D39.20 (mistral вон из редакторов; rate-limit-цифры оставить — нужны переводчику канала B пака-17); (3) `09-pilot-protocol.md:3` — ⚠-указатель застрял на D31/glm-5: продлить до пост-D39.22 (dspro-интерим · планка ≤2 не пройдена rerun2 · авто-QA слепыми метками D39.20 · стайл-каноны D39.21), тело не трогать; (4) `15-segmentation-empirics.md:6-7` — шапка до сих пор «НИ ОДНОГО платного вызова», а эксп залендён REV.2 (D39.7/D39.8, $12.79) — перевернуть статус-блок; (5) `16-bank-mining.md:3` — дописать финал «ИСПОЛНЕН И ЗАЛЕНДЁН (D39.10); gender-тачпойнт §7 закрыт (D39.19); продолжение — Go-майнер парити EXACT»; (6) `experiments/README.md` — индекс без строк exp15/16 (сверка застряла на D38.2); (7) `eval/README.md` — не тронут с 19.07 (пре-rerun2): освежить статус под пост-D39.22 (эксп закрыт · судейский риг-стандарт D39.7 · экстракция только `tmctl export`). +> - **ОТКРЫТЫЕ ПЕТЛИ (норма 25.07, перепись 180 инцидентов: класс NEVER_CLOSED больше не копим — каждая петля обязана получить диспозицию решено/отложено-с-записью/отклонено; ведёт оркестратор).** *Владелец:* ~~вокабуляр content-лейблов~~ **РЕШЕНО 25.07: ПАРА `violence`/`sexually-explicit`** (D39.27 п.5 — сохраняет D14 п.1 и dspro-редактора на violence) ⇒ следствие в работе: assert-only `action` (дельта пака-17) · ~~Q2 редактор под лейблом~~ **ОТЛОЖЕН С ЗАПИСЬЮ** (D39.27 п.7: при паре связывает только `sexually-explicit`-книги, которых нет; возвращается вместе с предусловием D22.7 перед первой explicit-книгой; кандидаты — grok-4.3 интерим, glm-5 только после сверки ToS Z.AI по первоисточнику, mistral отвергнут D39.20) · ~~ToS-факты + три решения по ним~~ **ЗАКРЫТЫ 25.07 (D39.29 факты + D39.30 подписи владельца):** лейбл `violence` НЕ заводится, интерпретация «нейтральное изображение ≠ пропаганда» зафиксирована письменно · риск Z.AI (плоский запрет «violent content»; экспозиция состоялась в rerun2 через glm-арм) ПРИНЯТ сознательно с условиями пересмотра · две строки `accepts_labels: [sexually-explicit]` (`xai`, `mistral`) ПОДПИСАНЫ и ПРИМЕНЕНЫ в `models.yaml`. **Остаток ToS-вопросов ЗАКРЫТ владельцем 25.07 (D39.32):** local = «политик нет, переводим всё» ⇒ строка применена · Gemini-оговорка читается СУЖЕНИЕМ ⇒ вердикт `FORBIDDEN`→`UNCLEAR`, но по доктрине это НЕ разрешение: строку Gemini не получает, **ждёт одного слова, если владелец хочет подписать интерпретацию как разрешение** · причину пустоты в конфиг НЕ выносим (живёт в quirks-доке) · **ре-чек политик стал ПРАВИЛОМ** (триггеры: Google ToS 30.07.2026 · квартал 25.10.2026 · любая правка `accepts_labels`) · дата аккаунта OpenAI — открыта, приоритет низкий (OpenAI вне цепочки). **Продуктовое (Ф3):** Gemini API Additional ToS запрещает клиентов, «likely to be accessed by individuals under 18» — обязательство на конечный продукт, независимо от лейблов · **промпт-слой под лейблом (НОВОЕ, вскрыто вопросом владельца): лейбл сегодня НЕ доезжает до промпта** (чистые данные маршрутизации + load-time гарантия); нужно ли, чтобы переводчик/редактор ЗНАЛИ о свойстве контента — отдельное решение промпт-слоя · ~~мини-каноны сид-дельты~~ ЗАКРЫТО 26.07: все четыре пункта решены, правок сида ноль; книжные канон-решения живут С КНИГОЙ (`books/gu-zhenren/CANON-NOTES.md`), НЕ в D-логе — урок владельца: движок не строится вокруг одной книги · ~~включение платной петли ремонта~~ **РЕШЕНО 26.07 (D39.38): НЕ включается** — замер 0 в её классах; вернуться при расширении классов и ненулевом остатке; **уточнение D39.39: «0» = ноль в охвате детекторов с измеренным теперь recall (латиница 0.50 боевой, битые формы 0.10) — решение в силе (петля видит теми же детекторами), но читать как «финал чист» нельзя** · **вопросы разметки Р1–Р4 (НОВОЕ, D39.39, пакет-6 §5, 21 спорная строка):** гипербола 千万 (довод: тот же автор в гл.2 даёт 数十万 о том же деянии) · что есть дефект в классе 成 — форма или значение (от ответа precision K5c 1.000 или 0.167) · сокращённая форма термина («гу» при dst «гу-тварь») · принципиально неразрешимая офлайн речь/мысль (если да — потолок recall K4b < 1.0 by construction, вписать в контракт правила) · **место фикс-пака «чекеры» в очереди** (рекомендация: после пака-20, перед паком-19) · ja→ru-реплика §B5 (тайминг) · старые Ф2.5-блокеры (билингв-якорь — D25 п.9 Q1 · контаминация корпуса — D27 п.4 · судья-дублёр D22.6 · планка запуска · publishable/waiver — D25 п.1 · FN-bound L3 — D25 п.4 · юр-пакет · провенанс 12-*-доков · xAI-ключ off перед продом D27 · residual-тачпойнты exp16, не влитые в сид-дельту: мини-голд алиасов · precision@30, `books/gu-zhenren/exp16/`). *Оркестратор:* ~~ратификация дизайна пака-16~~ РЕШЕНО D39.24 (25.07) · фантом-гард D-ссылок в чек-листе лендинга (действует) · ~~doc-sync pass~~ **ИСПОЛНЕН 25.07** (запись ниже: оба puml перерисованы под пост-пак-16 · баннеры на 01/02/03/04/06/07/08/09 · ресёрч-свип 18/18c/19/20/21/22 · README/POLYGON_PACKAGE4 освежены; residual — пинги полигону в его зоне) · ~~приёмка пака-17 фаза 1~~ **РЕШЕНО D39.26 (25.07: принято в редакции §14, три добора приёмки, фаза 2 размечена)** · **`escalation_model` = ОТВЕТИВШАЯ модель (НОВОЕ, вынесено из пака-17): вердикт-изменение** — golden пинит `esc_model` на ОТКАЗАВШЕМ хопе, маскировка не скрывает ⇒ отдельная ратификация с санкционированным пере-капчером · **`--accept-rebill[=usd]` с порогом `min($0.50, 5%×ProjectedBookUSD)` РАТИФИЦИРОВАН D20.2-Q2, но в коде/CLI ОТСУТСТВУЕТ (НОВОЕ)** — живёт только в спеке `backend/docs/D15.2-*.md`; `--resnapshot` пере-пиннит без суммы · **D22.7 (пер-чанковый L3-скрин) — предусловие первой erotica-книги в проде НЕ снято паком-17 (НОВОЕ, держать отдельным гейтом)** · фантом-гард D-ссылок в чек-листе лендинга (действует). *Бэкенд:* **ХВОСТЫ МИНИ-ПРОГОНА (D39.37, 26.07, по убыванию веса):** ~~(1) размеченный набор для чекеров~~ **ЗАКРЫТ 26.07 (полигон-пакет-6, D39.39)** ⇒ породил вход нового фикс-пака «чекеры»: 12 дефектов с file:line (супрессор K5c гасит юнит целиком · атрибуция K4b (23 безатрибутивных + 12 с `!?…`) · `inner_marker` на тире-строки · предохранитель K5a отсекает все реальные магнитуды · заглавные/гомоглифы K2 · 两 в `cheng_re` · U+0301 рвёт `TokenizeCyrillic` · мн.число в `decl.forms`-тулинге · однознаковые ключи пост-чека) — приёмка против набора за $0; **место в очереди — решение владельца (рекомендация оркестратора: после пака-20, перед паком-19)** · (2) **тест-пин джойна WHAT↔WHICH** (мутация оркестратора выжила — фикс-лист №1 следующего касания) · (3) покрытие WHAT↔WHICH (0/2 и 1/2) + флаговый майнинг-стоп (семантика владельца озвучена, D39.36 п.2; стоп очищается РАУНДАМИ) · (4) `dialogue_dash` мерить только на невиданном тексте (подогнан под 蛊真人) · (5) генеральность нарезки: кана/ханьцзи один класс ⇒ ja `est_out` ~1.7× завышен МОЛЧА; `EstimateTokens` недосчитывает кириллицу (резервации занижены) · (6) golden второй фикстурой С langpack · (7) `prompt_override` — честная формулировка гарантии слоя-2 · (8) майнер/банк не-CJK (едет с ja→ru) · (9) `request_log` скоуп/ретеншен + `first_flag_reason` третье представление истории · (10) флор-16000 без модели · (11) `max_tokens`-упоры вернутся на en · ~~пак-17 (фазы 1–2 + дельта)~~ **ЗАКРЫТ ЦЕЛИКОМ 25.07 (D39.26/27/28)** · ~~ПАК-18 «долги контракта»~~ **ПРИНЯТ И ЗАЛЕНДЕН 25.07 (D39.31) — долгов контракта не осталось**; выдавался (`BACKEND_PACK18_DEBTS_SESSION_PROMPT.md`: `--accept-rebill` на снапшотной гранулярности — `guard_hash` в коде нет и не строим · `escalation_model` = авторитетная модель с САНКЦИОНИРОВАННЫМ пере-капчером golden под этот дифф · два нита общности условно-байт-нейтрально) · **ru-target долг (слой 7, `isRuTarget`×11 прод-сайтов · `TokenizeCyrillic`×6 · ключ «ru» в санитайзере) — ЖДЁТ СВОЕГО ДИЗАЙН-ПАКА** (связывает только не-русский таргет, по текущей карте zh/ja/en→ru не срочен) · **ПАК-19 «голос и состояние» ВЫДАН 25.07** (`BACKEND_PACK19_VOICE_STATE_SESSION_PROMPT.md`, двухфазный; ниты общности едут ЕГО лендингом — D39.31 п.5) · **проекция пере-оплаты в `tmctl status` (НОВОЕ, из отчёта пака-18): спека §9 предлагает заменить булев `ConfigDrift` числом «N чанков, ~$X» — дёшево, `omitempty`, не сделано сознательно** · **не-долги, следующие несущие:** масштаб целой книги (волны/каденс/потолки/ETA на сотнях глав — гоняли максимум 5) · Ф2-механизмы (голос/состояние D21 · native-Gemini судья) · извлечение дискурс-норм/few-shot из ТЕЛ промтов (слой 2, форсинг = ja→ru) · ~~пак-16 ф.2~~ ЗАЛЕНДЕНА 25.07 · per-class исходы ремонта — схемное решение (класс не durable), принимается ВМЕСТЕ с включением петли · ниты общности (владелец 25.07) — **ОТЛОЖЕНЫ ПО ЗАМЕРУ (D39.31 п.5): едут на ближайший ПОЛНЫЙ `--resnapshot`**; для Detail-строк байт-нейтральной формы не существует определительно (дефолт шаблона обязан рендерить текущую строку). Прежняя формулировка: только в байт-нейтральной форме с доказательством исполнением (иначе `CheapGateVersion`/`pack.Version()` двигают снапшот стендовых книг и убивают $0-резюм драфта под замер остатка пака-16): Detail-строки чекеров → шаблоны/цитаты из данных (статический 时辰-текст в generic-файле соврёт второй паре) · множитель ×2 `lintTimeUnits` (`checkers.go:174`) → ключ данных. *Полигон:* ~~пакет-6 (размеченный набор чекеров)~~ **ОТРАБОТАН И ПРИНЯТ 26.07 (D39.39): 3015 позиций, 6 прогонов, $0; metrics.json воспроизведён побайтно; набор на стенде `books/gu-zhenren/labels/` = постоянный измерительный стенд чекеров; полигон-очереди НЕТ** (кандидаты следующего пакета: ёфикатор/санитайзер-классы не размечены — §6.5 отчёта; `dialogue_dash` на невиданном тексте) · ~~пакет 5 (факты ToS + 8 пингов)~~ **ОТРАБОТАН ЦЕЛИКОМ И ПРИНЯТ 25.07 (D39.29); все восемь пингов закрыты.** Исторический список закрытых пингов: (1) `00-provider-quirks.md:13,73` — катовер deepseek-chat 24.07 ПРОШЁЛ, пост-катовер факт (жив ли алиас, цены) не внесён — live-проба `/models` + вендор-дока; (2) `00-provider-quirks.md:69` — оговорка «mistral-editor-арм до guard» superseded D39.20 (mistral вон из редакторов; rate-limit-цифры оставить — нужны переводчику канала B пака-17); (3) `09-pilot-protocol.md:3` — ⚠-указатель застрял на D31/glm-5: продлить до пост-D39.22 (dspro-интерим · планка ≤2 не пройдена rerun2 · авто-QA слепыми метками D39.20 · стайл-каноны D39.21), тело не трогать; (4) `15-segmentation-empirics.md:6-7` — шапка до сих пор «НИ ОДНОГО платного вызова», а эксп залендён REV.2 (D39.7/D39.8, $12.79) — перевернуть статус-блок; (5) `16-bank-mining.md:3` — дописать финал «ИСПОЛНЕН И ЗАЛЕНДЁН (D39.10); gender-тачпойнт §7 закрыт (D39.19); продолжение — Go-майнер парити EXACT»; (6) `experiments/README.md` — индекс без строк exp15/16 (сверка застряла на D38.2); (7) `eval/README.md` — не тронут с 19.07 (пре-rerun2): освежить статус под пост-D39.22 (эксп закрыт · судейский риг-стандарт D39.7 · экстракция только `tmctl export`). > - **НАЙДЕНО СПЛОШНЫМ АУДИТОМ 25.07 (D39.34) — 23 позиции, что были ратифицированы, но не попали в трекер; каждая с диспозицией.** *(1) Обязательство, НЕ исполненное:* **флип `Gates.RegressionGuard.Enabled` (D38.4 п.5 «ОБЯЗАН включить» при сборке resnapshot) — ключа нет ни в одном шиппинг-конфиге ⇒ гейт false; rerun2 прошёл без построенной наблюдаемости** → едет обязательной строкой в пак, вызывающий ближайший resnapshot. *(2) Флипы гейтов за подписью владельца (остаются открытыми-с-записью):* coverage `enabled:false` (D12-Q4) · `postcheck_gate` в hard-gate требует пере-замера recall (D24.4+D28.1). *(3) Поглощено курсом:* заморозка «этапа B ~300 глав» (D26 п.1) — **снята D39.33** (масштаб последним), отдельной петлёй не считается. *(4) Открыто, вне «идеала»:* этапы Б+В спеки D15.2 (D33 п.5 «промт выдам после пере-прогона» — прогон был 23.07) — они про content-addressed resume/`guard_hash`, который D39.31 сознательно не строил · F3-остаток идемпотентности · `human_override` LOCK (D29 п.1г, в коде 0 вхождений) · морфо-гейты канцелярита и L1-лемматизация (Ф2, python-сайдкар) · полный OpenCC (0 вхождений) · опциональный пре-перевод гейт. *(5) Мелкие хвосты качества (собрать одним паком когда-нибудь):* ledger-очередь LOW/NOTE из D39.4 · остаток фикс-листа D23 п.4 и D28 п.3(б) · `editor-mono.md` DORMANT (ни в одном конфиге). *(6) Деньги/провайдеры (полигон):* вендор-чек префикс-кэша ZAI/GLM (на нём стоит вся кэш-экономика W1/Q2c) · продление `prices_checked` без правки чисел · scheduler-aware волны под peak-valley DeepSeek (прямой COGS-рычаг) · гейтнутые платные армы (edit-единица >3200 и др.) · wire-probe temperature в thinking-канале DeepSeek. *(7) Продукт/Ф3:* action-security gate перед выдачей tools/webfetch (D25 п.5) · планы research/22 (epub-tag-rewrite, Q7-леджер) · Gemini под-18 обязательство на конечный продукт. *(8) Вход в пак-19:* требование НАРРАТИВНОЙ гендер-аннотации (since_ch-смены + перспектива), а не булева поля — вписано в промт. > - Архивы хроники: `archive/PROGRESS-2026-07-04-10.md` (D31) · `archive/PROGRESS-2026-07-10-13.md` (D39.6-гигиена) · `archive/PROGRESS-2026-07-13-25.md` (слайс 25.07: стройка паков 11–16, rerun2). Записи ниже — живой хвост. @@ -121,6 +121,10 @@ ## Полигон (секция параллельной сессии — записи добавлять сюда) +### Пакет-6 «размеченный набор для чекеров» ОТРАБОТАН И ПРИНЯТ (D39.39), 26.07 + +Сессия полигона собрала набор из 91 юнита шести реальных прогонов (~149k знаков исходника, 3015 размеченных позиций, 70 дефектов, 21 спорная; синтетики ноль), разметила ДО просмотра вердиктов и прогнала НАСТОЯЩИЕ чекеры replace-харнессом. Первый честный замер линеек: где линейка стреляет — почти не врёт (K1/K2/K3/K5b precision 1.000), но recall почти везде низкий (K4b 0.109 · K3 0.100 · K5a 0.000), K5c ИНВЕРТИРОВАН на реальном материале (супрессор «процент» погасил единственный юнит с 10×-ошибками шкалы), K6 шумит 14:1 (мн.число вне `decl.forms` + однознаковый ключ 转). 12 дефектов чекеров с file:line, 4 вопроса владельцу (Р1–Р4). Приёмка оркестратора: `metrics.json` побайтно ре-раном, независимый пересчёт разметки, живой репро U+0301, сверка K5c по сырому корпусу. Отчёт: [archive/reports/POLYGON_CHECKER_LABELS_2026-07-26.md](archive/reports/POLYGON_CHECKER_LABELS_2026-07-26.md); набор — на стенде (вне git), ре-ран детерминирован. + *(Закрытая хроника сессий 1–3, 18+ пакетов и exp10/11 (04–10.07) — в [archive/PROGRESS-2026-07-04-10.md](archive/PROGRESS-2026-07-04-10.md), D31.)* *(Хроника exp12/exp13 (11–12.07) — в [archive/PROGRESS-2026-07-10-13.md](archive/PROGRESS-2026-07-10-13.md).)* diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index 6dfe9c6c..62091ce5 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1058,3 +1058,11 @@ API-529-долг закрыт: 8-осевой refute-by-default воркфлоу **Очередь ратифицирована владельцем:** пак-20 «банк: флаговый стоп + покрытие WHAT→WHICH» (двухфазный — синк → дизайн → ратификация → стройка) → пак-19 «голос/состояние» → свип «стартовый промт + гипотезы ресёрчей 01–22 против построенного» (владелец спросил «прошлись ли по всем?» — честный ответ был «не уверен»; свип $0, аудит-воркфлоу класса D39.34) → добор идеала (4 вопроса границы D39.33 всё ещё у владельца) → МАСШТАБ → пилот. Параллельно полигон: пакет-6 «размеченный набор для чекеров» (200–300 строк/класс, разметка до просмотра вердиктов, precision/recall текущих чекеров — линейки вместо глазомера). **Петля ремонта: НЕ включается** — отложено-с-записью: замер D39.37 дал 0 кандидатов в её классах, чинить нечего; вернуться при расширении набора классов и ненулевом остатке. **Мандат владельца в нормы промтов:** сессия ОБЯЗАНА синковать свою имплементацию об ратифицированную документацию и окружающий код ДО дизайна — таблица «источник ↔ код ↔ вердикт» в отчёте (шаг 0 пака-20; переносится во все последующие кодинг-промты). Контекст мандата: вопросы владельца об алгоритме банка показали, что доверие держится на прослеживаемости «ресёрч → ратификация → код», и её надо ПОКАЗЫВАТЬ, а не подразумевать. + +## D39.39 — Пакет-6 ПРИНЯТ: линейки чекеров впервые измерены против человеческой разметки (3015 позиций, 6 реальных прогонов, $0) — где линейка стреляет, она почти не врёт; но recall почти везде низкий, K5c инвертирован, K6 шумит 14:1; «остаток=0» D39.37 уточнён как «ноль в охвате узких детекторов», НЕ «финал чист» (26.07, оркестратор №8). ✅ + +**Приёмка исполнением:** `metrics.json` воспроизведён ПОБАЙТНО ре-раном харнесса (настоящие `internal/checks` через replace-модуль); разметка пересчитана независимо (3015 позиций: 70 дефектов, 21 спорная); баг U+0301 в `TokenizeCyrillic` воспроизведён живьём («бо́льшим» → «бо»+«льшим»); инверсия K5c подтверждена по сырому корпусу (`acceptance:10:0`: 10×-ошибки шкалы «один процент» для 一成 при слове «процент» в юните, глушащем подчекер целиком — `checkers.go:355`); код-якоря заявленных дефектов сверены. Протокол «разметка ДО вердиктов» соблюдён по конструкции сборки. Отчёт: `docs/archive/reports/POLYGON_CHECKER_LABELS_2026-07-26.md`; набор — на стенде `books/gu-zhenren/labels/` (текст книги, вне git), ре-ран детерминирован. + +**Сводка первого честного замера** (полный разбор — в отчёте): K1 时辰 1.000/1.000 (N=15) · K2 латиница 1.000/0.75 как детектор и 0.50 в боевом охвате — заглавные («Cultivation» в ФИНАЛЕ), гомоглифы («гy») и короткие токены вне класса · K3 битые формы 1.000/0.100 — один шаблон «-йть» вместо класса · K4b смешение 0.833/0.109 — «8→0» подтверждено на мыслях (99/100 молчат), но 41/46 реплик ВСЛУХ не опознаны · K4a — 0 входов на 6863 строках, непроверяем · K5a магнитуда — 0 срабатываний на 149k знаков (предохранитель отсекает идиомы вместе со всеми реальными магнитудами) · K5b 1.000/1.000 (N=8) · K5c — 0.167 читательской меркой / 1.000 конвенцией кода (вопрос Р2) · K5d — precision 0.000 (4 срабатывания, все безобидные) · K6 глоссарий 0.067 — 14 ложных на 1 подлинный (7 — мн.число вне `decl.forms`, 6 — однознаковый ключ 转 на глаголах, 1 — кавычки в форме). 12 дефектов чекеров зафиксированы с file:line (не чинились — полигон не автор). + +**Следствия.** (а) Чтение D39.37: «остаток=0» = ноль срабатываний детекторов, чьи recall теперь ИЗМЕРЕНЫ (петлевые классы по боевому дефолту `repair.go:117`: латиница 0.50 в охвате, битые формы 0.10). Решение «петлю не включать» НЕ пересматривается — петля видит теми же детекторами, чинить ей нечего; но «финал чист» из этой цифры не следует. (б) Набор = постоянный измерительный стенд: любой фикс чекеров теперь приёмуется против него за $0 — «глазомер сессий» в этом слое закрыт как класс. (в) Вход будущего фикс-пака «чекеры»: 12 дефектов file:line + supressor K5c пер-вхождением + атрибуция K4b + `inner_marker` на тире + предохранитель K5a + 两 в `cheng_re` + U+0301 + мн.число в сид-тулинге + однознаковые ключи пост-чека; место в очереди — решение владельца. (г) Четыре вопроса разметки Р1–Р4 — владельцу (гипербола 千万 · что есть дефект в 成 · сокращённая форма термина · неразрешимая офлайн речь/мысль); от Р2 зависит целевая семантика K5c, от Р4 — потолок recall K4b by construction. (д) 38/40 дефектов латиницы живут в ЧЕРНОВИКАХ — вне охвата гейтов по сознательному контракту (`waverun.go:486`); в финалы доехало 2, поймано 1 — вопрос «гейт черновика» отдельный и не срочный (редактор черновик переписывает). diff --git a/docs/POLYGON_PACKAGE6_CHECKER_LABELS_SESSION_PROMPT.md b/docs/archive/prompts/POLYGON_PACKAGE6_CHECKER_LABELS_SESSION_PROMPT.md similarity index 90% rename from docs/POLYGON_PACKAGE6_CHECKER_LABELS_SESSION_PROMPT.md rename to docs/archive/prompts/POLYGON_PACKAGE6_CHECKER_LABELS_SESSION_PROMPT.md index b8fe96b6..bf2c8336 100644 --- a/docs/POLYGON_PACKAGE6_CHECKER_LABELS_SESSION_PROMPT.md +++ b/docs/archive/prompts/POLYGON_PACKAGE6_CHECKER_LABELS_SESSION_PROMPT.md @@ -1,6 +1,8 @@ # Промт полигон-сессии: ПАКЕТ 6 — размеченный набор для чекеров (линейки вместо глазомера) -**Статус: ВЫДАН 26.07.2026, оркестратор №8.** $0, с бэкендом не пересекается. Зона записи: `eval/` + `docs/experiments/`; сам набор — НА СТЕНДЕ (он содержит текст книги — производные книги ВНЕ git). +**Статус: ИСПОЛНЕН И ПРИНЯТ 26.07.2026 (D39.39), АРХИВ.** Отчёт: `docs/archive/reports/POLYGON_CHECKER_LABELS_2026-07-26.md`; набор — на стенде `books/gu-zhenren/labels/`. + +**Статус выдачи: ВЫДАН 26.07.2026, оркестратор №8.** $0, с бэкендом не пересекается. Зона записи: `eval/` + `docs/experiments/`; сам набор — НА СТЕНДЕ (он содержит текст книги — производные книги ВНЕ git). **Первый деливерабл — эхо-блок (≤10 строк). ДО работы.** diff --git a/docs/archive/reports/POLYGON_CHECKER_LABELS_2026-07-26.md b/docs/archive/reports/POLYGON_CHECKER_LABELS_2026-07-26.md new file mode 100644 index 00000000..51d8c746 --- /dev/null +++ b/docs/archive/reports/POLYGON_CHECKER_LABELS_2026-07-26.md @@ -0,0 +1,502 @@ +# Полигон, пакет-6: размеченный набор для чекеров — методика, объёмы, precision/recall + +**Сессия:** полигон, 26.07.2026. Промт: `docs/POLYGON_PACKAGE6_CHECKER_LABELS_SESSION_PROMPT.md` (D39.38). +**Стоимость:** $0 — ни одного вызова провайдера. Сессия НЕ коммитит. +**Набор:** на стенде, `/home/ubuntu/books/gu-zhenren/labels/` (содержит текст книги → ВНЕ git). +В git — только этот отчёт и методика. + +> **Порядок исполнения (протокол «ровно так»).** Разделы §1 (определения) и §2 (объёмы) записаны +> в файл ДО того, как была размечена хоть одна строка, и ДО того, как был прочитан хоть один +> вердикт чекера. Вердикты (`retrieval_state.n_style_flags`, `style_detail`, `postcheck_detail`, +> детали из `report-final.txt`) в этой сессии не открывались до §4. Колонки вердиктов физически +> не выбирались SQL-запросами сборки корпуса — см. `build_corpus.py`. + +> **Ревью-шапка (оркестратор №8, 26.07): ПРИНЯТО, D39.39.** Приёмка исполнением: `metrics.json` +> воспроизведён ПОБАЙТНО ре-раном `measure.py` (харнесс вызывает настоящие `internal/checks` через +> replace-модуль; md5 `7ee20d67…` до и после); разметка пересчитана независимо по `labels/*.jsonl` +> (3015 позиций, дефекты по классам сходятся, кросс-таб K4 100/46/4/9 совпадает); баг U+0301 +> воспроизведён живьём на `TokenizeCyrillic` («бо́льшим» → «бо»+«льшим»); инверсия K5c подтверждена +> по сырому корпусу (`acceptance:10:0`: «Один процент, два процента, три процента» для +> 一成,两成,三成 при шести вхождениях «процент», глушащих подчекер — `checkers.go:355`); код-якоря +> дефектов №1, 5–8, 11–12 сверены с кодом (в т.ч. `cheng_re` без 两 при `两=2` в `cjk_numeral`; +> draft внутри cheap-гейтов потребляет только регресс-гард — `cheapgates.go:182`). Нит: в §3 бакет +> «CJK 9» — это `curly-quote`; подкласс `cjk-leak` = 11 строк, как в §6 (счётчики консистентны). + +## §1. Определения классов — зафиксированы ДО разметки + +Определения выведены из КОДА (код первичен), а не из названий классов. Каждое — моими словами, +с якорем `file:line`. Рядом — что чекер, по коду, НЕ считает дефектом (это важнее определения: +именно тут живут расхождения разметки и вердикта). + +### K1. DC1 — время (时辰 / счётные единицы) + +Якорь: [checkers.go:207-245](../../../backend/internal/checks/checkers.go#L207-L245), +данные пары — [dc-checkers.txt:41-54](../../../backend/configs/langpacks/zh-ru/dc-checkers.txt#L41-L54). + +**Моё определение.** Дефект = в источнике стоит длительность, измеренная в 时辰 (китайский «большой +час» = 2 астрономических часа), а в переводе та же длительность названа в русских часах с ЧИСЛОМ, +взятым из источника без пересчёта. `三个时辰` → «три часа» вместо ~«шесть часов»: длительность +занижена вдвое. Отдельная подформа — дробная: `半个时辰` (≈1 час) → «полчаса», длительность тоже +занижена вдвое. + +**Что кодом НЕ считается дефектом (и я размечаю так же, иначе меряю не тот детектор):** +- перевод без явного счёта часов («долго», «через время», «полдня») — валидный парафраз, не дефект + (`checkers.go:230-232`: нет совпадения `ru_hours_re` → 0); +- рендер с ПРАВИЛЬНЫМ числом (三个时辰 → «шесть часов») — не дефект; +- рендер с числом, которое не равно ни исходному счёту, ни удвоенному (三个时辰 → «четыре часа») — + по коду НЕ дефект: условие срабатывания `ruNum == n && ruNum != expectedHours` + (`checkers.go:239`). Такую строку я размечаю как дефект перевода, но помечаю подклассом + `outside-rule` — она обязана попасть в recall-гэп, а не в precision-ошибку. + +**Единица разметки.** Одно вхождение 时辰 в исходнике юнита × прогон (один и тот же исходник, +переведённый разными армами, даёт разные рендеры → разные items). ID: `run:chapter:chunk_idx:src_offset`. + +### K2. Латиница-остаток + +Якорь: [checkers.go:378-411](../../../backend/internal/checks/checkers.go#L378-L411). + +**Моё определение.** Дефект = в русском выходе осталось целое ЛАТИНСКОЕ слово, которое там быть не +должно: непереведённый кусок исходного/промежуточного английского («открыл их again»), утечка +служебной лексики промпта/разметки, английский термин вместо русского. + +**Что кодом НЕ считается дефектом:** +- токен с заглавной буквой — код отбрасывает (`checkers.go:391`): «сигнал имени собственного/бренда». + Я размечаю такие строки отдельно: заглавная ≠ легитимность (`TM`, `BANK`, `Cultivation` — утечки); +- токен короче 3 букв, токен с цифрой внутри (`v1`), римская цифра — отбрасывается; +- токен в per-project allowlist. + +**Единица разметки.** Одно вхождение максимального латинско-цифрового токена в целевом тексте +(финал или черновик). ID: `run:chapter:chunk_idx:field:byte_offset`. + +### K3. Битые словоформы + +Якорь: [checkers.go:437-454](../../../backend/internal/checks/checkers.go#L437-L454), +данные цели — [target-ru.txt:9](../../../backend/internal/lang/data/target-ru.txt#L9) (`broken_suffix йть`). + +**Моё определение.** Дефект = русское слово, которого в языке нет как формы: искажённая морфология +(«войть» вместо «войти»), склеенные/разорванные основы, обрубленное окончание, слово с +несуществующим суффиксом. Не относится: редкие, но правильные слова; авторские неологизмы книги; +транслит имён по Палладию; окказионализмы жанра. + +**Что кодом НЕ считается дефектом:** ВСЁ, кроме слов длиной ≥4, заканчивающихся на «-йть». +Код это и заявляет прямо: «Zero false-positive by construction (only a structural signature, no +dictionary)» (`checkers.go:436`). То есть у класса заведомо один-единственный обнаруживаемый шаблон, +а класс «битые словоформы» шире. Это и надо измерить. + +**Единица разметки.** Один русский словотип (тип, не токен) + позиция первого вхождения. +ID: `type:<слово>`, плюс список вхождений. + +### K4. `dialogue_dash` + +Якорь: [cheapgates.go:199-241](../../../backend/internal/checks/cheapgates.go#L199-L241), +форма реплики — `chevronSpeechShape` (`:250`), «это речь вслух?» — `isSpokenChevronLine` +([checkers.go:467-483](../../../backend/internal/checks/checkers.go#L467-L483)), +данные цели — [target-ru.txt:16-53](../../../backend/internal/lang/data/target-ru.txt#L16-L53). + +Класс распадается на два независимых правила; меряю их РАЗДЕЛЬНО, потому что и живут они врозь. + +**K4a — неверный маркер реплики (строчное правило).** Дефект = строка открывает прямую речь +маркером, которого в русской типографике нет: прямая ASCII-кавычка `"`, дефис `-` или короткое +тире `–` вместо длинного `—`. Условие формы: после маркера пробел и буква (для кавычки пробел +необязателен) — `dialogueShape`/`quoteShape` (`:279`,`:293`). +*НЕ дефект по коду:* `— 15 минут спустя` (тире + пробел + цифра — это врезка, не реплика, +`:210`); дефис, приклеенный к слову (перенос). + +**K4b — смешение стилей прямой речи (правило уровня чанка).** Дефект = внутри одного чанка речь +вслух оформлена И длинным тире, И кавычками-ёлочками. Ёлочная строка засчитывается, только если +(1) имеет форму атрибуции `«Реплика», — глагол` (`chevronSpeechShape`, `:250`) И (2) её атрибуция +содержит глагол ГОВОРЕНИЯ из закрытого списка цели и НЕ содержит маркера внутренней речи +(«про себя», «мысленно», …) — `isSpokenChevronLine`. +*НЕ дефект по коду и по русской норме:* ёлочки для МЫСЛИ рядом с тире для речи — это правильно +набранная проза, а не столкновение стилей (правка v5, `cheapgates.go:68-81`). Именно тут стоит +цифра «8→0», которую надо проверить честно. +*Сознательные промахи кода:* восклицательная реплика `«Реплика!» —` (без запятой) и безатрибутивная +`«Реплика.»` не распознаются как ёлочная речь (`:248-249`). + +**Единица разметки.** K4a/K4b — одна непустая строка целевого текста. +ID: `run:chapter:chunk_idx:field:line_no`. Дополнительно размечаю строки, начинающиеся с БУКВЫ, — +там живёт прямая речь вообще без маркера (это невидимо для чекера by construction, идёт в recall-гэп). + +### K5. Число-дрейф / магнитуды + +Четыре разных детектора; меряю раздельно. + +- **K5a — 万/億-магнитуда** ([cheapgates.go:421-462](../../../backend/internal/checks/cheapgates.go#L421-L462)). + Дефект = порядок величины из источника (`三万` = 3·10⁴) не представлен в переводе ни числом, ни + словом-магнитудой нужного порядка. *НЕ дефект по коду:* магнитуда, пересказанная прозой без + слов-магнитуд (`:453-459` — молчит); идиомы `万一/万分/千万/亿万` без цифры перед 万 (`:491`); + голые единицы `十万/百万` (там нет цифры перед маркером). +- **K5b — DC2 千万 / 数十万** ([checkers.go:281-302](../../../backend/internal/checks/checkers.go#L281-L302)). + Дефект = 千万 (10⁷) отдано как «тысячи», 数十万 (несколько ×10⁵) — как «десятки тысяч». + Код сам признаёт неустранимую двусмысленность: 千万 сплошь и рядом ГИПЕРБОЛА («тьма», «мириады»), + и её «тысячи» — в регистре (§5-A4, `cheapgates.go:90-93`). Размечаю гиперболу отдельным + подклассом `hyperbole`, решение по ней — не моё (идёт владельцу). +- **K5c — 成-процент** ([checkers.go:346-370](../../../backend/internal/checks/checkers.go#L346-L370)). + Дефект = 成 (десятая доля: 六成 = 60%) отдано десятичной ДОЛЕЙ вместо процента. + Внимание: код считает дефектом ФОРМУ, а не значение (`cheapgates.go:84-89` — сознательно оставлено). + Значит «три десятых» для 三成 — по коду дефект, хотя значение верное. Размечаю по коду + (`form-defect`), а «значение верно/неверно» веду ВТОРОЙ колонкой. +- **K5d — дрейф чисел черновик→финал** + ([regressionguard.go:64-76](../../../backend/internal/checks/regressionguard.go#L64-L76)). + Дефект = многозначное арабское число есть в черновике и пропало в финале (или появилось из + ниоткуда). *НЕ дефект по коду:* однозначные числа (их штатно пишут словом); число, переписанное + словами при редактуре, — код сам называет это своим ложным флагом (`:24-28`). + Гейт включён только в мини-прогоне (`minirun/pipeline.yaml: regression_guard.enabled: true`); + в rerun2 его нет. + +**Единица разметки.** K5a/K5b/K5c — вхождение триггера в исходнике × прогон. +K5d — (юнит, числовой токен, сторона). + +### K6. Глоссарий-промахи + +Якорь: [mempostcheck.go:61-122](../../../backend/internal/membank/mempostcheck.go#L61-L122). + +**Моё определение.** Дефект = термин глоссария, чей ИСХОДНЫЙ вид встретился в исходнике юнита, а в +переводе не появилось ни одной принятой формы его перевода: термин выброшен, переведён по-другому +или искажён. + +**Что кодом НЕ считается дефектом:** sticky-записи (их src в этом чанке и не должен быть, `:69`); +записи без dst; записи со статусом `ambiguous` — они не идут в счёт (`CountConfirmedMisses`, `:49`). +Принятое множество = базовый dst ∪ сохранённые склонённые формы (`decl.forms`), сравнение — +по целому слову с границами по буквам (`containsWholeWord`, `:128`). + +**Единица разметки.** (юнит, термин глоссария, чей src встречается в исходнике юнита). +ID: `run:chapter:chunk_idx:src`. + +### Общая шкала меток + +Каждый item получает одну метку: +`defect` · `ok` · `disputable` (спорные — владельцу, я их не решаю) · +плюс необязательный подкласс (`outside-rule`, `hyperbole`, `form-defect`, `unmarked-speech`, …). +`disputable` в знаменатель precision/recall НЕ входит и считается отдельно. + +--- + +## §2. Материал и объёмы — зафиксировано ДО разметки + +Корпус: `/home/ubuntu/books/gu-zhenren/labels/raw/corpus.jsonl` — 91 юнит из шести реальных +прогонов на стенде (никакой синтетики). + +| прогон | юнитов | исходник, зн. | черновик, зн. | финал, зн. | что это | +|---|---:|---:|---:|---:|---| +| `acceptance` | 53 | 72 646 | 239 534 | 239 522 | приёмка 25 глав, 10.07 (старый стек) | +| `minirun` | 14 | 28 837 | 90 882 | 94 490 | мини-прогон 10 глав, 25.07 (шиппинговая форма) | +| `rerun2-dspro` | 7 | 14 127 | 46 142 | 46 080 | пере-прогон гл.1–5, арм deepseek-v4-pro | +| `rerun2-glm` | 7 | 14 127 | 46 142 | 45 956 | тот же исходник, арм glm | +| `rerun2-mistral` | 7 | 14 127 | 46 142 | 41 875 | тот же исходник, арм mistral | +| `verify2` | 3 | 5 368 | 17 778 | 17 423 | двухглавая верификация, 26.07 | +| **итого** | **91** | **149 232** | **486 620** | **485 346** | | + +Исходники восстановлены детерминированной пере-нарезкой текущим кодом +(`chunk.IngestEncoded` + `chunk.SplitChunks` + группировка по `EditUnitID` — 1:1 с +`status.go:184` и `wave.go:41`), черновики — из `checkpoints.response_text` через +`checks.ExportNormalize`, финалы — из экспортов прогонов. +**Самопроверка сборки:** восстановленный исходник сверен побайтно с колонкой `source` готового +экспорта `rerun2 --pairs`. Совпадение полное на юнитах без заголовка главы; на 5 юнитах-началах +главы расхождение ровно 4 руны — это `第N节:`, который текущий код снимает в манифест-заголовок +(политика заголовков пака-13, `export.go:213-220`), а экспорт 23.07 ещё оставлял в колонке. +Расхождение объяснено и ожидаемо, а не молча проигнорировано. + +### Физический потолок объёма по классам (посчитан ДО разметки) + +Промт задаёт ориентир 200–300 строк на класс. **Четыре класса из шести физически столько не +содержат** — вот честные потолки на этом корпусе: + +| класс | что считалось | потолок items | 200–300 достижимо? | +|---|---|---:|---| +| K1 DC1 时辰 | вхождений 时辰 в исходниках юнитов | **15** (4 в уникальном исходнике) | **нет** | +| K2 латиница | вхождений латинско-цифровых токенов в целевом тексте | **92** (32 типа; из них попадают под правило кода 7 типов) | **нет** | +| K3 битые формы | русских словотипов | 12 946 типов (1 999 hapax) | да, выборкой | +| K4 dialogue_dash | непустых строк целевого текста | 6 863 (тире 1 259 · ёлочки 478 · прочие 5 088 · дефис/кавычка **0**) | да, выборкой | +| K5a магнитуда 万 | числовых пробегов с 万 в исходнике | 37 уникальных (×армы) | нет | +| K5b DC2 | 千万 3 · 数十万 2 уникальных (×армы) | **~15** | **нет** | +| K5c 成-процент | `цифра+成` в исходнике | 35 уникальных (×армы) | нет | +| K5d дрейф чисел | многозначных арабских чисел во всём корпусе | **19** | **нет** | +| K6 глоссарий | (юнит × термин, чей src есть в исходнике) | сотни | да | + +Синтетикой я эти классы не добиваю (см. §6 — там отдельная помеченная секция о том, чего набор +не покрывает и что для этого нужно). + +Отдельный факт, который стоит прочитать до всех цифр: **строк с дефисом или ASCII-кавычкой в начале +во ВСЁМ корпусе — ноль**. То есть ветка K4a (`hyphenLike`, `cheapgates.go:213-222`) на реальном +материале не срабатывает ни разу и её precision на этом наборе неизмерим — измеряется только K4b. + + + +--- + +## §3. Разметка: что сделано и как + +Разметил я, читая исходник и перевод; вердикты чекеров были получены ТОЛЬКО после того, как все +файлы `labels/*.jsonl` были записаны. Сети-кандидаты выведены из определений §1, а не из реализации +чекера (иначе recall меряется сам против себя) и сознательно ШИРЕ правил кода. + +| класс | единица разметки | размечено | из них дефект | спорных | +|---|---|---:|---:|---:| +| K1 DC1 时辰 | вхождение 时辰 × прогон | **15** (исчерпывающе) | 6 | 0 | +| K2 латиница | вхождение лат.-цифрового токена | **92** (исчерпывающе) | 40 | 0 | +| K3 битые формы | русский словотип | **2 177** (весь hapax-слой 1 999 + 178 из сетей) | 10 | 0 | +| K4 dialogue_dash | строка целевого текста | **348** (ёлочки 150 · тире 80 · буквенные 80 · markdown 29 · CJK 9) | 4 | 9 | +| K5a магнитуда 万 | вхождение × прогон | **67** (исчерпывающе) | 1 | 3 | +| K5b DC2 | вхождение × прогон | **11** (исчерпывающе) | 1 | 3 | +| K5c 成-процент | вхождение × прогон | **40** (исчерпывающе) | 7 | 4 | +| K5d дрейф чисел | (юнит, число, сторона) | **5** (исчерпывающе) | 0 | 0 | +| K6 глоссарий | (юнит × сработавший термин) | **260** из 1 257 (выборка) | 1 | 2 | +| **итого** | | **3 015** | **70** | **21** | + +Ориентир 200–300 строк выдержан там, где материал это позволяет (K3, K4, K6). Четыре класса +физически меньше — размечены ЦЕЛИКОМ и цифра названа честно; синтетикой не добивал (см. §6). + +Две проверки собственной работы исполнением, обе поймали мою ошибку, не чужую: +1. Восстановленный исходник сверен побайтно с колонкой `source` готового экспорта `rerun2 --pairs` + (§2) — расхождение оказалось ровно в 4 руны заголовка и объяснено. +2. Первый прогон дал по латинице «чекер не сработал ни разу» при том, что пер-юнитный прогон + показывал `latin_residue=1`. Причина — в моей измерялке: Go отдаёт БАЙТОВЫЕ смещения, а пул + считан в символах. После починки — precision 1.000 / recall 0.750. Цифра «0» была моей, не кода. + +--- + +## §4. Первое измерение: precision/recall ТЕКУЩИХ чекеров + +Вердикты получены вызовом НАСТОЯЩИХ функций пакета `internal/checks` (харнесс-модуль вне репо, +`replace` на репозиторный backend; ноль правок в репозитории). Спорные строки в знаменатель не +входят. Единица измерения выбрана та, на которой чекер реально выносит вердикт: для src↔tgt +подчекеров это ЮНИТ (одно срабатывание на единицу редактуры), для остальных — строка/токен/словотип. + +| класс | уровень | N | TP | FP | FN | TN | **precision** | **recall** | +|---|---|---:|---:|---:|---:|---:|---:|---:| +| K1 DC1 时辰 | юнит | 15 | 6 | 0 | 0 | 9 | **1.000** | **1.000** | +| K2 латиница (детектор) | токен | 92 | 30 | 0 | 10 | 52 | **1.000** | **0.750** | +| K2 латиница (боевой охват: только финалы) | токен | 31 | 1 | 0 | 1 | 29 | **1.000** | **0.500** | +| K3 битые словоформы | словотип | 2 177 | 1 | 0 | 9 | 2 167 | **1.000** | **0.100** | +| K4a неверный маркер реплики | строка | 348 | 0 | 0 | 0 | 348 | н/д | н/д | +| K4b ёлочная речь вслух (смешение) | строка | 146 | 5 | 1 | 41 | 99 | **0.833** | **0.109** | +| K5a магнитуда 万/億 | юнит | 27 | 0 | 0 | 1 | 26 | н/д (0 срабатываний) | **0.000** | +| K5b DC2 千万/数十万 | юнит | 8 | 1 | 0 | 0 | 7 | **1.000** | **1.000** | +| K5c 成-процент (читательская мерка) | юнит | 15 | 1 | 5 | 1 | 8 | **0.167** | **0.500** | +| K5c 成-процент (конвенция кода: форма=дефект) | юнит | 16 | 7 | 0 | 1 | 8 | **1.000** | **0.875** | +| K5d дрейф чисел | позиция | 5 | 0 | 4 | 0 | 1 | **0.000** | н/д | +| K6 глоссарий (все сработавшие термины) | юнит×термин | 258 | 1 | 14 | 0 | 243 | **0.067** | **1.000** | +| K6 глоссарий (только реально инъецированные) | юнит×термин | 215 | 0 | 8 | 0 | 207 | **0.000** | н/д | + +«н/д» — метрика не определена: либо чекер не сработал ни разу (нет знаменателя precision), либо +положительных по разметке ноль (нет знаменателя recall). Это тоже результат, а не пропуск. + +### Что стоит за цифрами (механика, с якорями) + +**K1 (DC1 时辰) — 6/6 и ни одного ложняка.** Единственный класс, где линейка работает ровно как +описана. Шесть подлинных дефектов: `三个时辰 → «три часа»` (три арма rerun2 из четырёх) и +`半个时辰 → «полчаса»` (dspro, glm, acceptance). Девять корректных рендеров, включая два +транслитерированных («чуть больше одного шичэня») — код на них молчит, и это правильно. + +**K5c (成-процент) — самая тяжёлая находка пакета.** Пять из шести срабатываний пришлись на юниты, +где ЗНАЧЕНИЕ передано верно («две-три десятых» для 两三成 = 20–30%, «сорок четыре сотых» для +四成四 = 0.44). А ЕДИНСТВЕННЫЙ юнит с настоящими ошибками шкалы — `acceptance:10:0`, где +`一成` (10%) отдано как «один процент», `一成,两成,三成` как «Один процент, два процента, три +процента», а `一成四` (14%) как «одна доля и четыре части», — **пропущен**: в этом же юните где-то +есть слово «процент», и супрессор процентной формы гасит подчекер целиком +([checkers.go:355](../../../backend/internal/checks/checkers.go#L355)). То есть на реальном материале +правило сработало ровно наоборот замыслу: промолчало там, где шкала действительно сломана в 10 раз, +и заговорило там, где всё верно. По конвенции самого кода (форма-дробь = дефект) precision=1.000 — +цифры расходятся не из-за реализации, а из-за того, ЧТО считать дефектом. Это вопрос владельцу (§5). + +**K4b (`dialogue_dash`, смешение) — «8→0» проверено.** Правка v5 в основном работает: из 100 +размеченных ёлочных МЫСЛЕЙ чекер флагнул **одну** (99 из 100 — молчание). Но ёлочных реплик ВСЛУХ +в корпусе 46 (31% ёлочных строк), и из них поймано 5. Разбор 41 пропуска: + +| причина | строк | +|---|---:| +| безатрибутивная реплика — связки `«…», —` нет вообще | 23 | +| реплика оканчивается на `!` / `?` / `…`, запятой после `»` нет — сознательный промах кода ([cheapgates.go:248-249](../../../backend/internal/checks/cheapgates.go#L248-L249)) | 12 | +| закрывающая `»` дальше 400 знаков (длинная реплика) | 3 | +| связка есть, но глагол говорения не из закрытого списка («раздался голос», «покинули его») | 3 | + +Единственное ложное срабатывание вскрывает механику: строка +`«Месть не входит в мои планы…», — подумав так, Фан Юань усмехнулся … и равнодушно произнёс: —` +— мысль, но `isSpokenChevronLine` ищет глагол говорения по ВСЕЙ строке +([checkers.go:471-481](../../../backend/internal/checks/checkers.go#L471-L481)), а «произнёс» +стоит в другом предложении и относится к следующей реплике. + +**K4a — правило не проверяемо на этом корпусе.** Строк, начинающихся с дефиса, короткого тире или +ASCII-кавычки, во всём корпусе (6 863 непустых строки) — **ноль**. Ветка `hyphenLike` +([cheapgates.go:213-222](../../../backend/internal/checks/cheapgates.go#L213-L222)) ни разу не +получила входа. Precision/recall неизмеримы, и это надо знать: половина класса живёт непроверенной. + +**Класс, которого у чекера нет: ОБРАТНАЯ ошибка маркера.** 4 строки из 80 размеченных тире-строк — +внутренняя речь, набранная тире как речь вслух: «— Жаль только этого хорошего гу, — вздохнул ПРО +СЕБЯ Фан Юань», «— …, — недовольно хмыкнул ПРО СЕБЯ старейшина», «— Как же так… — бормотал СЕБЕ ПОД +НОС Фан Чжэн». Маркеры «про себя» / «себе под нос» уже есть в данных цели как `inner_marker`, но +применяются только к ёлочкам. По конструкции чекер считает любую тире-строку правильной, поэтому +recall здесь 0.000 из 4. + +**K5a (магнитуда 万) — ноль срабатываний на всём корпусе, и это структурно.** Из 67 вхождений 55 — +идиомы (万物之灵, 万一, 千辛万苦, 万家灯火, 成千上万, 罪该万死, 十万八千里…). Оставшиеся реальные +магнитуды (数十万, 千万, 数万) не проходят предохранитель «цифра перед большим маркером» +([cheapgates.go:513-526](../../../backend/internal/checks/cheapgates.go#L513-L526)): 数 и 十 — не +цифры класса `Digit`, 千 — единица, а не цифра. Предохранитель отсекает идиомы правильно, но вместе +с ними — и все реальные магнитуды этого корпуса. Единственный подлинный дефект класса +(数十万 → «десятки тысяч» у mistral) пойман ДРУГИМ подчекером, DC2. + +**K5d (дрейф чисел) — 4 срабатывания, все безобидные.** Три — номера глав в заголовке, которого не +было в черновике; одно — `66% → «шестьдесят шесть процентов`, то есть ровно тот ложный флаг, который +код за собой признаёт ([regressionguard.go:24-28](../../../backend/internal/checks/regressionguard.go#L24-L28)). +Подлинного дрейфа в корпусе нет: многозначных арабских чисел во всех 91 юните — 19. + +**K6 (глоссарий) — 14 ложных на 1 подлинный.** Разбор: +- **6** — однознаковый ключ `转` сработал на ГЛАГОЛЕ (转身 «обернулся», 转过转角 «за поворотом», + 辗转 «мыкался», 转为 «стать», 脑筋转不快 «мысль ворочается медленно»). Ранга в исходнике нет, + переводить нечего, но условие «src сработал» — подстрочное вхождение. +- **7** — целевая форма есть, но во МНОЖЕСТВЕННОМ числе, которого нет в `decl.forms`: + «первокамней» при формах `первокамня/первокамню/первокамень`, «смертных» при `смертного/…`, + «гу-тварей» при `гу-твари/гу-тварь`. Это ровно `inflection_gap`, который код называет пробелом + СИДА, а не кода ([mempostcheck.go:109-111](../../../backend/internal/membank/mempostcheck.go#L109-L111)) — + теперь он измерен: 7 из 258 пар, ~2.7%. +- **1** — `甲等 → «разряд А»`, в тексте «разряда „А“»: типографские кавычки внутри формы рвут + сравнение по целому слову. + +Единственный подлинный промах (`minirun:8:1`, 古月方正 ×6 → «Фан Чжэна», клановое имя исчезло) +пойман. Но на подмножестве, которое боевой пост-чек РЕАЛЬНО проверял (217 из 260 пар — остальные не +прошли отбор/бюджет инъекции), подлинных промахов нет вовсе, а ложных 8: precision 0.000. + +**K2 и K3 — линейки честные, но узкие.** Ни одного ложного срабатывания в 92 и 2 177 items +соответственно. Recall ограничен конструкцией: латиница пропускает заглавные («Cultivation» в +ФИНАЛЕ acceptance — [checkers.go:391](../../../backend/internal/checks/checkers.go#L391)), токены +короче трёх («гy» с латинской `y` вместо кириллической `у` — гомоглиф) и токены с цифрой; битые +формы ловят ровно один шаблон «-йть» из десяти найденных мной битых слов. + +### Зафиксированные дефекты чекеров (фиксация, НЕ правка) + +Я не автор чекеров и ничего здесь не чинил. Каждый пункт — с якорем и с тем, чем он подтверждён +на наборе. + +| # | якорь | что именно | подтверждение на наборе | +|---|---|---|---| +| 1 | [checkers.go:355](../../../backend/internal/checks/checkers.go#L355) | процентный супрессор гасит подчекер по ВСЕМУ юниту, если слово «процент» встретилось где угодно | единственный юнит с настоящими 10×-ошибками шкалы (`acceptance:10:0`) пропущен | +| 2 | [checkers.go:471-481](../../../backend/internal/checks/checkers.go#L471-L481) | глагол говорения ищется по всей строке, а не в атрибуции ёлочки | 1 из 1 ложных срабатываний K4b | +| 3 | [cheapgates.go:250-275](../../../backend/internal/checks/cheapgates.go#L250-L275) | форма `«…», —` — единственный признак ёлочной речи | 38 из 46 реплик вслух не опознаны (23 безатрибутивных + 12 с `!`/`?`/`…` + 3 длинных) | +| 4 | [cheapgates.go:209-233](../../../backend/internal/checks/cheapgates.go#L209-L233) | тире-строка засчитывается корректной ВСЕГДА | 4 мысли, набранные тире («вздохнул ПРО СЕБЯ»), невидимы, хотя `inner_marker` уже есть в данных цели | +| 5 | [cheapgates.go:513-526](../../../backend/internal/checks/cheapgates.go#L513-L526) | «цифра перед большим маркером» отсекает 数十万 / 千万 / 十万八千 вместе с идиомами | подчекер `number_magnitude` не сработал ни разу на 149 232 знаках исходника | +| 6 | [checkers.go:391](../../../backend/internal/checks/checkers.go#L391) | заглавная буква = «имя собственное» → токен отброшен | «Cultivation» в ФИНАЛЕ `acceptance:3:0` невидим; маркеры утечки банка `TM`, `BANK` — тоже | +| 7 | [checkers.go:398](../../../backend/internal/checks/checkers.go#L398) | `minLatinResidueLen = 3` | гомоглиф «гy» (латинская `y` в слове «гу») невидим — 2 вхождения | +| 8 | [dc-checkers.txt:65](../../../backend/configs/langpacks/zh-ru/dc-checkers.txt#L65) | класс символов `cheng_re` не содержит 两, хотя `cjk_numeral` содержит (`两=2`) | `两成` в ряду `一成,两成,三成` (minirun ch10) не виден подчекеру процентов | +| 9 | [mempostcheck.go:112-122](../../../backend/internal/membank/mempostcheck.go#L112-L122) | принятое множество = базовый dst ∪ `decl.forms`; множественного числа в сиде нет | 7 ложных из 14: «первокамней», «смертных», «гу-тварей» | +| 10 | [mempostcheck.go:61-80](../../../backend/internal/membank/mempostcheck.go#L61-L80) | «src сработал» = подстрочное вхождение; однознаковый ключ `转` совпадает с частым глаголом | 6 ложных из 14 | +| 11 | [runes.go:32-50](../../../backend/internal/text/runes.go#L32-L50) | `TokenizeCyrillic` рвёт слово на комбинирующем ударении U+0301 (оно не кириллица) | «бо́льшим» → «бо» + «льшим» в финале `acceptance:25:0`; затрагивает и ёфикатор, и битые формы, и пост-чек | +| 12 | [waverun.go:486](../../../backend/internal/pipeline/waverun.go#L486) (охват, не баг) | `draft` уходит ТОЛЬКО в регресс-гард; остальные подчекеры видят лишь финал | 38 из 40 дефектов латиницы живут в черновиках и по конструкции вне охвата | + +Пункты 1–4 и 6–8 — это правила, которые можно поменять. Пункты 9–10 код сам называет пробелом +СИДА, а не кода; пункт 12 — сознательный контракт. Что из этого чинить и чинить ли — не моё решение. + +Побочные наблюдения вне шести классов (не размечал, только фиксирую факт срабатывания на 91 юните): +`dc6_register` — 4 юнита, `yo` — 1 юнит («тёмно»/«темно» в `rerun2-glm:1:0`). Ёфикатор на корпусе +недоразмечен: пар типа «вошел/вошёл», «шепот/шёпот», «отчетливо/отчётливо» в тексте заметно больше +одной — это отдельный класс и отдельный пакет. + +--- + +## §5. Спорные строки — пачкой владельцу, я их не решал + +21 item помечен `disputable` и в знаменатель метрик не входит. Все сводятся к четырём решениям. + +**Р1. 千万 как гипербола (3 item, класс K5b/K5a).** `杀了千万人的性命` в проклятии-обвинении: три +арма дали «тысячи и тысячи людей» / «тысячи жизней», один — «миллионы жизней». Довод в пользу +гиперболы, которого нет в коде: **тот же автор в главе 2 называет то же самое деяние +`屠杀了数十万人` (~10⁵)**, то есть 10⁷ в главе 1 — риторика персонажа, а не число. Если владелец +признаёт гиперболу не-дефектом, precision DC2 остаётся 1.000; если признаёт дефектом — правило +недосчитывает 3 из 4 армов, и вопрос переходит в «чем отличать гиперболу от магнитуды офлайн». +Код прямо пишет, что офлайн не отличает ([cheapgates.go:90-93](../../../backend/internal/checks/cheapgates.go#L90-L93)). + +**Р2. Что считать дефектом в классе 成 (4 item + вся расходящаяся метрика).** Рендер «сорок четыре +сотых» для 四成四 несёт ВЕРНОЕ значение (0.44) в форме дроби. Конвенция кода — форма и есть дефект; +читательская мерка — дефект только когда сломано значение. От выбора зависит **precision 1.000 или +0.167**. Отдельно: 4 item в `minirun:10:0` — «доля» в одном абзаце обозначает и 分 (1%), и 成 (10%) +(«потеряло целую долю», «истощилась на целых три доли»); тут я не смог решить, что имел в виду +переводчик, а не что имел в виду код. + +**Р3. Сокращённая форма термина (2 item, K6).** `蛊虫` при одобренном dst «гу-тварь» переведено просто +«гу» («отличительная гу клана Гуюэ»). Понятие передано и внутри юнита последовательно, но +утверждённой формы нет. Это дефект перевода, пробел полноты сида или норма — решать владельцу; от +ответа зависит, считать ли такие срабатывания пост-чека ложными. + +**Р4. Неоднозначная речь/мысль (9 item, K4).** Строки, где по тексту нельзя решить, произнесено это +вслух или подумано: «— Пятьсот лет жизни — словно сон» (один арм ставит тире, другой ёлочки на той +же фразе); «— Хе, по срокам как раз он. — Старейшина ... пробормотал себе под нос: —» (бормочет, +но при слушателе); «Пф...» — кто-то не сдержал смешка». Если владелец решит, что такие случаи +принципиально неразрешимы офлайн, то потолок recall у правила смешения ниже 1.0 by construction, и +это надо записать в контракт правила, а не гнаться за ним правками. + +Полный список спорных с контекстом — в наборе на стенде: `labels/labels/*.jsonl`, фильтр +`label == "disputable"`. + +--- + +## §6. Чего набор НЕ покрывает + +Это главный раздел для того, кто будет пользоваться цифрами §4. Каждая цифра оттуда верна ТОЛЬКО +внутри своих границ. + +**1. Одна книга, одна пара, один жанр.** Всё — 蛊真人, zh→ru, сянься. Ни одного среза на другой паре +или книге. Любое утверждение вида «чекер имеет precision X» — это «на этой книге». + +**2. Четыре класса физически малы, и метрика на них хрупкая.** K1 = 15 items (4 уникальных вхождения +在 исходнике), K5b = 11, K5d = 5, K2 = 92. `precision = 1.000` на шести положительных K1 — это +«не ошибся шесть раз», а не «работает». Один контрпример уронит цифру на 0.14. Доверительных +интервалов я не считал сознательно: при N=6 они шире самой цифры. + +**3. Recall меряется против МОЕЙ сети, а не против истины.** Дефект, который не попал ни в одну из +моих сетей, невидим и для разметки, и для метрики. Где сеть заведомо дырявая: + - **K3**: сплошь просмотрен только hapax-слой (1 999 типов). Битая форма, встретившаяся дважды, + в набор не попала. Вторая независимая сеть (сосед по Левенштейну у частого слова, 117 попаданий) + не добавила ни одного нового дефекта — но это проверка, а не доказательство. + - **K4**: буквенных строк размечено 80 из 5 088. Прямой речи вообще без маркера я в этой выборке + не нашёл, но выборка — 1.6% слоя. + - **K6**: 260 пар из 1 257. + - **K2/K5a/K5b/K5c/K5d/K1**: сплошь, дырок нет. + +**4. Ветка K4a непроверяема на этом корпусе.** Ноль строк с дефисом/короткой чертой/ASCII-кавычкой в +начале на 6 863 строках. Её precision/recall не измерены НИКАК — ни хорошо, ни плохо. + +**5. Классов чекеров больше, чем шесть.** Не размечены и не измерены: ёфикатор, транслит-междометия, +DC6-регистр, эксцизия-покрытие, коллапс длины, весь санитайзер (преамбулы, markdown-заголовки, +CJK-утечки), хотя markdown-заголовки (29 строк) и CJK-утечки (11 строк) в наборе видны как +подклассы K4 и ждут своего пакета. + +**6. Черновики размечены, но боевыми гейтами не проверяются.** 38 из 40 дефектов латиницы и почти вся +утечка инъекционного блока банка (`⟦TM-BANK-v1⟧` с колонками `name`/`title`/`term`/`place` прямо в +тексте `verify2`) живут в ЧЕРНОВИКАХ. Строка «K2 детектор» в §4 меряет линейку, строка «боевой +охват» — то, что реально доезжает до вердикта. Это не одно и то же, и путать их нельзя. + +**7. Набор — не оракул качества перевода.** Он отвечает ровно на вопрос «сработал ли чекер там, где +человек видит дефект ЭТОГО класса». Он ничего не говорит о верности, гладкости, регистре и о том, +что перевод вообще хороший. + +**8. Метрики K5a/K5b/K5c/K1 — на уровне ЮНИТА.** Юнит с двумя вхождениями, где одно верно, а другое +нет, засчитывается как один положительный. Пер-вхожденческая разметка в наборе есть (`labels/*.jsonl`), +и по ней можно пересчитать иначе — но это будет ДРУГАЯ метрика, не сравнимая с этой. + +**9. Синтетики в наборе нет вообще.** Ни одной строки я не дописывал. Там, где класса физически мало, +в §3 стоит настоящее число, а не добитое до 200. + +**10. Приёмка воспроизводима, но зависит от стенда.** Набор и харнесс — вне git (текст книги). +`labels/README.md` описывает, как ре-ранить; ключевая ловушка при повторе — снимать детерминированный +заголовок с финала, иначе номер главы читается как «появившееся число». + +--- + +## Итог одной таблицей + +| линейка | вердикт по итогам первого честного замера | +|---|---| +| K1 DC1 时辰 | работает как описана: 6/6, ложных нет. Материала мало (15) | +| K5b DC2 | 1/1, ложных нет. Материала мало (11), 3 спорных упираются в вопрос о гиперболе | +| K2 латиница | ложных нет; recall 0.75 как детектор и 0.50 в боевом охвате; заглавные и гомоглифы вне класса | +| K3 битые формы | ложных нет; ловит 1 битую форму из 10 — один шаблон вместо класса | +| K4b смешение стилей | «8→0» подтверждено на мыслях: 99 из 100 ёлочных мыслей молча (1 ложняк). Но 41 реплика вслух из 46 не опознана | +| K4a неверный маркер | **не измерено:** на корпусе нет ни одного входа | +| K5a магнитуда 万 | ноль срабатываний на всём корпусе; предохранитель отсекает и идиомы, и все реальные магнитуды | +| K5c 成-процент | **инвертировано на реальном материале:** промолчал на единственном юните с 10×-ошибками, сработал на пяти с верными значениями | +| K5d дрейф чисел | 4 срабатывания, все безобидные; подлинного дрейфа в корпусе нет | +| K6 глоссарий | 1 подлинный промах против 14 ложных; на реально инъецированном подмножестве — 0 против 8 | + +**Заявление = команда.** Приёмка: ре-ранить чекеры против набора по `labels/README.md` и сверить +`metrics.json`. Ожидаемый результат — побайтно те же цифры: и корпус, и харнесс, и чекеры детерминированы.