# AGENTS.md — карта репозитория для агентов-редакторов

Краткая карта для ИИ-агентов, которым дают задачу по правке этого репозитория.
Человекам — README.md; здесь только то, что предотвращает частые ошибки агентов.

## Что это за репозиторий

humanizer-ru — скилл Agent Skills: находит и снимает следы машинной генерации
в русском тексте. Текстовое ядро (`SKILL.md` + `references/`) исполняет агент;
`scripts/`, `eval/` — валидаторы и корпусы для CI, пользователь их не запускает.

## Инварианты (нарушение ломает CI)

1. **Две синхронные копии текстов.** `SKILL.md` и `references/*.md` существуют
   в двух местах: корень и `dsh/skills/humanizer-ru/`. Правишь одну — копируй
   в другую (гейт `check_bundle_sync.py`, побайтово, CRLF/LF терпимо).
   Скрипты `scripts/check_markers.py` и `scripts/scan_soft_signals.py`
   зеркалируются в `src/humanizer_ru/` (`check_pkg_sync.py`).
2. **Переносы строк — LF.** Windows-агенты: не оставляй CRLF в текстовых
   файлах; релизный гейт отвергает CR в архиве.
3. **Новый regex-маркер** — полный конвейер одной командой:
   `python3 scripts/add_marker.py` (запись в `CASES` + `CLASS_OF` (A/B) +
   три образца (прямой/отрицательный/граничный) + строка в
   `references/chatbot-artifacts-*.md` (для паритета) + секция в
   `tests/test-fixtures-cases.md` + запись в
   `research/fixtures/marker-sources.json` (source_url, accessed,
   verbatim_sample, fixture в `tests/fixtures/`) + регенерация
   `markers.v1.json` (`scripts/export_markers.py`) и демо
   (`demo/markers.v1.json` + `demo/generate_js_rules.py`) + зеркало
   пакета). Область действия гейта доказательств выводится из реестра
   `marker-sources.json` (список `REGISTERED_CASES` отменён 2026-09-05);
   новый case без записи в реестре — сирота, гейт падает.
4. **Витринные числа — гейты.** Счётчики паттернов и гейтов в README RU/EN,
   CHANGELOG, release-check сверяются машинно (`check_docs.py`, секция I.17):
   меняешь число — меняй факт, не только текст.
5. **Гейты умеют падать.** Новый валидатор обязан иметь `--selftest` с
   негативными кейсами и подключаться в `scripts/check_all.py`.
6. **Примеры «До/После» не добавляют фактов** (`check_examples.py`):
   в «После» не появляется чисел, имён, дат, которых не было в «До».
7. **Тексты скилла — без вердиктов об авторстве** по мягким признакам
   (Главное правило SKILL.md): формулировки «вероятно человеческий» и т.п.
   запрещены; детали — в CHANGELOG 3.11.1/3.12.0.

## Полный чек-лист одной командой

```sh
python scripts/check_all.py        # 141 гейт (130 в --quick)
python -m unittest discover -s tests
```

Полный прогон идёт около 9 минут (самые долгие гейты — целостность blind-eval,
~2,5 минуты, `--sdist-test` и compatibility-тест с чистыми venv). Таймаут вызова
меньше 12 минут обрывает зелёный прогон и выглядит как падение гейтов: при
автоматическом запуске закладывай таймаут >= 12 минут или используй `--quick`
(130 гейтов, ~2 минуты) для быстрой проверки.

Перед сдачей правки оба прогона обязаны быть зелёными.

## Куда что класть

| Нужно | Куда |
|---|---|
| Новый паттерн текста | `references/*-patterns.md` (по категории), границы обязательны |
| Новая грепаемая фраза | таблица в `references/quantitative-heuristics.md` |
| Отчёт исследования | `research/` (числа с атрибуцией, без подделок) |
| Данные прогона детекторов | `eval/detect-results/` (НЕ `eval/results/` — там контракт blind_eval) |
| Пользовательские правила правки | `knowledge/corrections.md` (append-only) |

## Чего не делать

- Не править `dsh/skills/humanizer-ru/**` вручную мимо синхронизации.
- Не запускать локальные нейросетевые модели любого рантайма (Ollama,
  transformers, llama.cpp) — запрещено владельцем (2026-08-25,
  уточнено поправкой 2026-09-04); словарные и правило-ориентированные
  библиотеки MIT/BSD/Apache разрешены как optional extra.
- Не ослаблять гейты, чтобы «пройти»: красный гейт чинят, а не отключают.
- Не пушить теги: релизы подписывает только владелец (GOVERNANCE.md).
- Не пересказывать входные тексты задачи в промпте исполнителя: исполнитель
  читает входы сам из файла (слепой прогон сценариев однажды поймал подмену
  фактуры при пересказе координатором прогона — в отчёт качества это попало бы как
  провал скилла).
- Числа в About (описании) GitHub-репозитория гейтами не сверяются: после
  смены витринных счётчиков обновить About вручную, иначе публика увидит
  разночтение.
- Не заносить в публичные файлы внутренние роли прогонов и локальные пути:
  метаданные отчётов пишутся нейтрально (модель, провайдер, температура), без
  «оркестратор/экзекьютор/веер» и без `C:\Users\...` — исторические прогоны
  не переписываются, правило действует для новых.

## Коммит-сообщения и исходящие тексты (issues, PR, сторонние сервисы)

Сообщение коммита описывает изменение, а не процесс его получения:
никаких «по итогам аудита», «модели нашли», «проверено веером» —
кто и как нашёл дефект, читателю истории не нужно. Что менялось
и почему (фактически) — единственное содержание.

Каждое фактическое утверждение сопровождается командой, которая упадёт,
если утверждение ложно. Перед отправкой черновика:

- python3 scripts/check_outward.py черновик.md — ловит ESC/mojibake,
  локальные пути, внутренние роли и отмечает категоричные утверждения
  («не существует», «история переписана», «раньше было только X»): к каждой
  такой строке прикладывается проверяющая команда.
- «Не вижу» и «нет» — разные утверждения. Отсутствие объекта локально
  проверяется полным клоном (shallow-клон молчит о половине истории) или
  API стороннего репозитория — и только потом становится публичным фактом.
- «Было раньше» читается из предыдущего коммита (git show X~1:путь),
  а не из памяти.
- Свойства артефакта сверяются с его содержимым, а не с аналогией по
  проекту: текстовый бандл не умеет того, что делают скрипты вне его.
- Выровненное вручную число получает гейт в этом же коммите.

## Дисциплина правок

Читаешь — потом пишешь; запускаешь — потом коммитишь.

- Перед каждым edit: прочитал текущее состояние файла на диске; replacement
  строится из прочитанного, не из памяти или дифа.
- Нестандартная замена = файловый скрипт: инлайн-Python в PowerShell с
  кириллицей и кавычками ломается всегда.
- Перед написанием гейта или кейса: проверил, что вход существует в среде,
  где он будет выполняться (фикстура selftest, рабочий каталог, PATH).
- Мутируешь одну сущность — посмотри, кто ещё читает её данные:
  меняется version → CHANGELOG, README-тег, CITATION; меняется счётчик →
  все витринные носители; меняется имя файла → все ссылки.
- Перед каждым commit: selftest затронутых гейтов, не только check_all.
