Руководство по проверке 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
Параметры командной строки
Вы можете тонко настраивать поведение линтера с помощью флагов:
--strict— строгий режим. Любые предупреждения (warn) будут трактоваться как ошибки (error), и линтер вернет ненулевой код выхода (1).--soft-mode— мягкий режим. Линтер выведет список всех найденных проблем, но всегда будет завершаться с успешным кодом выхода (0). Это полезно при первой интеграции в CI.--ignore "<path1>,<path2>"— дополнительные шаблоны путей для игнорирования (разделяются запятой). Эти шаблоны дополняют настройки из файлов конфигурации.--rules "<Rule1>,<Rule2>"— запуск только указанных правил (по умолчанию запускаются все встроенные и кастомные правила).--custom-rules-path "<path_to_file>"— путь к файлу с вашими собственными правилами.
Пример расширенного запуска:
chutils dev ai-lint --strict --ignore "build/,legacy_code.py" --rules "ManifestRule,SecurityHardcodeRule"
Встроенные правила
В 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. FileDependencySyncRule (severity: warn)
Проверяет синхронность обновления связанных файлов и документации в соответствии с картой зависимостей. Данное правило гарантирует актуальность руководств при модификации исходного кода.
- Что проверяет:
- Наличие измененных файлов по глоб-шаблонам источников (например,
"src/chutils/**/*.py"). - Если ключ-источник начинается с префикса
new:(например,"new:src/chutils/dev/rules/*.py"), проверка срабатывает только при создании новых (добавленных или неотслеживаемых) файлов в указанном каталоге, полностью игнорируя редактирование уже существующих файлов. - Если файлы-источники изменены (или созданы новые в режиме
new:), проверяет, что хотя бы один из связанных зависимых файлов (например,"docs/api_map.md") также был обновлен в том же коммите/наборе изменений.
- Наличие измененных файлов по глоб-шаблонам источников (например,
8. UpgradeCheckRule (severity: warn)
Обнаруживает изменение версии пакета в pyproject.toml по сравнению с Git HEAD.
- Что проверяет:
- Наличие увеличения версии при коммите или проверке.
- При обнаружении обновления автоматически скачивает описания изменений релизов из GitHub API (с кэшированием запросов во избежание лимитов).
- Генерирует файл AI-контекста миграции
.chutils/migration_context.mdс группировкой по категориям: Breaking Changes, New API и Deprecations.
- Зачем: Позволяет AI-ассистентам мгновенно получать информацию об изменениях API при повышении версии библиотеки, предотвращая использование устаревших методов.
9. LinterCoverageRule (severity: warn)
Проверяет степень покрытия исходного кода правилами отслеживания зависимостей в ai-lint.toml.
- Что проверяет:
- Проверяет, что каждый
.pyфайл в директорииsrc/chutils/соответствует хотя бы одному глоб-шаблону в секции[dependencies]файлаai-lint.toml. - Правило автоматически отключается, если секция
[dependencies]отсутствует или пуста, либо если само правилоFileDependencySyncRuleотключено в списке активных правил.
- Проверяет, что каждый
- Зачем: Гарантирует, что при добавлении новых модулей разработчики или ИИ-агенты не забудут прописать для них правила отслеживания документации, сохраняя её актуальность.
Исключение файлов из проверки покрытия
Если вам необходимо исключить определённые исходные файлы или папки из проверки покрытия правил зависимостей, вы можете использовать три способа:
-
Файл
.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
В дополнение к секции ignore в конфигурации, линтер автоматически ищет файл .chutilsignore в корне проекта. Вы
можете указать там пути в формате glob (по аналогии с .gitignore):
# Игнорировать автогенерированные файлы
src/chutils/dev/ast_indexer.py
*.tmp
temp/
Создание собственных правил (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