Два humanizer-ru: я отозвал свою лучшую метрику и зову тёзку на бенчмарк

Два проекта с одним именем

На GitHub два проекта с именем humanizer-ru. Мой создан 21.01.2026, соседний 03.04.2026. На 11.09.2026 у соседа 333 звезды, у меня 123: в 2,7 раза больше, набрано за два с половиной месяца. Проверка: gh api repos/Vladimir-Human/humanizer-ru --jq ".created_at,.stargazers_count" и gh api repos/ilyautov/humanizer-ru --jq ".created_at,.stargazers_count".

Разница не только в звёздах. Описание соседа обещает «64 признака нейросети, 21 жёсткий бан, сканер в комплекте» (дословно: gh api repos/ilyautov/humanizer-ru --jq .description, снято 11.09.2026). В моём проекте такие обещания запрещены списком: identity.v1.json перечисляет формулировки, которых проект не имеет права произносить. «Обход детекторов как гарантия», «доказывает, что текст написан человеком», «не искажая смысла» и ещё пять. Гейт check_identity.py сверяет их дрейф по всем носителям (коммит 7a4dee28).

Почему я отказался от слов, которые продают лучше? Измерил собственное обещание, и лучшее число пришлось отозвать самому.

Число, которое я опубликовал, а потом снял

25.08.2026 я опубликовал дельту детектируемости: на 12 парах средний скор судейской оценки падал после переписывания с 0.846 до 0.438. Дельта −0.408, знак-тест p=0.006, ниже в 11 парах из 12. Воспроизведение: python3 eval/reproduce.py, данные в eval/detect-results/2026-08-25-detect-axis-12-glm53.json.

Я поставил три контроля, и один убил результат. Реплика на других судейских линиях падение повторила, контроль метки держался. Сломал контроль формата: одна уборка оформления перед переписыванием (шапка обвязки, переносы, разметка, дефисы вместо тире) воспроизводит падение скора почти целиком. Разложение по трём семьям судей: интервал без нуля у канала «формат» в трёх из трёх, у канала «смысл сверх формата» ни в одном (ERRATA.md от 01.09.2026, разбор в research/AXIS-RUBRIC-RETRACTION-2026-09-01.md). Значит −0.408 измеряла не живость текста, а снятие оформления. Интерпретацию я отозвал, число оставил в данных как замер своей величины. Нюанс про судей: одна линия панели повторяла семью, давшую исходное число; независимых линий три.

Второй провал: положительный контроль читательской метрики 03.09.2026, сырой машинный текст против согласованного человеческого, та же панель и слепая подача, предрегистрация заморожена хешем. Вердикт FAIL: панель не отличила сырой машинный текст от человеческого, две семьи судей из трёх дали инверсию, выбирали машинный текст как «более человеческий». Отчёт: research/DI-CONTROL-2026-09.md. Читательское измерение слепо на контрасте, которым я собирался показывать качество переписывания: выводы по этой оси неинтерпретируемы, переписывание переехало в класс C, по явной просьбе и без заявлений о качестве. У таких замеров теперь гриф «судьи LLM, до человеческого контроля». Числа записи контроля приостановлены эрратой 06.09.2026: воспроизведение упирается в данные приватного прогона, цитировать их публично до раскрытия было бы нечестно (ERRATA.md). Исторический отчёт открыт.

Что проверки пережили

Уцелел детерминированный слой: он не судит текст, а ищет следы вставки; его числа воспроизводятся из публичных данных.

Ложные срабатывания маркеров на 12314 текстах-неносителях лёгкого домена (04.09.2026, один проход по замороженной предрегистрации): класс A дал 0, класс B 8, это 0.00065 с Wilson 95% интервалом [0.0003; 0.0013]. Все восемь объяснены: BOM вики-шаблонов, нулевая ширина, bidi-маркеры, переносы из PDF. Воспроизведение python tools/fp_corpus_measure.py, отчёт research/FP-CORPUS-2026.md.

Человеческий контроль: парный прогон 03.09.2026, 0 срабатываний на 26 человеческих текстах, Wilson [0%; 12.9%]. Воспроизведение: python3 eval/run_eval.py + python3 scripts/check_confidence.py --check, корпус eval/manifest.v1.json с хешами. Ноль публикуется как ноль и ходит с интервалом: 0 из 26 это наблюдение, не обещание.

Мягкий статистический слой как детектор мёртв, говорю это вслух. На реалистичном корпусе (90 машинных против 440 человеческих) нет рабочей точки «recall выше нуля при нуле ложных обвинений»: при T=1/K=1 recall 0.211 [0.140; 0.306] при доле ложных обвинений 0.491 [0.445; 0.538] (ERRATA.md от 01.09.2026). Прежнее заявление «62.5% recall при FP=0» отозвано там же. AUC мягкого счёта: 0.6068 и 0.6487 по поколениям генераторов, на тяжёлом домене 0.1626, инверсия (research/F8-UMBRELLA-2026.md, 04.09.2026, tools/f8_corpus_build.py + tools/f8_measure.py). У мягких признаков осталась одна честная роль: калибровать объём правки, а не выносить вердикты.

Зову тёзку на публичный бенчмарк

03.09.2026 я открыл issue #57 в соседнем репозитории: открытый протокол после-измерения и репликационный комплект без условий, каждый прогоняет его на своём проекте. 07.09.2026 автор ответил, цитата: «опубликовать тестовые данные. Ну типа, публичный тест, публичные данные. Сделать бенч для хуманайзеров. Буду рад поучаствовать». 10.09.2026 автор закрыл issue как отработанный. Ветка: https://github.com/ilyautov/humanizer-ru/issues/57, воспроизведение: gh api repos/ilyautov/humanizer-ru/issues/57 и /comments. Манифест метода: research/REWRITE-MEASUREMENT-2026-09.md.

