# План: Линтер (Ruff + ESLint) для агентской разработки ## Мотивация Привести тулинг проекта в соответствие с GRACE-Poly протоколом: - **Pylint** — мёртвый груз (плагин `pylint_ai_checker.checker` не существует, никто не использует) - **Ruff** — уже де-факто стандарт (все агенты ссылаются на `ruff check`), но нет конфига - **ESLint** — есть `.eslintignore`, но нет ни конфига, ни зависимостей, ни npm-скрипта - **semantics-contracts** `@REJECTED`: linter НЕ должен проверять GRACE-Poly контракты — это агентский протокол --- ### 1. Создать `backend/ruff.toml` ```toml target-version = "py313" line-length = 300 # перенос из .pylintrc (символов в строке, не LOC) [lint] select = [ "F", # pyflakes — неиспользуемые импорты/переменные (антислэш) "E", "W", # pycodestyle — PEP8 "I", # isort — порядок импортов "N", # pep8-naming — snake_case "UP", # pyupgrade — современный Python 3.13 "B", # flake8-bugbear — баги "SIM", # flake8-simplify — упрощение "C4", # flake8-comprehensions "C90", # mccabe — cyclomatic complexity (INV_7 из semantics-core) "ARG", # flake8-unused-arguments — мёртвые аргументы "T20", # flake8-print — запрет print (должен быть log()) "RUF", # ruff-specific ] ignore = [ "E501", # line-length — своё через глобальный параметр "D", # pydocstyle — контракты заменяют docstring (per .pylintrc) "ANN", # аннотации — слишком педантично ] [lint.mccabe] max-complexity = 10 # INV_7 из semantics-core [lint.per-file-ignores] "tests/*" = ["T20"] # в тестах print разрешён ``` ### 2. Удалить `.pylintrc` из корня проекта - Плагин `pylint_ai_checker.checker` не существует - Ruff покрывает всё (и быстрее, и с автофиксом) - Ни один агент/скилл не ссылается на pylint ### 3. Добавить ruff в `backend/requirements.txt` ``` ruff>=0.11.0 ``` ### 4. Создать `frontend/eslint.config.js` (flat config) ```js import svelte from "eslint-plugin-svelte"; import js from "@eslint/js"; import globals from "globals"; export default [ js.configs.recommended, ...svelte.configs["flat/recommended"], { languageOptions: { globals: { ...globals.browser, ...globals.node }, }, rules: { "no-unused-vars": ["error", { argsIgnorePattern: "^_" }], "no-console": ["warn", { allow: ["warn", "error"] }], }, }, { ignores: [ "node_modules/", "dist/", "build/", ".svelte-kit/", ".vite/", "coverage/", ], }, ]; ``` ### 5. Обновить `frontend/package.json` **devDependencies** (добавить): ```json "eslint": "^9.0.0", "@eslint/js": "^9.0.0", "eslint-plugin-svelte": "^3.0.0", "globals": "^16.0.0" ``` **scripts** (добавить): ```json "lint": "eslint .", "lint:fix": "eslint . --fix" ``` `.eslintignore` уже существует — его содержимое корректно. ### 6. Обновить агентские инструкции | Файл | Изменение | |---|---| | `.opencode/agents/python-coder.md` | `ruff check src/ tests/` → `ruff check .` | | `.opencode/agents/qa-tester.md` | `ruff check src/ tests/` → `ruff check .` | | `.opencode/agents/fullstack-coder.md` | `ruff check src/ tests/` → `ruff check .` | | `.opencode/agents/speckit.md` | Добавить `npm run lint` в verification | | `.opencode/skills/semantics-python/SKILL.md` | `ruff check src/ tests/` → `ruff check .` | | `.opencode/skills/semantics-contracts/SKILL.md` | `ruff check .` | | `.opencode/command/speckit.*.md` | `ruff check backend/src/ backend/tests/` → `ruff check .` | ### 7. Верификация ```bash # Python cd backend && source .venv/bin/activate pip install -r requirements.txt # установка ruff python -m ruff check . # Frontend cd frontend && npm install # установка eslint + плагинов npm run lint ``` --- ## Что НЕ проверяет linter (сознательно) - GRACE-Poly анкоры (`@BRIEF`, `@RELATION`, `@PRE`/`@POST`, `#region`) — rejected контрактами - Наличие/отсутствие контрактных тегов C1-C5 — агентский протокол - Длину модуля (< 400 LOC) и контракта (< 150 LOC) — сложно автоматизировать в linter, мониторится через code review