Руководство по проверке AI-готовности (ai-lint)
chutils dev ai-lint — это специализированный инструмент статического анализа (линтер), разработанный для оценки *
AI-готовности* вашей кодовой базы.
Современные AI-ассистенты и автономные кодинг-агенты (такие как Antigravity, Gemini CLI, Claude, GitHub Copilot)
работают значительно эффективнее, если кодовая база хорошо структурирована, снабжена подробными манифестами, строгой
типизацией и стандартизированными docstrings. Инструмент ai-lint помогает автоматически проверять кодовую базу на
соответствие этим стандартам.
Зачем нужен ai-lint?
При работе искусственного интеллекта с вашей кодовой базой возникают следующие проблемы:
- Отсутствие контекста: ИИ не знает архитектурных ограничений проекта, принятых соглашений или используемых технологий, если они нигде не описаны.
- Плохая типизация: Без аннотаций типов (
type hints) ИИ часто делает ошибочные предположения о структурах данных, что ведет к багам. - Неполная документация: Если публичные методы не документированы по стандарту (например, Google Style), ИИ сложнее понять их контракты, параметры и возвращаемые типы.
- Утечка секретов: AI-ассистенты отправляют части кода на внешние сервера. Наличие захардкоженных токенов и паролей в коде создает серьезную угрозу безопасности.
- Изобретение велосипедов: Если в проекте уже есть готовые утилиты (например, логгер или менеджер секретов из
chutils), ИИ может этого не знать и начать писать собственные аналоги.
ai-lint решает эти проблемы, выполняя статический аудит проекта по ряду специализированных правил.
Использование существующих правил
Базовый запуск
Для запуска проверки в текущей директории выполните:
poetry run python -m chutils dev ai-lint
или после установки библиотеки:
chutils dev ai-lint
Параметры командной строки
Вы можете тонко настраивать поведение линтера с помощью флагов:
--staged— аудит только файлов, подготовленных к коммиту (staged diff) в Git. В этом режиме линтер проверяет только измененные файлы, а правила отслеживания зависимостей и покрытия фокусируются на подготовленных изменениях.--strict— строгий режим. Любые предупреждения (warn) будут трактоваться как ошибки (error), и линтер вернет ненулевой код выхода (1).--soft-mode— мягкий режим. Линтер выведет список всех найденных проблем, но всегда будет завершаться с успешным кодом выхода (0). Это полезно при первой интеграции в CI.--ignore "<path1>,<path2>"— дополнительные шаблоны путей для игнорирования (разделяются запятой). Эти шаблоны дополняют настройки из файлов конфигурации.--rules "<Rule1>,<Rule2>"— запуск только указанных правил через запятую (по умолчанию запускаются все правила).--exclude-rules "<Rule1>,<Rule2>"— исключение указанных правил из аудита.--output-format {default,table}— формат вывода результатов проверки (по умолчанию:table).--group-by {file,rule}— группировка вывода отчета (по файлам или по правилам, по умолчанию:file).--custom-rules-path "<path_to_file>"— путь к файлу с вашими собственными правилами.
Пример расширенного запуска:
chutils dev ai-lint --staged --strict --exclude-rules UpgradeCheckRule
Встроенные правила
В ai-lint встроен ряд правил:
1. ManifestRule (severity: warn)
Проверяет наличие файлов манифестов ИИ в корневом каталоге проекта и в основных пакетах (подкаталогах src/).
- Используемые имена файлов:
antigravity.md,agents.md,GEMINI.md(в любом регистре),.cursorrules,.windsurfrules. - Зачем: Файлы манифестов служат инструкцией для ИИ-агентов. В них описывается структура проекта, используемые библиотеки и глобальные правила кодирования.
2. DocstringQualityRule (severity: error)
Выполняет AST-анализ всех публичных классов, функций и методов (исключая тесты).
- Что проверяет:
- Наличие docstring у публичных классов и функций.
- Соответствие структуры docstring формату Google Style (наличие обязательных разделов
Args:иReturns:при наличии параметров и возвращаемого значения). - Документированность каждого аргумента функции в разделе
Args:. - Наличие аннотаций типов (
type hints) у всех аргументов функции (кромеselfиcls). - Наличие аннотации возвращаемого значения (кроме метода
__init__).
- Зачем: Строгая типизация и структурированные docstrings критичны для генерации точного кода ИИ.
3. SecurityHardcodeRule (severity: error)
Сканирует текстовое содержимое файлов и строит AST-дерево для поиска секретов.
- Что проверяет:
- Приватные ключи (заголовки
-----BEGIN PRIVATE KEY-----). - Токены облачных провайдеров (AWS Access Key, Slack Token и др.).
- Жестко заданные присвоения строк переменным, содержащим в имени
key,secret,password,token,pwd( длиной более 8 символов, если они не похожи на плейсхолдеры).
- Приватные ключи (заголовки
- Зачем: Защита от случайной утечки учетных данных в контекст больших языковых моделей (LLM).
4. ChutilsIntegrationRule (severity: warn)
Проверяет интеграцию с экосистемой chutils в проекте.
- Что проверяет:
- Использование стандартного модуля
logging(рекомендует перейти наchutils.setup_logger). - Использование библиотеки
keyringнапрямую (рекомендуетchutils.SecretManager). - Прямые обращения к
os.getenvилиos.environ(рекомендует использовать встроенные инструменты управления конфигурациейchutils). - Ручные вызовы метода
.mkdir(parents=True, exist_ok=True)(рекомендует использоватьchutils.fs.ensure_dir). - Ручные вызовы
.write_text()/.write_bytes(), прямой вызов сериализаторовjson.dump/yaml.dumpили использование временных файловtempfileс последующим перемещением/переименованием для записи файлов ( рекомендует использовать безопасную атомарную записьchutils.fs.atomic_write). - Ручные вызовы получения текущего UTC-времени с использованием
datetime.utcnow()илиdatetime.now(timezone.utc)(рекомендует использоватьchutils.time.utc_now()).
- Использование стандартного модуля
- Зачем: Обеспечивает единообразие архитектуры проекта и направляет ИИ на переиспользование уже готовых библиотечных решений.
5. APIMapRule (severity: error)
Проверяет актуальность карты публичного API (api_map.md).
- Что проверяет:
- Наличие файла
api_map.mdв корне. - Полное соответствие содержимого
api_map.mdреально экспортируемым публичным функциям, классам и константам библиотеки.
- Наличие файла
- Зачем: Карта API позволяет ИИ быстро ориентироваться в возможностях библиотеки без необходимости сканирования всех исходных файлов.
6. EnvSyncRule (severity: warn)
Проверяет соответствие состава ключей переменных окружения в файлах .env и .env.example.
- Что проверяет:
- Одновременное существование файлов
.envи.env.example(если один есть, а другого нет — выдает предупреждение). - Совпадение наборов ключей в обоих файлах.
- Одновременное существование файлов
- Зачем: Предотвращает ошибки запуска приложения из-за отсутствующих локальных переменных или забытых обновлений в файле-шаблоне.
7. CodeDecompositionRule (severity: warn)
Контролирует архитектурную декомпозицию и размер исходных файлов.
- Что проверяет:
- Количество строк в одном файле (по умолчанию не более 700 строк, настраивается параметром
max_file_lines). - Количество классов в одном модуле (по умолчанию не более 5 классов, настраивается параметром
max_file_classes).
- Количество строк в одном файле (по умолчанию не более 700 строк, настраивается параметром
- Зачем: Предотвращает разрастание «божественных» модулей, снижает когнитивную нагрузку и улучшает качество анализа кода большими языковыми моделями.
8. APIMapHashRule (severity: warn)
Вычисляет целостный хэш публичного API кодовой базы и сопоставляет его с сохраненным в api_map.md.
- Что проверяет:
- Сверяет актуальный SHA-256 хэш публичного интерфейса проекта со значением хэша в метаданных
api_map.md. - При расхождении сообщает о необходимости перегенерировать карту с помощью команды
chutils dev generate-context -o api_map.md. - Данное предупреждение носит информационный характер и не блокирует сборку даже в режиме
--strict.
- Сверяет актуальный SHA-256 хэш публичного интерфейса проекта со значением хэша в метаданных
9. FileDependencySyncRule (severity: warn)
Проверяет синхронность обновления связанных файлов и документации в соответствии с картой зависимостей. Данное правило гарантирует актуальность руководств при модификации исходного кода.
- Что проверяет:
- Наличие измененных файлов по глоб-шаблонам источников (например,
"src/chutils/**/*.py"). - Если ключ-источник начинается с префикса
new:(например,"new:src/chutils/dev/rules/*.py"), проверка срабатывает только при создании новых (добавленных или неотслеживаемых) файлов в указанном каталоге, полностью игнорируя редактирование уже существующих файлов. - Если файлы-источники изменены (или созданы новые в режиме
new:), проверяет, что хотя бы один из связанных зависимых файлов (например,"docs/api_map.md") также был обновлен в том же наборе изменений. - Поддержка
--staged: В режимеchutils dev ai-lint --stagedправило анализирует строго файлы, подготовленные к коммиту в индекс Git (git diff --cached), исключая незастейдженные изменения рабочей копии. - Обход глобальных списков игнорирования: Данное правило проверяет Git-изменения напрямую, не подавляясь
записями из
.gitignore,.chutilsignoreили секциейignoreвpyproject.toml. Это гарантирует, что даже если файлы документации (например,docs/*.md) или индекса находятся в глобальном списке игнорирования линтера, правило все равно заставит их обновить. Подавить проверку можно только точечной инлайн-директивой в файле:# chutils: ignore[FileDependencySyncRule].
- Наличие измененных файлов по глоб-шаблонам источников (например,
10. UpgradeCheckRule (severity: warn)
Обнаруживает изменение версии пакета в pyproject.toml по сравнению с Git HEAD или зафиксированной версией в
.chutils/last_known_version.json.
- Что проверяет:
- Наличие увеличения версии при коммите или проверке.
- При обнаружении обновления автоматически скачивает описания изменений релизов из GitHub API (с кэшированием запросов во избежание лимитов).
- Генерирует файл AI-контекста миграции
.chutils/migration_context.mdс группировкой по категориям: Breaking Changes, New API и Deprecations.
- Зачем: Позволяет AI-ассистентам мгновенно получать информацию об изменениях API при повышении версии библиотеки, предотвращая использование устаревших методов.
Настройка и отключение UpgradeCheckRule
Вы можете гибко управлять работой правила и генерацией чейнджлога:
-
Через переменные окружения (
ENV):CHUTILS_DISABLE_UPGRADE_CHECK=1— полностью отключает правилоUpgradeCheckRuleи сетевые запросы к GitHub.CHUTILS_GENERATE_CHANGELOG=0— отключает запись файла.chutils/migration_context.md, но сохраняет информационное предупреждение линтера.
-
Через файл конфигурации (
ai-lint.tomlилиpyproject.toml): ```toml # Отключение правила целиком [ai-lint] exclude_rules = ["UpgradeCheckRule"]
# Или точечная настройка поведения [ai-lint.upgrade_check] enabled = false # Полное отключение правила generate_changelog = false # Отключение только создания файла migration_context.md ```
- Через параметры CLI:
bash chutils dev ai-lint --exclude-rules UpgradeCheckRule
11. LinterCoverageRule (severity: warn)
Проверяет степень покрытия исходного кода правилами отслеживания зависимостей в ai-lint.toml.
- Что проверяет:
- Проверяет, что каждый
.pyфайл в пакетеsrc/chutils/охвачен хотя бы одним глоб-шаблоном в секции[dependencies]файлаai-lint.toml. - Поддержка
--staged: В режимеchutils dev ai-lint --stagedпроверка покрытия выполняется только для измененных и добавленных файлов, подготовленных к коммиту. - Правило автоматически отключается, если секция
[dependencies]отсутствует или пуста, либо если само правилоFileDependencySyncRuleотключено в конфигурации линтера (вrulesили черезexclude_rules).
- Проверяет, что каждый
- Зачем: Гарантирует, что при добавлении новых модулей разработчики или ИИ-агенты не забудут прописать для них правила отслеживания документации, сохраняя её актуальность.
Исключение файлов из проверки покрытия
Если вам необходимо исключить определённые исходные файлы или папки из проверки покрытия правил зависимостей, вы можете использовать три способа:
-
Файл
.chutilsignoreв корне проекта (Рекомендуется для постоянных исключений): Добавьте глоб-шаблоны файлов в.chutilsignore. ПравилоLinterCoverageRuleавтоматически пропустит их.text # .chutilsignore **/testing/**/*.py **/dev/scaffold.py -
Секция
ignoreвai-lint.toml: Укажите пути в глобальном списке игнорирования линтера:toml [ai-lint] ignore = ["**/temp_*.py", "src/chutils/debug_helpers.py"] -
Инлайн-директивы в коде (Рекомендуется для точечного скрытия файлов): Добавьте специальный комментарий в начале (первые 10 строк) исходного файла:
python # chutils: ignore[LinterCoverageRule] # или универсальный игнор всех правил: # chutils: ignore[all]
[!NOTE]
Обратите внимание, что файл.gitignoreне используется правиломLinterCoverageRuleдля исключения файлов. Это сделано для того, чтобы исходные файлы кодовой базы, находящиеся во временном или локальном Git-игноре на этапе разработки, всё равно были должным образом задокументированы.
Настройка конфигурации
Вы можете настроить параметры ai-lint через стандартные файлы конфигурации проекта. Настройки объединяются в следующем
приоритете (от высшего к низшему):
- Флаги CLI
- Переменные окружения (
CH_DEV_AILINT_STRICT,CH_DEV_AILINT_IGNORE,CH_DEV_AILINT_RULES,CH_DEV_AILINT_CUSTOM_RULES_PATH,CH_DEV_AILINT_SOFT_MODE) - Файл
config.yml(секцияDev.AI-Lint) - Файл
pyproject.toml(секция[tool.chutils.ai-lint]) - Значения по умолчанию
Настройка в pyproject.toml
Рекомендуемый способ настройки проекта — добавление секции в pyproject.toml:
[tool.chutils.ai-lint]
strict = false
soft_mode = false
ignore = [
".git",
".venv",
"__pycache__",
"build",
"dist",
"tests",
"docs",
"src/chutils/testing"
]
rules = ["ManifestRule", "DocstringQualityRule", "SecurityHardcodeRule"]
custom_rules_path = ".chutils/custom_rules.py"
env_path = ".env"
example_path = ".env.example"
Настройка зависимостей файлов (File Dependency Sync)
Для правила FileDependencySyncRule вы можете задать сопоставление вложенной секцией
[tool.chutils.ai-lint.dependencies] в pyproject.toml или в корневой секции [dependencies] во внешних файлах
ai-lint.toml/ai-lint.json:
[tool.chutils.ai-lint.dependencies]
"src/chutils/**/*.py" = ["README.md", "docs/api_map.md"]
"schema.json" = ["docs/schema_guide.md"]
# Проверка сработает только при добавлении новых правил (файлов) в указанную директорию
"new:src/chutils/dev/rules/*.py" = ["docs/ai_lint.md"]
Механизм фильтрации и файл .chutilsignore
При выполнении аудита ai-lint объединяет правила скрытия путей из нескольких источников в следующем порядке
приоритета:
- Флаги CLI (
--ignore "<pattern>"): высший приоритет, перекрывают любые глобальные настройки. - Секция
ignoreвpyproject.toml([tool.chutils.ai-lint]) /ai-lint.toml. - Файл
.chutilsignoreв корне проекта: специализированный маскировочный файл форматаgitignore, позволяющий отсечь файлы от ИИ без их скрытия от Git. - Файл
.gitignoreв корне проекта: базовые правила игнорирования Git.
[!NOTE]
Особенность правилаLinterCoverageRule: Данное правило намерено игнорирует.gitignore, но учитывает.chutilsignoreи секциюignoreвpyproject.toml. Это гарантирует, что локально неотслеживаемые исходные.pyфайлы проекта всё равно будут проверены на наличие документации и правил связей.
Пример .chutilsignore:
# Игнорировать автогенерированные файлы и временные отчерки для AI
src/chutils/dev/ast_indexer.py
*.tmp
temp/
tests/fixtures/*
Создание собственных правил (Custom Rules)
Если вам необходимо внедрить специфичные для вашего проекта архитектурные правила, вы можете написать свои собственные правила на Python.
Базовые классы
Пользовательское правило должно быть классом, унаследованным от chutils.dev.ai_lint.Rule.
Интерфейс правила выглядит следующим образом:
from typing import Optional
class LintResult:
rule_name: str # Имя правила, создавшего результат
message: str # Сообщение об ошибке/предупреждении
severity: str # Уровень критичности: "error" или "warn"
file_path: Optional[str] # Абсолютный путь к файлу с проблемой (опционально)
line_number: Optional[
int
] # Номер строки с проблемой (1-индексированный, опционально)
fix_suggestion: Optional[str] # Совет по исправлению проблемы (опционально)
class Rule:
name: str = "" # Уникальное имя правила
description: str = "" # Краткое описание правила
severity: str = "error" # Уровень критичности по умолчанию ("error" или "warn")
def check(self, base_dir: str, files: list[str]) -> list[LintResult]:
"""
Выполняет проверку. Должен возвращать список LintResult.
Args:
base_dir: Абсолютный путь к корню проекта.
files: Список абсолютных путей ко всем неигнорируемым файлам проекта.
"""
raise NotImplementedError
Шаг 1. Написание правила
Создайте файл .chutils/custom_rules.py в вашем проекте.
Например, напишем правило NoAnyTypeRule, которое запрещает использовать Any в аннотациях типов (согласно Zero-Any
Strategy):
import ast
from pathlib import Path
from chutils.dev.ai_lint import Rule, LintResult
class AnyTypeVisitor(ast.NodeVisitor):
def __init__(self, file_path: str, rule_name: str) -> None:
self.file_path = file_path
self.rule_name = rule_name
self.issues: list[LintResult] = []
def visit_Name(self, node: ast.Name) -> None:
# Проверяем использование имени Any
if node.id == "Any":
self.issues.append(
LintResult(
rule_name=self.rule_name,
message="Обнаружено использование типа 'Any' в аннотации.",
severity="error",
file_path=self.file_path,
line_number=node.lineno,
fix_suggestion="Используйте более конкретный тип или Union/Generic вместо Any.",
)
)
self.generic_visit(node)
class NoAnyTypeRule(Rule):
name = "NoAnyTypeRule"
description = "Запрещает использование типа 'Any' в кодовой базе для соблюдения строгой типизации."
severity = "error"
def check(self, base_dir: str, files: list[str]) -> list[LintResult]:
results: list[LintResult] = []
for file_path in files:
# Проверяем только Python-файлы и исключаем тесты
if not file_path.endswith(".py"):
continue
if "tests" in Path(file_path).parts:
continue
try:
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# Парсим файл в AST и обходим его
tree = ast.parse(content)
visitor = AnyTypeVisitor(file_path, self.name)
visitor.visit(tree)
results.extend(visitor.issues)
except Exception as e:
# В случае синтаксических ошибок пропускаем файл
pass
return results
Шаг 2. Подключение правила
Чтобы подключить созданное правило, укажите путь к нему в вашем pyproject.toml:
[tool.chutils.ai-lint]
custom_rules_path = ".chutils/custom_rules.py"
Или передайте путь при запуске команды:
chutils dev ai-lint --custom-rules-path ".chutils/custom_rules.py"
При запуске линтер динамически импортирует ваш файл, найдет все классы, унаследованные от Rule, создаст их экземпляры
и выполнит проверку наряду со встроенными правилами.
Интеграция в CI/CD
Автоматическая проверка AI-готовности кодовой базы при каждом коммите или Pull Request помогает поддерживать проект в идеальном состоянии для работы AI-агентов.
GitHub Actions
Создайте файл .github/workflows/ai-lint.yml:
name: AI Readiness Lint
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
- name: Run AI Linter
run: |
poetry run python -m chutils dev ai-lint --strict