Предложение принимаю. Условия уже работают у меня:

  1. Публичные данные: корпуса с хешами, прогон одной командой.
  2. Предрегистрация до прогона, правило свёртки результата заморожено хешем.
  3. Каждое число с датой и командой; недоступное публикуется как недоступное, с причиной (METRICS.md).
  4. Никаких таблиц с чужими именами: сравнение только парным прогоном одной даты на общем корпусе (LEADERBOARD.md).
  5. Никаких вердиктов об авторстве: детекторные метрики относительные.

Что инструмент делает на самом деле

Ядро детерминированное: 40 regex-маркеров, 31 класса A и 9 класса B (count/class_a_count/class_b_count в markers.v1.json, коммит 7a4dee28). Класс A: жёсткие артефакты копипасты, :contentReference[oaicite:N], ?utm_source=chatgpt.com, grok_card://, метки шагов агента, адреса песочниц. Класс B: контекстные индикаторы, невидимые символы, заглушки шаблонов, символы приватной области. У 38 маркеров из 40 есть запись доказательства с URL и дословным образцом (research/fixtures/marker-sources.json).

Невидимые символы разделены на 23 диапазона по риску: 9 safe снимаются (zero-width space, BOM, мягкий перенос), 11 ambiguous только с явным согласием, они легитимны в эмодзи и смешанных направлениях письма, 3 dangerous не снимаются никогда: U+2028 и U+2029 держат структуру строк и абзацев (markers.v1.json, invisible_classes). Режима «удалить всё невидимое одним движением» нет по построению, это тоже пункт запрещённых обещаний.

Маркер класса A означает факт вставки и статус «источник требует проверки»; вердикта об авторстве нет ни по A, ни по B: совпадения класса B мало даже для рекомендации проверить. Это Главное правило скилла.

Носители: CLI из восьми команд (pip install humanizer-ru, 3.35.2 от 08.09.2026, https://pypi.org/pypi/humanizer-ru/json, stdlib), MCP-сервер из семи инструментов, active в официальном реестре (11.09.2026, https://registry.modelcontextprotocol.io/v0.1/servers/io.github.Vladimir-Human%2Fhumanizer-ru/versions/latest), GitHub Action с гейтом вставки, браузерное демо, где текст не покидает браузер (https://vladimir-human.github.io/humanizer-ru/).

Честные границы

Перефраз и гладкий машинный текст без артефактов слой не ловит: статистика как детектор не работает (показано выше). Короткий текст не ловится: сигналов меньше, чем слов. Водяные знаки без ключа невидимы по построению. Смешанное авторство инструмент не разбирает, английские детекторы не импортирует. Тяжёлый домен остаётся зоной риска: ложных срабатываний на порядок чаще (оба замера 04.09.2026, числа выше). Полные границы: docs/THREAT-MODEL.md.

Собственная чистилка побеждает собственный детектор: после humanizer-polish --remove recall внедрённых маркеров падает с 1.0 до 0.1579, порог 0.5 не выполнен (research/ADVERSARIAL-ROBUSTNESS-V2-2026.md, 04.09.2026, воспроизведение tools/mutants_build.py, tools/f3v2_measure.py, tools/f3v2_rewrite_measure.py). Слепая перезапись теряет факты: доля пар с потерей 0.5699 [0.4685; 0.6658], с добавлением нового 0.3441 (research/FACT-LOSS-2026.md, 04.09.2026, python tools/factloss_measure.py). Поэтому переписывание идёт со сверкой humanizer-facts diff, а обещание «смысл сохранится» в запрещённом списке.

Главная граница: проект почти не видят. Предрегистрированный замер находимости 03.09.2026 дал 2 находки из 5, порог пройден впритык (research/findability-prereg-2026-09-03.md, следующий замер не раньше 1 октября). Из 490 посетителей репо за 14 дней 229 пришли из Google (gh api repos/Vladimir-Human/humanizer-ru/traffic/popular/referrers, owner-only, окно 28.08–10.09.2026). Авторских публикаций нет: на 11.09.2026 я не нашёл ни одной от имени проекта; запросы "Vladimir-Human" habr, "Vladimir-Human" vc.ru, humanizer-ru статья возвращают только репозиторий и автокаталоги. Установки skills.sh растут: 603 на 06.09.2026 (research/DISTRIBUTION-JOURNAL.md), 633 на 11.09.2026 (https://www.skills.sh/vladimir-human/humanizer-ru/humanizer-ru). PyPI: 2605 за неделю на 11.09.2026 (https://pypistats.org/api/packages/humanizer-ru/recent), внутри собственный CI, чистой аудитории счётчик не даёт (METRICS.md). Продолжение истории — на vc.ru (пост от 12.09.2026) и на Хабре (песочница, отправлено в ночь на 12.09.2026, модерация).

Вместо вывода

Я не могу написать в описании репозитория «64 признака и 21 бан»: identity.v1.json запрещает, гейт сверяет все носители. Что могу показать: реестр из 28 чисел, где 2 proven, 23 limited и 3 withdrawn на 08.09.2026 (eval/facts/facts.v1.json, пересчёт статусов: jq -r '.entries[].status' eval/facts/facts.v1.json | sort | uniq -c), эррату с шестью датированными записями (заголовки ERRATA.md на 11.09.2026), лидерборд с парным прогоном одной даты, приглашение к бенчмарку. Инструмент, который отзывает собственное лучшее число, остаётся должен читателю одно: всё остальное пересчитывается.