Skip to content

feat(ci): require a verifiable code reference in every changed doc - #130

Open
ManSio wants to merge 1 commit into
mainfrom
feat/docs-refs-gate
Open

ManSio wants to merge 1 commit into
mainfrom
feat/docs-refs-gate

Conversation

@ManSio

@ManSio ManSio commented Nov 13, 2026

Copy link
Copy Markdown
Owner

Что и зачем

AGENTS.md §8 требовал, что каждая правка документации ссылается на факт кода. Проверялось это
человеком: два guard'а смотрят файл целиком (флаги — check_docs_vs_installer.py,
переменные — check_docs_vs_config.py) и не видят, что именно изменилось в PR.

Гейт делает правило механическим для изменения: изменённый .md обязан добавить
проверяемую ссылку.

Что добавлено

  • scripts/check_docs_refs.py — режимы --base <sha> (PR), --staged (локально),
    --diff-file (тесты/отладка). Проверяется факт, не шаблон:
    • путь внутри репозитория (src/…py, .githooks/…) — существует;
    • path::symbol — символ объявлен (def/class/присваивание/поле), а не упомянут в комментарии;
    • path:NNN — строка в пределах файла;
    • install.py --flag — флаг известен установщику; install.py::symbol — функция объявлена;
    • имя переменной — код реально читает её из окружения (os.getenv/os.environ/process.env).
  • Косметика (опечатка/перенос) не блокируется: файл уже ссылался на код и добавленные
    строки не вносят новых утверждений. Перенесённая строка с уже существующей цифрой — не
    новое утверждение (сравнение с текстом файла до правки).
  • Исключения: docs/archive|blog|research/**, experiments/**, реестры по имени файла
    (docs/{en,ru,zh}/CHANGELOG.md тоже).
  • Лимиты: >200 файлов или >20 000 добавленных строк → exit 3 («refusing to pass»).
    Пустой дифф → явное сообщение; не-UTF-8 вход (PowerShell >) → exit 3.
  • CI: шаг Docs references в job test, база — github.event.pull_request.base.sha
    (checkout в job — fetch-depth: 0).
  • AGENTS.md §8 — описание гейта и его границ; §7.7 — шаг в списке CI.

Независимое ревью (свежий контекст) — 4 блокера, все закрыты

# Находка ревьюера Фикс Проверка
B1 env подтверждался подстрокой: MSCODEBASE_DOCS ⊂ MSCODEBASE_DOCS_MARGIN → проходил множество имён, реально читаемых из окружения; сравнение по целому имени test_env_prefix_of_a_real_name_is_rejected + мутация
B2 на Windows-консоли (cp1252) гейт падал трейсбеком на ✗, негативные тесты «проходили» из-за крэша stdout.reconfigure(utf-8, errors=replace) + ASCII-маркеры PYTHONIOENCODING=cp1252 pytest … → 35 passed
B3 git C-quoted путь (не-ASCII/пробел) не распознавался → молчаливый rc=0 unquote_git_path() + тест с "b/docs/en/\320\244.md" test_quoted_non_ascii_path_in_diff_is_parsed
B4 перенос строки с уже существующей цифрой блокировался (реальный коммит) «новое утверждение» = текст, которого не было в файле до правки test_moved_line_with_existing_numbers_is_not_a_new_claim

Major'ы: experiments/** и docs/*/CHANGELOG.md в исключениях; env больше не привязан к трём
префиксам (ONNX_FIXED_PADDING валиден); неизвестный флаг больше не отбрасывает валидную
ссылку в той же строке; ::return и символ «только в комментарии» отклоняются; bare
install.py без флага перестал быть «ссылкой»; лимит строк покрыт тестом; тесты
герметичны (свой git-репозиторий, не HEAD репозитория).

Тесты и мутации

pytest tests/test_docs_refs_gate.py -q        -> 35 passed
pytest (тот же файл) с PYTHONIOENCODING=cp1252 -> 35 passed
ruff check src/ tests/ scripts/check_docs_refs.py -> All checks passed
python scripts/check_docs_vs_installer.py     -> 155 flag reference(s), 0 problem(s)
python scripts/check_docs_vs_config.py        -> 68 variable(s), 0 problem(s)

Мутации (каждая обязана красить тест):

symbol declaration check -> test_symbol_that_is_only_mentioned_is_rejected   RED
installer flag check     -> test_unknown_installer_flag_is_rejected          RED
path containment         -> test_path_traversal_does_not_count               RED
file cap                 -> test_too_many_files_is_refused                   RED
line cap                 -> test_too_many_added_lines_is_refused             RED
new-claim clause         -> test_new_number_in_a_citing_file_still_needs_a_reference RED
env prefix exactness     -> test_env_prefix_of_a_real_name_is_rejected       RED

Ложные блокировки на реальной истории

реплей 36 линейных коммитов main с *.md  -> 0 заблокированных  (до правок: 10 из 36)
G5 + G6 + G7 (уже смёржены)              -> 45 markdown-файлов, 0 без ссылки

Матрица обхода (что гейт НЕ доказывает)

# Вход Статус
1 реальный, но нерелевантный символ («прачечная») ⚠️ A1 — проверяет ревьюер
2 ссылка только в fenced-блоке без утверждения ⚠️ A2
3 документ не в .md (.txt/.rst) ⚠️ A3 (канон — .md)
4 симлинк на POSIX наружу ⏳ не проверено локально; resolve + is_relative_to, точка проверки — ubuntu-раннер
5 bare install.py без флага закрыто (не считается фактом)

Граница записана в AGENTS.md §8: гейт доказывает существование факта, не его
релевантность утверждению.

Риски

  • Первый прогон на легитимной правке без ссылки даст fail — это замысел; лечится ссылкой
    или расширением исключений отдельным PR.
  • Шаг добавлен в CI, не в pre-commit: диапазон PR — естественное место, hook уже несёт 14 гейтов.

@coderabbitai

coderabbitai Bot commented Nov 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 68778fe7-26e3-49ad-a2cb-f8d9ca2ad68e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant