* feat(spec): mobile-first silent enforcement in STACK_REQUIRED + Template C * feat(ci): frontend-e2e job with Playwright in fullstack cookiecutter * docs(skills): mention mobile-first in audit, code-standards, project-status tool * fix(ci): use npm install instead of npm ci + add e2e regression test --------- Co-authored-by: opencode-agent <agent@opencode.local>
8 KiB
| name | description |
|---|---|
| code-standards | Universal code standards for any language. Use when writing, refactoring, or reviewing code. Also when user says "стандарты кода", "code review", "правила разработки". |
Code Standards
1. Код как рассказ
- KISS: Пиши лаконично, без переусложнений. Код читается как последовательный рассказ
- Функциональный стиль: Классы — только когда нужно состояние или интерфейс библиотеки. В остальном — функции
- Приватность: Внутреннюю логику модуля скрывай. Префикс
_в Python/JS,privateв TS/Rust, internal методы по умолчанию - Разделение ответственности: Бизнес-логика ≠ транспорт ≠ представление. Максимум 200-300 строк на файл. Одна ответственность на файл
2. Прагматизм
- YAGNI: Только то что нужно сейчас. Никаких заделов «на будущее», оверинжиниринга и самодеятельности
- Правило 80/20: Если задача ведёт к неоправданному усложнению — предупреди и предложи альтернативу до написания кода
3. Принципы модульности
- Функция/метод — не длиннее 30-50 строк. Если больше — разбивай на мелкие тестируемые функции
- Файл — до 200-300 строк. Больше → декомпозиция
- Конфиги/константы — в отдельный файл, не в логику
- Приватные функции/методы для внутренних деталей (с префиксом
_или аналогом языка)
4. Документирование
- AGENTS.md правило «No comments unless requested» — это default: код без комментариев
- Этот skill описывает исключение: Google-style docstrings на английском для публичных API — когда контракт warrants (библиотечный API, public surface)
- Описывай зачем, а не что — код и так говорит что делает
5. Architecture: good vs bad
Слои для backend: routes → schemas → services → db/models (4-tier, однонаправленный). Роуты тонкие (импортируют только services + schemas), сервисы работают с db/models, бизнес-логика здесь. project-status.py enforces subset (thin routes, centralized models); этот раздел объясняет «почему».
Backend (подробно)
GOOD tree (синтетический):
src/<package>/
├── api/
│ ├── v1/
│ │ ├── routes/users.py ← тонкие роуты, импортируют только services + schemas
│ │ ├── dependencies.py ← Depends(), get_current_user
│ │ └── router.py
│ └── router.py
├── config/
│ ├── settings.py ← pydantic-settings
│ └── logger.py ← loguru setup
├── db/
│ ├── connection.py ← Tortoise.init
│ └── models/ ← ВСЕ ORM-модели здесь (centralized)
│ ├── user.py
│ ├── post.py
│ └── comment.py
├── schemas/ ← Pydantic DTO (НЕ Tortoise models)
│ ├── base.py
│ ├── user.py
│ └── post.py
├── services/ ← бизнес-логика (работает с db/models)
│ ├── user_service.py
│ └── post_service.py
└── utils/
└── metadata.py
Правила GOOD:
- Все ORM-модели в
db/models/(centralized) - Schemas (Pydantic) отдельно от models (Tortoise) — НЕ смешивать
- Роуты тонкие — импортируют только
servicesиschemas - Сервисы работают с
db/models— бизнес-логика здесь - Слои: routes → schemas → services → db/models (4-tier, однонаправленный)
BAD tree 1 — feature-scatter:
src/<package>/
├── channels/
│ ├── models.py ← ❌ модель здесь (scatter)
│ ├── routes.py
│ └── service.py
├── monitor/
│ ├── models.py ← ❌ ещё модель здесь
│ └── routes.py
├── logs/
│ └── models.py ← ❌ и здесь
├── models.py ← ❌ root-level модель
├── db.py ← ❌ connection flat (не db/connection.py)
└── main.py
Проблемы BAD 1: модели раскиданы по feature-папкам; models.py в root; db.py flat; не publishable; Tortoise modules должен перечислять 4+ файла вручную.
BAD tree 2 — mixed-layers:
src/<package>/
├── api/
│ ├── v1/
│ │ └── users.py ← ❌ роут содержит бизнес-логику + Tortoise queries
│ └── models.py ← ❌ модели в api/ (не в db/models/)
├── services/
│ └── user_service.py
│ └── schemas.py ← ❌ schemas в services/ (не в schemas/)
└── main.py
Проблемы BAD 2: роут делает Tortoise queries напрямую (не тонкий); модели в api/models.py (не db/models/); schemas внутри services (не отдельный слой).
Fullstack (кратко)
Backend as above (in backend/ + frontend/ separation). Frontend: SvelteKit co-located *.test.ts в src/lib/, e2e/*.spec.ts для Playwright. НЕ смешивать backend код в frontend/ и наоборот. + mobile-first (PWA + Playwright mobile + axe a11y) — silent enforcement через STACK_REQUIRED["fullstack"].
CLI (кратко)
cli.py (Typer commands) + core.py (business logic). Нет api/db/schemas layers. tests/test_cli.py + tests/test_core.py.
6. Tests
Что писать (как запускать — в run-tests skill). project-status.py enforces subset (conftest required, anti-stub, mirror structure); этот раздел объясняет «почему».
Типы тестов
- Regression — воспроизводит конкретный баг, который был исправлен. Ссылается на issue/PR (
test_parser_handles_crlf_regression_#227). - Integration — пересекает слои (DB+API, scheduler+DB). Имеет
pytest.mark.integration+skipifopt-in. Вtests/integration/. - Unit — чистая функция/сервис, без DB/сети. В
tests/unit/.
Антипаттерны
- Stub files —
test_*.pyбезdef test_*/async def test_*(digital_factory 50/62 файлов).project-statusWARNs. - Тесты без assertions — только
print/logger.info. Каждый тест должен иметь минимум 1assert. - Тесты ради тестов — coverage ради coverage, без реальной проверки поведения.
Mirror structure (backend)
tests/unit/↔src/<pkg>/services/(unit-тесты сервисов)tests/api/↔src/<pkg>/api/v1/routes/(route-тесты через TestClient)tests/integration/↔ cross-cutting flows (opt-in)
conftest.py
Обязателен (backend). Shared fixtures: mock_settings, client, auth_client, create_<entity> factories.