13 KiB
SOFTSIGN-DECL (finding-1) — отчёт оркестратору для совместного решения с владельцем
✅ ПРИНЯТ И ЗАЛЕНДЕН; ОБА ВОПРОСА РЕШЕНЫ (оркестратор №9 + владелец, 02.08.2026, D39.76). Спот-чеки приёмки: пин харнесса через rev-parse (build.sh:17) · счёт dst сверен (150 строк / 147 уник.) · durable-сырьё и оба адверсариал-прогона на месте · контрфактика «Синь/синим» бьётся с независимой проверкой фикс-пака. Решения: (Q1) СТОПГЭП A — ДА: сид-формы «Винный червь» И «Фан Юань» (цена нулевая, спойлер-точность протагониста важна); формы пишет бэкенд-сессия (детерминированная морфология, не вкус), подпись владельца обычным сид-циклом; сдвиг
memory_version→ штатный repin, перекупок нет; тем же касанием — гвоздь Линь/линию→Линь/линий и ПРЯМОЙ позитивный тест «Фан Юаню» через forms[] (закрывает PARTIAL ревью D39.75). (Q2) finding-1 ЗАКРЫВАЕТСЯ на A; C (движковый anchor) — в ЗАГЕЙЧЕННЫЙ ТРИГГЕР: реопен только при второй паре живьём, кросс-парный полигон-замер (перенос «[титул]+[ь-фамилия]» + числовой класс, ≥2 пары) = гейт любой правки ядра. Основание: A1 глобально вреден; anchor-gated сломан адверсариал-прогоном (переносит коллизию; чистота книги = транслит-везение); измеренный промах мал и локализован (~4–7 пер-чанк/25 глав, почти весь «Винный червь», «Фан Юань»=0).
Что: исследование finding-1 (мягкознаковый декл-разрыв банк-пост-чека), отпочковавшегося от
BANK_FIXPACK §а при лендинге D39.75 (бэклог-строка 91). Кто/где: бэкенд-сессия; по прямому указанию
владельца замер проведён в eval-конвенции (eval/softsign-decl/, пин-харнесс, $0). Дисциплина: 2-й
путь счёта · вскрытие единиц глазами · author≠reviewer ДВА прогона (дизайн + код/рекомендация). Владелец:
«провести замеры, решать вместе с оркестратором» — отсюда этот отчёт. Строить/править — по слову
владельца; ядро Go этой сессией НЕ трогалось.
Вопрос
declinedFormPresent не принимает склонённую мягкознаковую форму («Фан Юаню»~«Фан Юань»): стеммер §3 «ь»
не стрипает. Наивное «добавить «ь» в decl_suffix» отвергнуто в fix-pack (глобальная коллизия
«Синь/Линь»→«синий/линия»). Чем закрывать: (A) сид-перечень декл-форм · (C) движковый anchor-gated
матч · (B) ничего. И — не ляжет ли решение книго/языко-зависимо в ЯДРО (вопрос владельца).
Метод
Харнесс eval/softsign-decl/main.go на БОЕВОМ стеммере (lang.NewTargetStemmer), build.sh пинит
бэкенд коммитом (78b7b34) через git archive, replace-модуль вне репо — прецедент pkg7/minerharness.
Корпус: банк ~/books/gu-zhenren/coldrun-a/BANK-FULL.tsv (147 уник. dst) × боевой 25-глав-выход
acceptance/guzhenren-25ch-ru.txt (37 480 слов). Сырьё+2 адверсариал-прогона — durable
~/books/gu-zhenren/softsign-decl/. Четыре правила матчинга: A0 (боевое, «ь» не стрипается) · A1
(наивное глобальное «ь») · A2 (anchor=точный) · A3 (anchor=норм-стем).
Находки (с исправлениями самопроверки — обе ошибки мои)
-
Разрыв реален, но МАЛ. Occurrence-level 259 окон (184 склонённых «Фан Юань» = Юаня 152/Юаню 19/Юанем 7/Юане 6 + 67 «Винного червя» + хвост). Но пост-чек срабатывает ПО-ЧАНКОВО: на реальном размере чанка (~1–2k токенов) честный промах = ~4–7 на 25 глав, почти весь — ОДИН термин «Винный червь»; «Фан Юань» → 0 per-chunk (номинатив всегда рядом). ⚠ Моё раннее «~26» было артефактом мелкого блока (1.5k симв) — снято 2-м путём (свип 800→12000 симв: 57→26→13→7→4). Число — прокси (не боевой чанкер).
-
Код харнесса аудирован TRUSTWORTHY (author≠reviewer, статик): 6/6 NO-BUG —
stemAugдоказуемо faithful (реестровые суффиксы все на гласную → ь-финал no-op под реальным реестром), якорь не лицензирует сам себя (norm[k]=false ⟹ exact[k]=false),loadBankDst=147 сверено с файлом (150 строк, 3 дубля dst). Числа окон код-верифицированы + воспроизведены 2-й Python-реализацией. -
A1 (наивное «ь») отвергнут корректно — вред ГЛОБАЛЬНЫЙ, книго-независимый. M4:
softSameStem("Синь","синим")=true,("Линь","линий")=true. Голое «ь» поражает глобальныйSameStem, а через него весь путьdeclinedFormPresent→ и Postcheck, и SpoilerLeaks, в любой книге. -
Adversarial-прогон 1 (дизайн) сломал A3: anchor-gated НЕ закрывает коллизию — ПЕРЕНОСИТ её с одно-словного класса на форму
[титул]+[ь-фамилия](гипотетич. «старейшина Синь» ложно примет «старейшина синего»). В gu-zhenren 0 коллизий — транслит-везение (CJK-стемы юан/шэн не русские слова), НЕ свойство гейта → доказательство безопасности пара-зависимо. Числовой класс НЕ защищён реально на корпусе: «пятого ранга» ×13, «шестого ранга» ×10 — якорь «ранга» общий, гейт даёт ноль защиты. Поправка: A3 ТРОГАЕТ SpoilerLeaks (общий путь), спасает лишь observability-статус. -
Adversarial-прогон 2 (рекомендация) поймал мою противоречивость: я звал сид-перечень «нулём действия», а он — РУЧНОЙ труд. Сверено по коду:
decl.formsруко-писаны в сиде (memseed.go:89→memory.go:315); майнер морфологию НЕ майнит (его «decl» = отвергнутые поверхности, miner_emit.go:60); генератора склонений в Go нет. Для ВСЕГО мягкого класса сид-перечень = «142/142-null», что §3 и убивал.
Общность (ключевой вопрос владельца) — решение остаётся ВНЕ ядра
- Рекомендуемый путь (A) — данные сида
decl.forms, матч genericcontainsWholeWord(mempostcheck.go:158): ноль строк Go, новая пара кладёт свои формы в свой сид, Go не трогается → инвариант «пара, которой в репо нет, без правки Go» выполнен. Grep ядраmembank/stemmerна книго/пара-ЛИТЕРАЛЫ и lang-ВЕТКИ — пусто (единственный хит — иллюстративный коммент-пример 方源→Фан Юань вmempostcheck.go:128, не ветка кода). - Движковый (C) ТРОНУЛ бы алгоритм
declinedFormPresent(ядро membank) + «ь» вtarget-ru.txt(lang-данные). Алгоритм generic — архитектурно чисто ЕСЛИ строить; но его БЕЗОПАСНОСТЬ валидирована на одной паре → в ядро на одно-парном свидетельстве нельзя. Именно это и есть «плохое решение в ядре», которого владелец не хочет.
Опции для решения
| Что | Плюсы | Минусы | |
|---|---|---|---|
| A | Сид-перечень декл-форм 1–2 ВИДИМЫХ мягких канон-имён («Винный червь»; «Фан Юань» если важен SpoilerLeaks) | дёшево (~10 строк YAML), точный матч, ноль коллизии, вне ядра, закрывает ~весь измеренный промах | ручной труд; не масштабируется на хвост; per-book |
| B | Ничего + NB-коммент/регресс-гвоздь (уже в HEAD) | ноль риска/работы | ~4–7 ложняков/25 глав остаются (у шумовой планки) |
| C | Движковый СЛОЙНЫЙ (tail-restricted anchor + стоплист ь-кардиналов) | общий once-done, любая будущая книга бесплатно; данные в lang, алгоритм generic | трогает ядро; safety (перенос/числа) НЕ измерена (M4=3 пары, 1 книга); нужен кросс-парный гейт-замер ПРЕЖДЕ стройки |
Рекомендация (на совместное решение)
- Сейчас: A (+B). Сид-перечень «Винного червя» (+«Фан Юань» при нужде SpoilerLeaks) — закрывает измеренный промах вне ядра; NB-коммент + гвоздь остаются; поправить инертный гвоздь «Линь/линию» → «Линь/линий». В ядро — ничего.
- C — НЕ строить на одно-парном свидетельстве. Если решаем закрывать системно, сперва ЗАКАЗАТЬ полигону кросс-парный корпус-замер частоты ложняков переноса ([титул]+[ь-фамилия]) и числового класса на ≥2 парах (zh→ru + ja→ru/en→ru) как ГЕЙТ; только положительный замер оправдывает правку ядра.
- Честный исход-кандидат: закрыть finding-1 на A, снять со строки 91, C оставить как загейченный бэклог-триггер (не открытый долг).
Что решить вместе с владельцем
- Делаем стопгэп A? Кто пишет сид-формы (полигон / владелец канона)?
- Заказываем кросс-парный гейт-замер под C — или закрываем finding-1 на A и C снимаем в загейченный триггер?
Артефакты
eval/softsign-decl/—main.go·build.sh·README.md(методика+цифры+пределы, исправлен).~/books/gu-zhenren/softsign-decl/—softsign_probe_out.txt·adversarial-review.txt(дизайн) ·code-recommendation-audit.txt(код+рекомендация).- backend HEAD (D39.75): NB-коммент
target-ru.txt:231-237· гвоздиstemmer_test.go/memdecl_test.go.
Честные пределы
Одна книга (gu-zhenren zh→ru); M4 = 3 руко-выбранные пары; per-chunk промах — прокси (не боевой чанкер,
faithful — через tmctl export); чистота A3 на корпусе — транслит-везение, НЕ доказательство общей
безопасности. Числа окон код-верифицированы и 2-м путём; интерпретации (перенос/числовой класс) —
предварительны по CLAUDE.md §4 до вебновелл-кросс-парного среза.