diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 526ab87c..554b6013 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1,6 +1,6 @@ # Журнал прогресса -> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-07-25, пак-17 закрыт, право по ToS подписано, пак-18 принят — долгов контракта нет, D39.26–D39.31). **Источник истины по РЕШЕНИЯМ — `architecture/05-decisions-log.md` (D1–D39.50); этот файл — ЖУРНАЛ.** +> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-07-25, пак-17 закрыт, право по ToS подписано, пак-18 принят — долгов контракта нет, D39.26–D39.31). **Источник истины по РЕШЕНИЯМ — `architecture/05-decisions-log.md` (D1–D39.51); этот файл — ЖУРНАЛ.** > - **Фазы/курс:** Ф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 в её классах; вернуться при расширении классов и ненулевом остатке; **уточнение 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, вписать в контракт правила) · ~~место фикс-пака «чекеры» в очереди~~ **РЕШЕНО 26.07 (D39.40): это ПАК-21, а перед ним мини-прогон ~10 глав на полном бэкенде (после лендинга 20 и 19)**; ответы Р1–Р4 нужны к дизайну пака-21 · 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; **место РЕШЕНО (D39.40): ПАК-21, после мини-прогона на полном бэкенде; + переезд `translitInterjections` в данные (улов владельца)** · (2) **тест-пин джойна WHAT↔WHICH** (мутация оркестратора выжила — фикс-лист №1 следующего касания) · ~~(3) покрытие WHAT↔WHICH + флаговый майнинг-стоп~~ **ПАК-20 ЗАКРЫТ ЦЕЛИКОМ 26.07 (фаза 1 D39.41 · решения D39.42 · фаза 2 ПРИНЯТА И ЗАЛЕНДЕНА D39.45): терминолог + `--verify-bank` (дефолт=авто) + авто-провод с пометкой + точечная ре-редактура с $0-пере-пином + банкнота отдельным файлом; живьём на 10 главах, $0.0476, деньги сходятся тремя путями; заделы серии/импорта — контрактами.** Открытое по паку: `feed_cap` (рекомендация: малой дельтой) · жанровые метки словаря · подпись словаря после фазы B полигона · resnapshot стендовых книг с auto-строками; хвосты: `AttachKWIC` квадратичен · смета молчит о пере-покупке роли на подписи · S12 частичен · zh-worst-case в `bankTokenBudget` (утечка §0 признана) · gofmt `llm.go` (до-паковый) · **вариативность банкноты 37↔14 (n=2) → полигону в фазу B** · (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/` = постоянный измерительный стенд чекеров; ~~ПАКЕТ-7 (v2, ресёрч-программа)~~ **ЗАКРЫТ ЦЕЛИКОМ 26.07 (A: D39.43 · Z-решения: D39.44 · B+B′: D39.46; $0.45043 из коридора $2.60): ратифицировано «контексты — главный рычаг терминолога»; судья = только катастроф-экран с декоем; словарь инертен до расширения эмиссии на term; три процессных правила — в нормы промтов; ~~на владельце подписи Z-B1–B4~~ **АМЕНДИРОВАНО D39.47: жанровый словарь ОТМЕНЁН КАК КЛАСС (решение о переводе = подпись владельца на банк КНИГИ; Z-B1/B2/B6 сняты, Z-B4 сужен, Z-B3 остаётся — промпт уже в узкой форме); дельта размотки → бэкендерам, главный вопрос покрытия = расширение эмиссии на term + feed_cap (ждёт санкции)**; амендмент D39.42 п.1 (терминолог на полном банке = единицы долларов) и Q4→Р3 (сокращённая форма = поле записи, вход пака-21) — в силе; полигон-очередь ПУСТА, кандидаты: вариативность банкноты 37↔14 · ёфикатор/санитайзер-разметка · dialogue_dash на невиданном (оставшиеся кандидаты: ёфикатор/санитайзер-классы не размечены — §6.5 отчёта пакета-6; `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`). diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index a0477b91..7354f219 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1154,3 +1154,7 @@ API-529-долг закрыт: 8-осевой refute-by-default воркфлоу **Ратифицировано фактами:** (1) **расширение `emitRankCap`/фильтра типа НЕ строится**: 66 из 74 поверхностей банкноты лежат вне варианта C по ЧАСТОТЕ (82% ниже emitMinFreq на срезе — вне кандидатного алфавита), а на хвосте расширенной эмиссии роль ВЫДУМЫВАЕТ dst 77–82% стабильно (сентинел ⟦TM-NO-DST⟧ различает «переводимо», не «терм», и нестабилен даже там — размах 0.375); (2) **носитель покрытия — банкнота** (5/6 кандидатов, класс term с dst), но она невоспроизводима (Жаккар 0.077–0.40 между прогонами одних глав) и эмитирует 《咏梅》/咏梅 как разные строки — лечения, выдержавшие проверку: нормализация книжных кавычек + агрегация по прогонам; **частотного экрана НЕ существует** (§5.1: 少年 1149 против 光阴之河 15 — порога нет; полигон сам снял свою рекомендацию); (3) **дыра языка ответа**: ⟦TM-CANON⟧ — де-факто якорь ЦЕЛЕВОГО ЯЗЫКА; без него 22/40 английских строк в одном прогоне из трёх (8×120 тоже течёт), и конвейер их банкует (`wellFormedLemma` пропускает латиницу) — закрыть ДО любого расширения канала; (4) **kwic-дефолт 3×40 ДОСТАТОЧЕН** (ни одна точка сетки не отличима, 0×0 — лучшая; развилка «подача×контекст» неразличима), НО `kwic_width` в РУНАХ = утечка пары в общий слой (43–84 морфемы zh против обрубка фразы en) → пар-данные; (5) **蛊/转 подписаны и не доезжают ни одним каналом** (`SignificantLen=1`) — правка ДАННЫХ сида (`allow_short: true`); (6) **условие судьи-экрана (фолбэк D39.46) наступило**, но экран платный за кандидата — дизайн обязан посчитать, где ставить и что снимается бесплатно; (7) **холодный старт с пустым банком — не мерил никто**, и именно там цена любого утверждения о покрытии (кандидат — совместить с мини-прогоном D39.40); (8) §6: **en-детектора НЕ СУЩЕСТВУЕТ** (`hanRuns` — 0 эмиссии на латинице), ja с zh-таблицами активно неверен (0/10) — второй книге нужен второй ДЕТЕКТОР, эксперименты на Кристоффе преждевременны; прототип каналов — `mine_nonhan.py` пакета-7. **Напряжение с D39.46 «контексты — главный рычаг» названо, НЕ отменено:** три различия постановки (лёгкая выборка · якорь в боевой сборке · нет строки drafts:); пере-замер на трудной выборке пакета-7 с боевой сборкой — кандидат, до него kwic не трогать. **Дефект нарезки пакета-7** (фильтр по номеру 节 при перезапуске нумерации в томах): абсолютные recall фазы A занижены втрое (0.089→0.255 на непрерывном срезе), структурный вывод (term кратно слабейший) УСТОЯЛ. Приёмка: 8/8 CONFIRMED, ревью-шапка с нитами на отчёте `POLYGON_PREMEASURE_2026-07-26.md`; деньги $0.11313 из потолка $0.30. + +## D39.51 — Дизайн «дисциплина банкноты + дыра языка ответа» РАТИФИЦИРОВАН, стройка санкционирована (владелец: «идём», 26.07): языковой экран на ВЫХОДЕ + счётчик OffLanguage + фильтр свёртки банкноты + нормализация кавычек в свёртке (Q1) + агрегация из чекпойнтов (A1) + kwic_width в пар-данные (файл zh-ru НЕ шипуем) + doc-хвост. Судья ОТЛОЖЕН; мини-прогон D39.40 — В ХОЛОДНОЙ конфигурации; allow_short — на нём (26.07, оркестратор №8). ✅ + +**Отчёт:** `docs/archive/reports/PACK20_BANKNOTE_DESIGN_2026-07-26.md` (ревью-шапка). Принципиальные решения: (1) **гарантия языка — на выходе, не на входе** (предикат offLanguage по `*unicode.RangeTable` через конфиг гейта `target_script`, обязателен при enabled, вне снапшота, $0; направление отказа объявлено: отвергнутый законный латинизм дешевле англо-канона); (2) **кавычки — в свёртке (Q1), не в парсере/NormalizeSourceKey** (Q2/Q3 платят волной за косметику; Q1 $0 и ретроактивен; NormVersion не двигается — тест-страж); (3) **агрегация банкноты — производное из чекпойнтов (A1), без новых таблиц**; инвариант «прогон без новых черновиков даёт байт-идентичную карту» — пином; предложения отвергнутых попыток входят (решение: предложение = улика, не канон); (4) **судья-с-декоем НЕ строится** (≈$0.025/книга — цена не аргумент; его положительное решение = решение о переводе за владельца, против D39.47; популяция неизвестна до холодного старта; сначала P1); (5) **три расхождения сессии с записками оркестратора приняты** (allow_short = базовая версия = перепокупка книги → на холодный прогон; kwic-файл zh-ru не шипуем; судья отложен). **Замеры полигону:** пример формата в промпте (≈$0.009, критерий до прогона: 0 не-целевых строк ×3 против 22/40) · P1 consistency ($0: Σchunks-предложивших / chunks-содержащих; порог засчитывается при ≥80% термов и ≥60% мусора; арм-без-фактора = голая частота обязана провалиться; положительный исход = право на ПОРЯДОК, не на выброс строк) · приёмка предиката на живом сырье 147 вызовов (живо, подтверждено: ровно 27 строк §3.4 и ни одной сверх). **Мини-прогон D39.40 = холодная конфигурация** (пустой сид, банкнота+терминолог ON, --verify-bank, ОТДЕЛЬНАЯ БД) — пять ответов за ≤$0.23: банкнота без цензуры · совместный recall (замер 1 состоится) · язык при пустом якоре (счётчик OffLanguage как прибор) · побочки allow_short · второй сэмпл для агрегации. Приёмка стройки: мутации M-Я1/M-Я2 + регресс 16 живых строк + пин общности (латинская цель переворачивает вердикты) + пин инварианта агрегации + сырьё-приёмка. diff --git a/docs/archive/reports/PACK20_BANKNOTE_DESIGN_2026-07-26.md b/docs/archive/reports/PACK20_BANKNOTE_DESIGN_2026-07-26.md new file mode 100644 index 00000000..c716dc70 --- /dev/null +++ b/docs/archive/reports/PACK20_BANKNOTE_DESIGN_2026-07-26.md @@ -0,0 +1,576 @@ +# Пак-20, продолжение: ДИЗАЙН по замерам пакета-8 — дисциплина банкноты и дыра языка ответа + +**База:** D39.50 (пакет-8 принят, 8/8 CONFIRMED), D39.47/48, `POLYGON_PREMEASURE_2026-07-26.md`. +**Зона:** `backend/` (эта сессия — только ЧТЕНИЕ; ни одной строки продового кода не изменено). +**Статус:** фаза ДИЗАЙНА. Деньги сессии **$0** (ни одного платного вызова). Сессия НЕ коммитит. +**Дальше:** СТОП → ратификация владельца → стройка. + +> **Ревью-шапка (оркестратор №8, 26.07): ДИЗАЙН РАТИФИЦИРОВАН, D39.51 — стройка пп.1–7 §8 санкционирована.** +> Спот-проверка оркестратора: `AllowShort` в хеше строки банка (memory.go:368) и место эхо-гейта +> (terminology.go:882-885) — сошлись; четыре опоры сессии проверены ЕЮ исполнением, полная проверка — +> мутациями приёмки стройки. Все три расхождения с записками оркестратора ПРИНЯТЫ как правильные: +> `allow_short` = перепокупка книги (не «строка данных») → на холодный прогон; пар-файл kwic для zh-ru +> не шипуем (значение = фолбэк, LangpackVersion не трогаем); судью не строить — не из-за денег, а +> потому что его положительное решение отнимает подпись у владельца (принцип D39.47) + популяция +> неизвестна до холодного старта. Ответ на §10 п.6: сырьё 147 вызовов ЖИВО +> (скретчпад полигон-сессии, raw2/raw3/raw3b + raw_anchor побайтовая копия; верификатор приёмки D39.50 +> пересчитывал по нему деньги) — приёмка предиката §2.5 п.5 на настоящем сырье ОБЯЗАТЕЛЬНА. +> Дефолты по решениям §10 (вето владельца одной строкой): судья ОТЛОЖЕН до P1 + холодного старта · +> мини-прогон D39.40 идёт В ХОЛОДНОЙ конфигурации (отдельная БД — операционное условие §6 в силе) · +> `allow_short` для 蛊/转 — данными на нём же. Полигону — два замера (§8 пп.8–9, ≈$0.009 + $0). + +Посылка «расширить эмиссию майнера» закрыта замером отрицательно, и хорошо, что до стройки: §2 моей +дельты (`PACK20_DELTA_2026-07-26.md`) устарела целиком, кроме одного — оси «что банкуется без подписи +≠ что кладётся на подпись». Она пережила пакет-8 и стала в этом дизайне несущей. + +--- + +## §0 Эхо-блок (что я услышал, ДО работы) + +1. Не проектировать: подъём `emitRankCap`, снятие фильтра типа, частотный экран для банкноты, подъём + kwic-дефолтов. Всё четыре закрыты замером — механизмом, а не порогом. +2. Предмет: (1) дыра языка ответа — закрыть ДО любого расширения канала; (2) дисциплина банкноты + (кавычки + агрегация по прогонам; семантический отбор — судья или владелец, посчитать деньгами); + (3) `kwic_width` из Go-константы в пар-данные, значение НЕ менять; (4) `allow_short` — упомянуть; + (5) холодный старт — не мерить самому, предложить, как его снимет мини-прогон. +3. `NormalizeSourceKey` — ключевая нормализация; оси объявить явно. +4. Нормы D39.46/47: арм без фактора · сравнение на расходящихся позициях · декой · критик полноты на + фазу · право сказать «этого делать не надо». +5. Алгоритмы не подгонять под язык/книгу. Ревью допустимо, скоуп-крип — нет. +6. Отчёт → СТОП. Судья в прод-провод — только с отдельной санкцией. + +--- + +## §1 Синк-таблица: источник ↔ код ↔ вердикт + +Вердикт «подтверждаю исполнением» означает, что я выполнил проверку в этой сессии (временный тест, +удалён сразу после снятия чисел); «подтверждаю чтением» — что грунтовал по `file:line`, но не запускал. + +| # | Утверждение полигона | Адрес в коде | Вердикт | +|---|---|---|---| +| 1 | Роль отвечает по-английски, и конвейер это банкует (§3.4) | [terminology.go:842-892](backend/internal/terminology/terminology.go#L842-L892) `ParseReply`, [:576-588](backend/internal/terminology/terminology.go#L576-L588) `wellFormedLemma` | **Подтверждаю ИСПОЛНЕНИЕМ.** Боевой `ParseReply` на строках `修行→cultivation`, `元海→Primordial Sea`, `转→realm`, `是为→is`: **принято 5 из 5, bad_lines = 0**. Ни один счётчик не шевельнулся | +| 2 | Якорь ⟦TM-CANON⟧ — де-факто якорь целевого ЯЗЫКА, и он пуст на холодном старте | [terminologist.go:307-316](backend/internal/pipeline/terminologist.go#L307-L316), [terminology.go:714-765](backend/internal/terminology/terminology.go#L714-L765) `CanonFor` | **Подтверждаю чтением.** `CanonFor` берёт только APPROVED-строки; их ноль до первой подписи. Пустой якорь → `renderPairs` даёт `""` → сообщение не отправляется вовсе | +| 3 | Эхо-гейт не ловит английский | [terminology.go:885](backend/internal/terminology/terminology.go#L885) | **Подтверждаю чтением.** Проверка `normalize(dst) == key` ловит эхо ИСХОДНИКА; английское слово исходником не является | +| 4 | `《咏梅》` и `咏梅` — две разные строки карты подписи | [norm.go:136-156](backend/internal/text/norm.go#L136-L156), [banknote.go:288](backend/internal/pipeline/banknote.go#L288) | **Подтверждаю ИСПОЛНЕНИЕМ.** `key(《咏梅》)="《咏梅》"` против `key(咏梅)="咏梅"`, не равны. NFKC книжные кавычки не снимает — они не совместимостные | +| 5 | `蛊`/`转` подписаны и не доезжают ни одним каналом | [memory.go:276](backend/internal/membank/memory.go#L276), [norm.go:252-263](backend/internal/text/norm.go#L252-L263), [miner_emit.go:27,33](backend/internal/miner/miner_emit.go#L27) | **Подтверждаю ИСПОЛНЕНИЕМ.** `SignificantLen(蛊)=1`, `SignificantLen(转)=1`, `SignificantLen(蛊师)=2` — ровно порог `minKeyLenHan=2` | +| 6 | Банкнота — носитель покрытия (5/6 кандидатов) | [mining.go:87-120](backend/internal/pipeline/mining.go#L87-L120), [terminology.go:128-214](backend/internal/terminology/terminology.go#L128-L214) `Merge` | **Подтверждаю чтением и УТОЧНЯЮ:** в живом слое это ещё и означает, что ~84% кандидатов несут строку `drafts:` — то есть целевой язык уже стоит в запросе. Замер §3 его снял («черновых вариантов нет») и потому меряет риск языка в его ХУДШЕЙ точке. Дыру это не отменяет (см. §2.0) | +| 7 | Частотного экрана для банкноты не существует (§5.1) | [miner_emit.go:27](backend/internal/miner/miner_emit.go#L27) `emitMinFreq` | **Подтверждаю и присоединяюсь.** Порога, разделяющего `少年` (1149) и `光阴之河` (15), нет. Своё предложение частотного порога полигон снял сам — это образцовая работа, и повторять её я не буду | +| 8 | kwic-дефолт 3×40 достаточен | [terminologist.go:57-61](backend/internal/pipeline/terminologist.go#L57-L61) | **Принимаю вердикт, оспариваю его перенос.** Достаточность измерена на ЛЁГКОЙ выборке без строки `drafts:` (§3.3 сам называет три различия). Практический вывод — «поднимать нечем» — от этого не страдает, и я не предлагаю поднимать | +| 9 | `kwic_width` в рунах — утечка пары в общий слой (§6.3) | [terminology.go:331-346](backend/internal/terminology/terminology.go#L331-L346) `window` | **Подтверждаю чтением.** Окно режется в рунах, константа одна на все пары | +| 10 | Эмиссия банкноты — лотерея прогона (Жаккар 0.077–0.40) | [glossary.go:258-299](backend/internal/store/glossary.go#L258-L299) (PK `book_id,chapter,chunk_idx`), [banknote.go:330-379](backend/internal/pipeline/banknote.go#L330-L379) | **Подтверждаю чтением и УТОЧНЯЮ механизм:** внутри ОДНОЙ базы повтор невозможен — чекпойнт реиграет тот же текст, и `bankProposalsJSON` пересчитывается из него ([stagerun.go:415](backend/internal/pipeline/stagerun.go#L415)). Разъезд возникает только когда черновики РЕАЛЬНО перекупаются; тогда `UPSERT` по PK **затирает** прошлые предложения — объединение теряется | +| 11 | Роль выдумывает dst 77–82% на расширенном хвосте | — | **Принимаю; предмета для кода нет** (расширение не строится) | +| 12 | Условие фолбэка «судья-с-декоем» наступило | — | **Принимаю.** Считаю деньгами в §3.4 | + +**Побочная находка ревью (не скоуп-крип, а мой собственный хвост D39.47):** в +[pipeline.go:255-261](backend/internal/config/pipeline.go#L255-L261) doc-комментарий `TerminologyGate` +всё ещё обещает роли «its genre glossary». Механизма нет с D39.47 — осталась строка документации. +Правка на одну строку, кладу в стройку этого пакета, отдельного решения не прошу. + +--- + +## §2 Дыра языка ответа (главный предмет) + +### §2.0 Что именно сломано — точная формулировка + +Не «модель иногда отвечает по-английски». Сломано то, что **у конвейера нет ни одного места, где +проверяется, что ответ роли написан на целевом языке**, и все три существующих стража пропускают +латиницу по своим законным причинам: + +- `wellFormedLemma` пропускает — латиница легитимна для латинских имён; +- эхо-гейт молчит — ответ не равен исходнику; +- `CanonConflicts` молчит — конфликтовать не с чем, якорь пуст. + +Дальше строка едет по штатному маршруту: `ParseReply` → `attachConsolidatedDst` +([terminologist.go:384-396](backend/internal/pipeline/terminologist.go#L384-L396)) → `status: draft` → +авто-банк → инъекция редактора с ⟨проверить⟩. То есть **`修行 → cultivation` становится рабочим каноном +книги**, и единственное, что стоит между ним и текстом, — глаз владельца на стопе, которого в авто-режиме +нет по определению. + +Важное уточнение к §3.4 полигона, в обе стороны: + +- **риск в бою МЕНЬШЕ измеренного:** в живом батче ~84% кандидатов (65 из 78 на срезе §1.3) несут строку + `drafts:` с русскими вариантами, а замер их снял ради чистоты фактора. Целевой язык в запросе обычно + присутствует; +- **но точка отказа ровно та, где этой страховки нет:** холодный старт (якорь пуст) + кандидат от майнера + без черновых вариантов (11 из 78) = батч, в котором целевого языка нет НИГДЕ, кроме промпта. Промпт + написан по-русски целиком — и §3.4 показывает, что этого не хватило. + +Отсюда конструктивное требование: гарантия языка **не должна зависеть от содержимого запроса**. Всё, что +живёт во входе (якорь, черновики, примеры в промпте), — это снижение вероятности; гарантия может стоять +только на ВЫХОДЕ. + +### §2.1 Вариант А (рекомендуемый): детерминированный экран целевого письма на выходе + +**Предикат.** Строка ответа не является переводом, если в ней есть буквы и **ни одна** из них не +принадлежит письму цели. Числа, пунктуация, дефисы — не буквы и не участвуют. + +``` +offLanguage(dst, script) := (letters(dst) > 0) && (hits(dst, script) == 0) +``` + +**Общность.** Письмо приезжает в `terminology` ЗНАЧЕНИЕМ (`*unicode.RangeTable`), как уже приезжает +`Conformance func(dst, typ) float64` ([terminology.go:351-361](backend/internal/terminology/terminology.go#L351-L361)). +Ни имени языка, ни имени письма в пакете нет. Таблица резолвится по ИМЕНИ из `unicode.Scripts` — +стандартная таблица Go, покрывающая любое письмо. Ревью-вопрос «заработает ли на паре, которой в репо +ещё нет, без правки Go?» — **да**: новая пара объявляет своё письмо строкой конфига. + +**Проверено исполнением на реальных строках отчёта** (не на выдуманных фикстурах): + +| Множество | Строки | Результат | +|---|---|---| +| Английские ответы §3.4/§2.6 | `cultivation` · `Primordial Sea` · `Rank 1` · `Grade C` · `talent` · `Wine Bug` · `realm` · `Qingmao Mountain` · `Gu Yue` · `is` | **10 из 10 помечены** | +| Подписанные владельцем и живые русские | `культивация` · `море истинной ци` · `гу-мастер` · `Фан Юань` · `гу` · `талант` · `винный червь` · `старейшина` · `Гуюэ` · `апертура` · `третья гу` · `гу Силы` · `Река времени` · `9` · `«Ода сливе»` · `Фан Юань` | **16 из 16 прошли** | +| Тот же предикат при латинской цели | `культивация` / `cultivation` | роли меняются местами, Go не трогается | + +Ложных срабатываний нет ни одного, включая пограничные: `гу` (2 буквы), `9` (букв нет — не трогаем), +кавычки и двойной пробел. + +**Где стоит.** Ровно там, где уже стоит эхо-проверка — [terminology.go:885](backend/internal/terminology/terminology.go#L885), +и по той же логике: «ответ, который есть исходник, — не перевод» ↔ «ответ, который написан не на языке +цели, — не перевод». Строка считается плохой (`bad`), термин остаётся неконсолидированным +(`status: auto`, инертен). Ни одна выдумка в банк не попадает. + +**Направление отказа названо явно.** Предикат может отвергнуть ЗАКОННЫЙ латинский рендеринг (пара, где +владелец хочет сохранить «Wi-Fi» латиницей). Цена ошибки — потерянное предложение, которое владелец +подпишет руками; цена противоположной ошибки — англоязычная строка в каноне книги. Ошибаться в эту +сторону — решение, а не недосмотр. + +**Наблюдаемость (обязательна, иначе экран сам становится тихой деградацией).** Отдельный счётчик +`OffLanguage` в `terminologyResult` ([terminologist.go:65-81](backend/internal/pipeline/terminologist.go#L65-L81)) +— НЕ слияние с `BadLines`: «модель ответила не на том языке» и «модель сломала формат» требуют разных +действий. Батч, где доля не-целевых строк ≥ ½, логируется `Warn` с именами строк: это ровно сигнатура +срыва §3.4 (22 из 40), и она должна быть видна оператору в тот же момент, а не в отчёте через сутки. + +**Тот же предикат — на втором входе.** Черновая банкнота тоже несёт dst в банк +([banknote.go:330-379](backend/internal/pipeline/banknote.go#L330-L379)), и `是为 → is` в §2.6 показывает, +что канал не иммунен. Фильтр ставится в СВЁРТКЕ (`bankObservedByKey`) и на записи +(`bankProposalsJSON`), а не в парсере — почему именно так, см. оси в §3.1. + +**Чего экран НЕ делает** (границы, чтобы его не переоценили): он не ловит смешанную строку +(`cultivation (культивация)` пройдёт — кириллица есть), не ловит правильный язык с неправильным +смыслом, и не улучшает качество ни на одном термине. Он закрывает ровно один класс: язык. + +### §2.2 Вариант Б: строгая форма предиката (доля, а не наличие) + +`offLanguage := hits/letters < 0.5`. Ловит `cultivation (культивация)` и пояснения в скобках, которые +промпт запрещает, а `wellFormedLemma` пропускает (скобки не в списке `[]{}<>|`). **Не рекомендую в этом +паке:** это уже не «язык», а «формат ответа», отдельный класс с собственной ценой ложных срабатываний +(законные скобки в титуле). Называю как открытую опцию, чтобы не подавать её потом как новую находку. + +### §2.3 Вариант В (вход, дополняющий, НЕ заменяющий): пример формата в промпте + +§3.4 показывает не «модель не знает языка», а «модель повторяет письмо примеров, которые видит». +Тогда самое дешёвое воздействие на вход — не якорь, а **строка примера формата в промпте роли**, +написанная на целевом письме. Это ДАННЫЕ (`prompts/zh-ru/terminologist.md`), Go не трогается, снапшот +не двигается, цена — перепокупка только батчей терминолога. + +**Но это гипотеза, а не замер, и я не предлагаю её строить вслепую.** Она проверяется на уже +построенном харнессе полигона одним армом: их же «3×40 без якоря» ×3 повтора, плюс строка примера. +Критерий назвать ДО прогона (предлагаю: 0 не-целевых строк в 3 прогонах против 22/40 в контрольном). +Цена по их же таблице §4 — **≈$0.009**. + +Порядок важен: вариант А строится независимо от исхода В. Если В сработает, А почти никогда не будет +срабатывать — и это правильное состояние: страховка, которая молчит. + +### §2.4 Деньги и оси варианта А + +| | | +|---|---| +| **Деньги стройки** | $0 (детерминированный предикат, ни одного вызова) | +| **Деньги в проде** | $0 навсегда | +| **Снапшот движка** | НЕ двигается: предикат читает ОТВЕТ, байты запроса не меняются; `gates.terminology` в снапшот не фолдится ([pipeline.go:263-268](backend/internal/config/pipeline.go#L263-L268)) | +| **Батчи терминолога** | НЕ перекупаются (адрес батча — байты запроса) | +| **Книга без англоязычных строк в банке** | путь байт-в-байт прежний, не перебилливается | +| **Книга, у которой такая строка в авто-банке ЕСТЬ** | строка исчезает → обогащённая версия банка сдвигается → **редакторская волна перебилливается ОДИН раз**. Это штатный путь «банк изменился», а не `--resnapshot` движка | +| **Конфиг** | новый ключ `gates.terminology.target_script` (имя письма). Обязателен при `enabled: true`, проверяется на ЗАГРУЗКЕ по идиоме [pipeline.go:986-1003](backend/internal/config/pipeline.go#L986-L1003) — гейт, который не может отработать, отвергается до денег | + +**Почему конфиг, а не пар-данные langpack.** Файл в `configs/langpacks/<пара>/` фолдится в +`Pack.Version()` → `LangpackVersion` → **обе волны** ([snapshot.go:428](backend/internal/pipeline/snapshot.go#L428)) +→ полная перепокупка книги. Платить перепокупкой черновой волны за объявление письма — несоразмерно. +`gates.terminology` не фолдится вообще, поэтому там объявление стоит $0. Общность при этом сохранена: +значение — данные, не Go. + +**Альтернатива, которую я рассмотрел и отверг:** выводить письмо цели из уже загруженных пар-данных +(`palladius.txt` целиком на кириллице). Соблазнительно — ноль новых ключей, — но это скрытая связь: +файл написан для транскрипции, и правка в нём молча меняла бы поведение языкового экрана. Явное +объявление дороже на одну строку конфига и честнее. + +### §2.5 Приёмка (как это доказывается, а не заявляется) + +1. **Мутация M-Я1:** снять предикат → тест на реальных строках §3.4 обязан покраснеть. +2. **Мутация M-Я2:** ослабить до «есть хоть одна буква цели ИЛИ строка короче N» → красное на `is`. +3. **Регресс ложных срабатываний:** 16 живых русских строк (включая подписанные владельцем) — зелёные. +4. **Пин общности:** тот же предикат с латинской целью меняет вердикты местами — доказывает, что в Go + не осело знание о паре. +5. **$0-верификация на настоящем сырье:** полигон сохранил все 147 вызовов пакета-8. Если сырьё живо — + прогнать предикат по ним целиком: он обязан пометить ровно 27 известных строк §3.4 и ни одной сверх. + Это лучшая приёмка, чем любая фикстура, и стоит $0. **Запрос к полигону:** доступно ли сырьё. + +--- + +## §3 Дисциплина банкноты + +### §3.0 Что здесь на самом деле лечится + +Банкнота даёт 5/6 кандидатов и умеет класс `term` с dst — и она же невоспроизводима. Три дефекта +разной природы, и их нельзя лечить одним средством: + +| Дефект | Природа | Лечение | Цена | +|---|---|---|---| +| `《咏梅》` ≠ `咏梅` | нормализация | детерминированное, $0 | §3.1 | +| объединение предложений теряется при перекупке черновиков | долговечность | детерминированное, $0 | §3.2 | +| 48% предложений — разовые фразы («звук дождя») | СЕМАНТИКА | бесплатного нет — замер, потом судья или владелец | §3.3–3.4 | + +**Почему мусор в банке вреден — назову прямо, потому что от этого зависит, сколько за отбор не жалко +платить.** Строка `雨声 → «звук дождя»` со статусом `draft` попадает в инъекцию редактора с пометкой +⟨проверить⟩. Она (а) ест бюджет инъекции и вытесняет настоящие термы (`n_evicted` это уже считает), +(б) засоряет карту подписи владельца и (в) — главное — **предписывает редактору переводить обычное +слово ОДНИМ фиксированным способом**. Последнее прямо противоречит цели проекта: механизм, созданный +против расхождения терминов, применённый к не-термину, производит ровно ту деревянность, ради победы +над которой всё строится. + +### §3.1 Кавычки: нормализация обрамляющей парной пунктуации + +**Правило (пар-слепое по построению).** Снять с ключа обрамление, если ПЕРВАЯ руна — открывающая +(`unicode.Ps` ∪ `unicode.Pi` ∪ ASCII `"` `'`), а ПОСЛЕДНЯЯ — закрывающая (`unicode.Pe` ∪ `unicode.Pf` ∪ +те же ASCII); повторять, пока снимается; остановиться, если остаток пуст. Требование парности не даёт +покалечить `O'Brien` или строку, у которой кавычка только с одной стороны. Работает для `《》`, `「」`, +`“”`, `«»`, `""` — то есть для пар, которых в репо ещё нет, без правки Go. + +**Где стоит — и это главная ось.** + +| Место | Что чинит | Цена | +|---|---|---| +| **(Q1) свёртка `bankObservedByKey` + запись `bankProposalsJSON`** ← **рекомендую** | ключи сходятся, 4 строки карты подписи становятся 2, ретроактивно для уже оплаченных прогонов | **$0.** `retrieval_state` не wire-load-bearing ([migrate.go:316-327](backend/internal/store/migrate.go#L316-L327)); снапшот не двигается | +| (Q2) парсер `parseBanknote` | то же | `bankParserVersion` фолдится ([snapshot.go:113-130](backend/internal/pipeline/snapshot.go#L113-L130)) → `--resnapshot` → **перепокупка всей черновой волны** каждой книги с включённым каналом | +| (Q3) `text.NormalizeSourceKey` | то же + совпадение с ключами банка памяти | `NormVersion` → `memoryVersion` → **обе волны**; плюс смена семантики матчинга для всей памяти | + +Q2 и Q3 платят волной за косметику. Q1 даёт тот же результат бесплатно и вдобавок лечит УЖЕ записанные +строки, потому что свёртка перечитывает сохранённый JSON. + +**Дом функции:** `internal/text` рядом с прочими чистыми предикатами, с явным комментарием, что она +**не входит** в нормализационный артефакт и `NormVersion()` не двигает, + тест-страж на неизменность +`NormVersion()`. (Альтернатива — `internal/terminology`; выбрал `text`, потому что предикат нужен обоим +потребителям и не содержит терминологической логики.) + +**Измеренный эффект:** Жаккар между двумя прогонами одних глав 0.077 → 0.400 (§1.4), минус 3 дубля из +67 строк карты подписи (4.5%). Честно: **это не лечение precision, это лечение тождества.** + +### §3.2 Агрегация по прогонам: объединение вместо затирания + +**Что ломается сегодня.** `retrieval_state` имеет PK `(book_id, chapter, chunk_idx)` и UPSERT +([glossary.go:258-299](backend/internal/store/glossary.go#L258-L299)). Пока черновики резюмятся из +чекпойнтов — предложения воспроизводятся байт-в-байт. Как только черновик РЕАЛЬНО перекуплен (снапшот +сдвинулся), новая строка затирает старую, и предложения прошлого сэмпла исчезают навсегда, хотя +чекпойнт с их текстом лежит в базе. + +**Вариант A1 (рекомендуемый): объединение выводится из ЧЕКПОЙНТОВ, нового долговечного состояния нет.** +Свёртка читает не текущие `retrieval_state`, а все чекпойнты книги переводческой роли, и разбирает из +них блоки ⟦TM-BANK-v1⟧ тем же кодом, которым это уже делается на резюме +([stagerun.go:415](backend/internal/pipeline/stagerun.go#L415)). Нужен один новый store-запрос +(`checkpoints JOIN jobs ON job_id WHERE book_id=? AND role=?`), с исключением производных +(`finish_reason='banknote_export'` — там блок уже срезан) и с тем же гейтом `finish=="stop"`. + +- **Плюс:** ноль новых таблиц и миграций; свойство «пересчитывается каждый прогон, самолечится» + сохранено (это норма этого кода: производное лучше хранимого); покрытие **монотонно** — поверхность, + однажды предложенная, больше не теряется. +- **Минус, называю прямо:** в объединение войдут и предложения ОТВЕРГНУТЫХ попыток (эхо, обрыв). Считаю + это приемлемым и объявляю решением: предложение — это улика, а не канон; владелец всё равно подписывает. + Альтернатива (только победившие попытки) требует читать `chunk_status.final_hash`, который сам + перезаписывается — то есть лечит симптом тем же механизмом, который сломан. + +**Вариант A2:** отдельная таблица `banknote_proposal` (append-only). Отвергаю: долговечное состояние, +не выводимое из чекпойнтов, миграция, и первый же баг записи становится неисправимым — против дисциплины +всего этого хранилища. + +**Обязательство, которое я обязан доказать тестом, а не заявить.** [mining.go:108-120](backend/internal/pipeline/mining.go#L108-L120) +прямо предупреждает: если дельта отличается между прогоном 1 и прогоном 2, сдвигается редакторская +волна и книга перебилливается ни за что. Объединение это ужесточает. Инвариант: **прогон, который не +купил ни одного нового черновика, обязан дать байт-идентичную карту подписи.** Он держится по +построению (множество чекпойнтов не изменилось → объединение не изменилось), но именно поэтому его +нужно запинить тестом, а не оставить рассуждением. + +**Что агрегация НЕ даёт — и это важно для ожиданий.** Новых поверхностей она не приносит, пока никто не +купил второй сэмпл черновика. Второй сэмпл — это вторая черновая волна, самая дорогая часть конвейера; +рекомендовать её ради покрытия я не буду. Агрегация покупает **немонотонную потерю → монотонность**, и +только её. Единственный бесплатный второй сэмпл, который у нас будет естественным образом, — мини-прогон +холодного старта (§6). + +**Оси:** объединение может ДОБАВИТЬ строк → авто-банк вырастет → обогащённая версия банка сдвинется → +редакторская волна перебиллится один раз, и только у книги, у которой черновики покупались более одного +раза. У книги с одним сэмплом — байт-в-байт прежнее поведение. + +### §3.3 Семантический отбор: сначала $0-замер, и он может закрыть вопрос + +Прежде чем предлагать платный экран, обязан назвать бесплатный сигнал, который никто не мерил, — +и мерить его я предлагаю ДО стройки, потому что если он работает, платить не надо вовсе. + +**Сигнал.** Частота в тексте отвергнута замером. Но в свёртке уже лежит другое число: `Chunks` — в +скольких ЧАНКАХ переводчик независимо предложил эту поверхность +([banknote.go:351-356](backend/internal/pipeline/banknote.go#L351-L356)). Это не частота в тексте, а +**повторяемость решения**: сколько раз независимый чтец, глядя на разные куски, счёл строку достойной +объявления термином. Ставлю гипотезу на отношение + +``` +consistency := Σ chunks(предложившие поверхность) / (число чанков, где поверхность ВСТРЕЧАЕТСЯ) +``` + +`少年` встречается в множестве чанков и предложен один раз → отношение близко к нулю. `光阴之河` +встречается в двух и предложен в одном → 0.5. Это ортогонально частоте — то есть не повторение +опровергнутого порога. + +**Замер P1 ($0, полигон, из уже сохранённых артефактов).** На 74 размеченных поверхностях посчитать +`consistency` и проверить, разделяет ли она «настоящий терм книги» и «обычное слово». Критерий назвать +ДО счёта (предлагаю: разделение засчитывается, только если существует порог, оставляющий ≥80% настоящих +термов и убирающий ≥60% мусора; иначе — «не разделяет»). Арм без фактора обязателен: та же проверка для +голой частоты — она обязана провалиться (это уже известно из §5.1 и служит калибровкой методики). + +**Заранее говорю, чего этот замер не может.** Разметка «настоящий/мусор» — один разметчик и один вкус; +на границе (`家主` «глава клана» против `中年` «средний возраст») она сама шатается. Поэтому положительный +исход P1 даёт право строить БЕСПЛАТНЫЙ ранжирующий сигнал (сортировка карты подписи, порядок подачи), +но **не право автоматически выбрасывать строки**. Выбрасывание — это решение о содержимом банка книги, +и по духу D39.47 оно принадлежит подписи владельца, а не порогу в Go. + +### §3.4 Судья-с-декоем: где ставить и сколько стоит (расчёт, а не оценка) + +Условие фолбэка D39.46 наступило. Считаю деньгами. + +**Популяция.** 67 поверхностей на 10 главах → ~6.7 на главу. Для книги в 100 глав — **≈670** +(линейная экстраполяция, то есть ВЕРХНЯЯ граница: словарь книги насыщается, и доля новых поверхностей к +концу падает). + +**Цена одного кандидата.** Улика судьи — та же, что у терминолога: исходник + контексты + предложенный +dst. Мой собственный замер на боевой сборке: **223 токена на кандидата** при kwic 3×40. Выход вердикта +≈10 токенов. Цены `deepseek-v4-flash` из [models.yaml](backend/configs/models.yaml): $0.14/$0.28 за 1M. + +| Статья | Токенов | $ | +|---|---|---| +| Вход 670 × 223 | 149 410 | 0.0209 | +| Выход 670 × 10 | 6 700 | 0.0019 | +| +10% строк-декоев (калибровка, не удвоение) | | 0.0023 | +| **Один проход, книга 100 глав** | | **≈$0.025** | +| Три повтора (если понадобится устойчивость) | | ≈$0.075 | + +С кэшем (в пакете-8 75% входа пришло из кэша) реальная цифра ниже. Против цели ~$0.85/ранобэ — **≈3%**. + +**Вывод по деньгам, который я обязан сказать честно:** экран дёшев, и цена — НЕ аргумент против него. +Но и экономии он не даёт: терминолог на тех же 670 кандидатах стоит примерно столько же, так что +«отсечём мусор, чтобы сэкономить на роли» — самообман (экономия ≈$0.011). Оправдание у экрана одно — +качество банка (§3.0), и решать его судьбу надо в этих терминах. + +**Где ставить — три позиции.** + +| Позиция | Что защищает | Оценка | +|---|---|---| +| **J1: перед терминологом**, на banknote-only кандидатах | И авто-банк, И карту подписи, И вход роли — одним экраном выше по течению | **предпочтительная**, если экран вообще ставится | +| J2: после консолидации | только банк; роль уже потратилась | хуже J1 без выигрыша | +| J3: только на карте подписи владельца | лист подписи; авто-банк остаётся замусоренным | не закрывает §3.0(в) — редактор всё равно получает мусор | + +**И тем не менее — рекомендация: сейчас НЕ строить.** Три причины, по убыванию: +(1) $0-замер P1 может снять предмет целиком; (2) новый ПЛАТНЫЙ вызов в прод-проводе требует отдельной +санкции по этой же записке; (3) главная неизмеренная цифра — холодный старт (§6) — меняет саму +популяцию, которую судья бы фильтровал: неизвестно даже, 670 их или 2000. Ставить фильтр на популяцию +неизвестного размера — это проектировать по догадке ровно там, где пакет-8 только что показал цену +догадки. + +--- + +## §4 `kwic_width` → пар-данные (значение не меняется, меняется место жительства) + +**Дефект (§6.3):** 40 рун = 43–84 морфемы на zh (две реплики диалога) и обрубок фразы посреди +предложения на en. Одна константа означает разное — классическая утечка пары в общий слой. + +**Вариант A (рекомендуемый): необязательный пар-файл + инженерный фолбэк.** +`configs/langpacks/<пара>/terminology.txt` с парами `ключ значение` (`kwic_width 40`, при нужде +`kwic_per_term 3`), читается идиомой `readOptional` — **ровно как `heading.txt` и `dc-checkers.txt`** +([langpack.go:196-225](backend/internal/lang/langpack.go#L196-L225)): отсутствует → фича инертна и +`Version()` побайтно стабилен; присутствует → байты фолдятся, правка = громкий `--resnapshot`. +Приоритет резолвинга в одном месте (`terminologyOpts`, +[terminologist.go:99-112](backend/internal/pipeline/terminologist.go#L99-L112)): **явный конфиг книги → +пар-данные → инженерный фолбэк**. + +**Для zh-ru файл НЕ шипуем.** Измеренное значение совпадает с фолбэком, значит файл не купил бы ничего, +а `Pack.Version()` сдвинулся бы → `LangpackVersion` → **обе волны** → полная перепокупка книги. Платить +перепокупкой за переезд константы, которая не меняется, нельзя. Механизм при этом построен: пара en-ru +шипует свой файл со своим значением, и на ней ничего перекупать не надо — там ещё ничего не куплено. + +**Вариант Б: мерить окно не в рунах, а в предложениях источника** (`sentence-terminator.txt` в паке +уже есть, [langpack.go:139-151](backend/internal/lang/langpack.go#L139-L151)). Единица становится +пар-осмысленной по построению. **Не рекомендую сейчас:** это меняет БАЙТЫ контекстов → перекупку батчей +терминолога, а сетка §3.1 показала, что ни одна форма подачи не отличима от другой. Менять то, что +измеренно не влияет, — трата без гипотезы. Называю как опцию на случай, если пере-замер на трудной +выборке (§7) покажет, что контексты всё-таки решают. + +**Оси варианта A:** zh-ru — ничего не двигается, ноль перепокупок. Новая пара с файлом — её собственные +батчи терминолога, волн нет. Go-фолбэк остаётся, но перестаёт быть единственным источником истины, и +ревью-вопрос «заработает ли на паре, которой нет в репо» получает ответ «да, дропом файла». + +--- + +## §5 `allow_short` для `蛊`/`转` — данные, но НЕ бесплатные + +Механизм подтверждён исполнением: `SignificantLen(蛊)=1` при пороге 2, обход — `allow_short: true` в +строке сида, Go не трогается ([memory.go:276](backend/internal/membank/memory.go#L276)). Пока согласен +с полигоном. Дальше — три вещи, которых в §1.5 нет, и они меняют вывод «просто добавь строку». + +1. **Это перепокупка ВСЕЙ книги.** `AllowShort` фолдится в хеш строки банка + ([memory.go:368](backend/internal/membank/memory.go#L368)), а `蛊` — строка с `source: seed`, то есть + входит в БАЗОВУЮ версию банка ([snapshot.go:264-271](backend/internal/pipeline/snapshot.go#L264-L271)). + Базовая версия — это снапшот ЧЕРНОВОЙ волны. Правка данных, но цена — заново купленная книга. +2. **Ключ из одного иероглифа сидит внутри своих же составных.** `蛊` — подстрока `蛊师`, `蛊虫`, + `力量蛊`. Он начнёт срабатывать в каждом таком чанке, а разрешение вложенности уйдёт на + trust-gate/суппрессор (`n_trust_gated_suppress`) — механизм есть, но нагрузка на него станет + систематической, а не редкой. +3. **Пост-чек становится обязательством на почти каждый чанк.** 188 вхождений на 10 главах: E1 начнёт + требовать «гу» в выходе почти везде, и часть требований будет ложной — «гу» законно живёт внутри + «гу-мастера», а совпадение считается по нормализованной целевой форме. + +**Рекомендация:** строку сида добавить — но **на холодном мини-прогоне** (§6), где книга покупается +заново по другой причине и цена пункта 1 равна нулю, а пункты 2–3 сразу измеряются готовыми счётчиками +(`n_evicted`, `n_trust_gated_suppress`, `n_postcheck_miss`). Отдельного «просто добавим строку» я не +рекомендую: это выглядит как правка данных, а стоит как волна. + +--- + +## §6 Холодный старт: как его снимает мини-прогон (предложение, не исполнение) + +**Почему это несущая цифра.** Замер 1 не состоялся именно потому, что 49 из 51 термов сида были +инъектированы, а промпт переводчика просит «новые, которых нет в глоссарии». Значит **всё, что мы знаем +о банкноте, измерено на канале, которому заткнули рот**. Сколько она предлагает, когда её не глушит +инъекция, не знает никто, — а от этого зависит и размер популяции для §3.4, и оценка покрытия, и веса +§C2-3. + +**Предложение: мини-прогон D39.40 исполняется в холодной конфигурации.** Не отдельный замер — тот же +прогон, только с пустым банком. + +- **Что меняется:** книга стенда конфигурируется без сида (`seed_glossary` пуст) — правка ДАННЫХ; канал + банкноты ON, терминолог ON, `--verify-bank` для полного стоп-стола. +- **Почему это не искусственно, а НАОБОРОТ:** новая книга в проде приходит именно так — без единой + подписанной строки. Холодный прогон репрезентативнее того, что мы гоняли до сих пор. +- **Цена:** одна черновая волна на 10 главах. Мини-прогон 26.07 стоил **$0.23**; пустой банк убирает + инъекцию (входные токены падают), так что это верхняя граница. + +**Что он закрывает за одни деньги — пять вопросов сразу:** + +| Вопрос | Чем измеряется | Кем ждался | +|---|---|---| +| Сколько предлагает банкнота без цензуры инъекцией | число поверхностей, `n_banknote_lines` | §1.7, D39.50 п.7 | +| Совместный recall майнер ∪ банкнота против подписанного сида | сид не инъектирован → знаменатель чист, замер 1 состоится | §1.2 (не состоялся) | +| Течёт ли язык ответа вживую при ПУСТОМ якоре | счётчик `OffLanguage` из §2.1 — сам по себе измерительный прибор, $0 | §3.4 | +| Побочки `allow_short` на `蛊`/`转` | `n_evicted`, `n_trust_gated_suppress`, `n_postcheck_miss` | §5 | +| Второй сэмпл черновика для агрегации (§3.2) | объединение с существующим прогоном тех же глав | §1.4 | + +**Условие, которое делает эти цифры сравнимыми:** прогон должен идти в ОТДЕЛЬНОЙ базе, а не поверх +существующей (иначе чекпойнты реиграют старые черновики и «холодного» ничего не будет). Это операционная +деталь, но без неё замер молча превратится в резюм. + +--- + +## §7 Чего я НЕ проектирую и почему (границы) + +1. **Расширение эмиссии** — закрыто D39.50. Ни `emitRankCap`, ни фильтр типа, ни `feed_cap` в этом + дизайне не трогаются. +2. **Частотный экран банкноты** — опровергнут §5.1, повторять не буду. +3. **Подъём kwic-дефолтов** — оснований нет (§3.2 полигона); переезд места жительства ≠ смена значения. +4. **Судья в прод-проводе** — посчитан (§3.4), но не проектируется до отдельной санкции и до P1. +5. **Пере-замер «контексты — главный рычаг» на трудной выборке** — напряжение D39.46 ↔ пакет-8 названо + полигоном честно; это работа полигона, а не бэкенда, и до неё kwic трогать нечем в обе стороны. +6. **Второй детектор для латиницы (§6)** — отдельный пак, отдельное решение; в этом дизайне только + отмечаю, что он не блокирует ни один пункт выше. +7. **Строгая форма языкового предиката (§2.2)**, **окно в предложениях (§4Б)** — названы как опции, + строить не предлагаю. + +--- + +## §8 Сводка: что строить, что мерить, что решать + +| # | Пункт | Действие | Деньги стройки | Деньги прода | Двигает ли снапшот | +|---|---|---|---|---|---| +| 1 | Языковой экран на выходе (§2.1) | **СТРОИТЬ** | $0 | $0 | нет; редакторская волна ОДИН раз только у книги с англо-строкой в банке | +| 2 | Счётчик `OffLanguage` + громкий лог батча (§2.1) | **СТРОИТЬ** вместе с 1 | $0 | $0 | нет | +| 3 | Языковой фильтр на свёртке банкноты (§2.1) | **СТРОИТЬ** | $0 | $0 | нет | +| 4 | Нормализация обрамляющих кавычек, Q1 (§3.1) | **СТРОИТЬ** | $0 | $0 | нет | +| 5 | Агрегация из чекпойнтов, A1 (§3.2) | **СТРОИТЬ** + пин инвариант «резюм даёт байт-идентичную карту» | $0 | $0 | только у книги с >1 покупкой черновиков, один раз | +| 6 | `kwic_width` в пар-данные, вариант A (§4) | **СТРОИТЬ**, файл для zh-ru НЕ шипуем | $0 | $0 | нет | +| 7 | Doc-хвост `TerminologyGate` про жанровый словарь (§1) | **СТРОИТЬ** (одна строка) | $0 | $0 | нет | +| 8 | Пример формата в промпте роли (§2.3) | **МЕРИТЬ**, ≈$0.009 (полигон) | — | $0 | перекупка только батчей терминолога | +| 9 | `consistency` как отбор банкноты (§3.3) | **МЕРИТЬ P1, $0** (полигон) | — | — | — | +| 10 | Судья-с-декоем J1 (§3.4) | **НЕ строить**; ≈$0.025/книга, ждёт P1 + холодный старт + санкцию | — | ≈$0.025 | — | +| 11 | `allow_short` для `蛊`/`转` (§5) | **ДАННЫЕ**, только на холодном прогоне | — | — | базовая версия банка = вся книга | +| 12 | Холодный старт (§6) | **исполнить мини-прогон в холодной конфигурации** | ≤$0.23 | — | новая база | + +**Итого денег на всё до стройки: ≈$0.009 (полигон) + $0 (P1).** Стройка пунктов 1–7 — $0 и без единого +вызова провайдера. Прод после стройки не дорожает ни на цент. + +--- + +## §9 Адверсариальный селф-ревью + +Бью по собственному дизайну; то, что устояло, оставлено, то, что не устояло, вычеркнуто выше. + +1. **«Языковой экран — костыль; лечить надо промпт».** Частично верно, и потому вариант В (§2.3) в + дизайне есть. Но вход лечится вероятностно, а якорь пуст ровно там, где страшнее всего. Экран стоит + $0 и молчит, когда всё хорошо. Оставляю оба, с явным порядком: гарантия не зависит от исхода замера. +2. **«Предикат сломает пару, где цель латиница, а исходник — тоже».** Проверил исполнением: предикат + слеп к исходнику и меняет вердикты вместе с целью. Для en→ru он даже ЦЕННЕЕ (§6.2 полигона: срыв в + английский на английском исходнике глазом неотличим от работы). +3. **«≥1 буква цели — слишком слабо, `cultivation (культивация)` пройдёт».** Верно. Назвал как вариант + Б и не рекомендую в этом паке: это другой класс (формат, не язык) со своей ценой ложных + срабатываний. Не прячу. +4. **«Агрегация из чекпойнтов затащит мусор отвергнутых попыток».** Верно, объявил решением. Отвергнутый + черновик — плохой ТЕКСТ; его банкнота от этого не становится неправдой, а подписи всё равно нет. +5. **«Агрегация нарушает детерминизм между прогонами и перебиллит волну».** Самое серьёзное возражение; + [mining.go:108-112](backend/internal/pipeline/mining.go#L108-L112) предупреждает об этом прямым + текстом. Ответ: множество чекпойнтов меняется ТОЛЬКО когда куплены новые черновики, то есть волна и + так перекупалась. Но рассуждения мало — поэтому инвариант вынесен в обязательство приёмки (§3.2). +6. **«Кавычки надо чинить в `NormalizeSourceKey`, там место нормализации».** Соблазнительно и почти + правильно семантически. Цена — перепокупка обеих волн у каждой книги плюс смена семантики матчинга + всего банка памяти ради 4.5% строк. Q1 даёт тот же результат за $0 и ретроактивно. Оси выписаны. +7. **«`consistency` — это переодетая частота, которую только что опровергли».** Проверяю честно: + частота считает вхождения в текст, `consistency` — долю чанков, где независимый чтец ОБЪЯВИЛ строку + термином, к числу чанков, где строка вообще есть. `少年` частотен и почти никогда не объявлен — + именно на этой паре они и расходятся. Но гипотеза остаётся гипотезой: поэтому P1, с критерием ДО + счёта и с армом-без-фактора (голая частота обязана провалиться). +8. **«Судья дешёв — значит стройте».** Считаю это ловушкой. Дёшев он на популяции, размер которой + неизвестен (холодный старт не мерен), и его положительное решение — это выбрасывание строк из банка + книги, то есть та самая «решение о переводе за владельца», от которой D39.47 только что отказался. + Экран должен предлагать порядок, а не отнимать право подписи. +9. **«Вся эта фактура — одна книга, одна пара, одна модель».** Да. Поэтому единственные вещи, которые я + предлагаю строить, — детерминированные, пар-слепые и $0: они не опираются на числа этой книги. + Всё, что опирается (пороги, отбор), отправлено в замер. +10. **Против собственной дельты.** §2 моего же отчёта от 26.07 предлагала расширение эмиссии и считала + его деньги. Замер закрыл посылку. Не переношу оттуда ничего, кроме оси «что банкуется без подписи ≠ + что кладётся на подпись» — она пережила проверку и стоит под §3.0. + +### Критик полноты (норма D39.46, на эту фазу) + +| Проверка | Итог | +|---|---| +| Каждый пункт записки покрыт | 5 из 5 (§2 язык · §3 дисциплина · §4 kwic_width · §5 allow_short · §6 холодный старт) | +| Синк-таблица «источник ↔ код ↔ вердикт» | §1, 12 строк + найденный doc-хвост | +| Проверено исполнением, а не чтением | 4 опоры: приём английского боевым `ParseReply`, расхождение ключей кавычек, `SignificantLen`, предикат на 26 реальных строках | +| Арм без фактора | заложен в P1 (голая частота) и в замер §2.3 (арм без примера) | +| Декой | §3.4, 10% строк, посчитан деньгами | +| Право сказать «не надо» | использовано трижды: судья (не строить), `allow_short` (не «просто строка»), пар-файл kwic для zh-ru (не шипуем) | +| Деньги названы до стройки | §8, ≈$0.009 + $0 | +| Оси каждого пункта | §8, столбцы «двигает ли снапшот» | +| Общность | по каждому пункту отвечен вопрос «пара, которой нет в репо, без правки Go» | +| **НЕ покрыто** | размер популяции банкноты на полной книге (нужен холодный старт) · вторая пара · вторая модель · разметка «терм/мусор» одного разметчика · доступность сохранённого сырья пакета-8 для приёмки §2.5 п.5 | + +--- + +## §10 Что на владельце + +1. **Санкция на стройку пунктов 1–7 §8** (языковой экран + счётчик + фильтр свёртки + кавычки + + агрегация + `kwic_width` в пар-данные + doc-хвост). Всё детерминированное, $0, прод не дорожает. +2. **Санкция на два замера полигона:** пример формата в промпте ≈**$0.009** и `consistency` **$0**. +3. **Решение по §3.4:** ставить ли семантический экран вообще, и если да — J1 перед терминологом, + ≈$0.025/книга. Моя рекомендация — отложить до P1 и холодного старта. +4. **Решение по §6:** идёт ли мини-прогон D39.40 в ХОЛОДНОЙ конфигурации (пустой банк). Одни деньги — + пять ответов, включая единственную неизмеренную цифру пакета-8. +5. **Решение по §5:** добавлять ли `allow_short` для `蛊`/`转` — и подтверждение, что это делается на + холодном прогоне, где перепокупка книги стоит ноль. +6. **Вопрос к полигону (не к владельцу):** живо ли сохранённое сырьё 147 вызовов пакета-8 — на нём + языковой предикат принимается на настоящих данных вместо фикстур, за $0. + +**СТОП.** Стройка — после ратификации. Ни строки продового кода эта сессия не изменила и не коммитила. diff --git a/docs/archive/reports/POLYGON_PREMEASURE_2026-07-26.md b/docs/archive/reports/POLYGON_PREMEASURE_2026-07-26.md index 1b304117..8c03f313 100644 --- a/docs/archive/reports/POLYGON_PREMEASURE_2026-07-26.md +++ b/docs/archive/reports/POLYGON_PREMEASURE_2026-07-26.md @@ -225,7 +225,10 @@ recall против подписанного сида объявляется Н уровне множеств выглядит как разъезд в 97%. И объём даёт банкнота: 67 против 13, то есть **пять шестых кандидатов в карту подписи приходит не от майнера**. -По типам строк банкноты: `term` 67 строк · `title` 13 · `name` 4 · `place` 3. То есть банкнота +По типам строк банкноты в ТОМ ЖЕ основном прогоне (71 строка): `term` 57 · `title` 9 · `name` 3 · +`place` 2. *(Первая редакция давала здесь 67/13/4/3 — счёт по ТРЁМ прогонам рядом с числом +поверхностей одного; смена популяции без оговорки, поймано ревью оркестратора D39.50, исправлено.)* +То есть банкнота эмитирует ровно тот класс, который майнер не эмитирует НИКОГДА (фильтр типа `name|place|title`). Среди её предложений — `光阴之河` (Река времени), `十大奇蛊`, `九转境界`, `力量蛊`, `智慧蛊`, `青铜真元`, `紫府`, `秘法`, `遗藏`, `蛊室`, `性命交修`, `开窍大典`.