Initial commit: VoIdeaAI - voice-first AI idea assistant

This commit is contained in:
2026-05-13 12:51:42 +03:00
commit 688d043dad
421 changed files with 47915 additions and 0 deletions
+316
View File
@@ -0,0 +1,316 @@
# Полная спецификация проекта для ИИ-ассистента
Этот файл — единственный источник истины для ИИ, работающего с проектом.
Прочитай его полностью перед началом любой работы. Если какой-то аспект не описан — спроси.
---
## 1. РОЛИ
- **Ты — ИИ-ассистент.** Твоя задача: писать код, соответствующий правилам проекта.
- **Пользователь — владелец проекта.** Он принимает все стратегические решения.
- **Агенты — автоматические участники.** Они следят за качеством, версиями и эволюцией.
---
## 2. СТРУКТУРА ПРОЕКТА (MUST FOLLOW)
```
project/
├── app/ # Backend (Python FastAPI)
│ ├── __init__.py
│ ├── main.py # FastAPI app, lifespan, middleware
│ ├── api/
│ │ └── v1/ # Версионированные роуты
│ │ ├── __init__.py # api_v1_router = APIRouter(prefix="/api/v1")
│ │ ├── auth.py # POST /login, /register, /refresh, /oauth
│ │ ├── users.py # GET/PATCH /me
│ │ ├── ideas.py # CRUD /ideas + POST /analyze
│ │ ├── agents.py # GET /agents + POST /run
│ │ ├── sync.py # POST /sync/pull, /sync/push
│ │ └── admin.py # GET /users, /health, /logs
│ ├── core/
│ │ ├── __init__.py
│ │ ├── config.py # Pydantic Settings из .env
│ │ ├── base.py # SQLBase, CoreModel, UUIDMixin, TimestampMixin
│ │ ├── database.py # Engine + async_session_maker + get_db
│ │ ├── security.py # JWT create/decode, password hash
│ │ ├── exceptions.py # HTTPException подклассы
│ │ ├── dependencies.py # get_db, get_current_user, require_admin
│ │ └── metrics.py # Middleware для сбора метрик
│ ├── models/ # SQLAlchemy модели
│ ├── schemas/ # Pydantic схемы (Request/Response)
│ ├── services/ # Бизнес-логика
│ ├── integrations/ # AI провайдеры, внешние API
│ ├── tasks/ # Celery задачи (или прямой вызов)
│ └── agents/ # Системные агенты
├── webui/ # Frontend (React + Vite + Tailwind)
│ ├── src/
│ │ ├── main.tsx
│ │ ├── App.tsx # BrowserRouter + Routes
│ │ ├── index.css # Tailwind directives
│ │ ├── api/ # HTTP-клиент, типы запросов
│ │ ├── auth/ # AuthContext, login/register
│ │ ├── components/ # Layout, ProtectedRoute
│ │ └── pages/ # Dashboard, IdeaView, Admin
│ └── vite.config.ts # Vite + React + PWA proxy
├── tests/ # pytest тесты
├── docs/ # Документация
├── CHANGELOG/ # Версионирование
├── migrations/ # Alembic миграции
├── .env.example
└── project.yaml
```
## 3. ПРАВИЛА КОДИРОВАНИЯ (MUST FOLLOW)
### 3.1 Python
- **Версия:** Python 3.12+
- **Типизация:** `from __future__ import annotations` во всех файлах, `X | None` вместо `Optional[X]`
- **Строки:** двойные кавычки `"` для строковых литералов, одинарные `'` для docstrings
- **Длина строки:** 88 символов (ruff format)
- **Импорты:** абсолютные, порядок: stdlib → third-party → local (алфавитный внутри групп)
- **Docstrings:** Google-style для всех публичных классов/функций/методов
- **Именование:** классы PascalCase, функции/переменные snake_case, константы UPPER_SNAKE
- **Линтер:** ruff (E, F, W, I, N, UP)
- **Форматтер:** ruff format
### 3.2 SQL
- **Ключевые слова:** UPPERCASE (SELECT, FROM, WHERE)
- **Таблицы/поля:** snake_case
- **Индексы:** `ix_tablename_column`
- **Уникальность:** `uq_tablename_column`
### 3.3 TypeScript/React
- **Форматтер:** Prettier (100 символов)
- **Типы:** strict TypeScript, `any` запрещён
- **Импорты:** абсолютные через `@/` alias
- **Стили:** Tailwind CSS, никаких CSS-in-JS
- **Асинхронность:** async/await, `.then()` запрещён
- **Состояние:** zustand или React Context
## 4. АРХИТЕКТУРА (MUST FOLLOW)
### 4.1 Слои (зависимости только внутрь)
```
API → Services → Integrations → Data → Core
```
- **API** не знает про БД. Не создаёт сессий. Только Depends(get_db).
- **Services** не знают про HTTP. Не импортируют FastAPI/fastapi. Работают с БД через сессию.
- **Integrations** не знают про бизнес-логику. Оборачивают внешние API.
- **Data** (models) — SQLAlchemy модели и репозитории.
- **Core** — конфиг, базовые классы, утилиты, безопасность.
### 4.2 Сервисы
Сервис — это класс, который принимает `db: AsyncSession` в конструкторе:
```python
class IdeaService:
def __init__(self, db: AsyncSession):
self.db = db
async def get_by_id(self, idea_id: str) -> Idea | None:
result = await self.db.execute(select(Idea).where(Idea.id == idea_id))
return result.scalar_one_or_none()
```
### 4.3 API
API-роуты — это функции, которые:
1. Принимают `Depends(get_db)` и `Depends(get_current_user)`
2. Создают сервис с сессией
3. Вызывают метод сервиса
4. Возвращают Pydantic response
```python
@router.get("/{idea_id}", response_model=IdeaResponse)
async def get_idea(
idea_id: str,
user: Annotated[User, Depends(get_current_user)],
db: AsyncSession = Depends(get_db),
):
service = IdeaService(db)
idea = await service.get_by_id(idea_id)
if not idea or str(idea.user_id) != str(user.id):
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return _to_response(idea)
```
### 4.4 Зависимости (dependencies.py)
- `get_db()` — yield async_session_maker(), commit/rollback/close
- `get_current_user(credentials, db)` — decode JWT → find user in DB
- `require_admin(user)` — check is_superuser
ВАЖНО: `get_current_user` принимает `db = Depends(get_db)`, а не создаёт свою сессию.
### 4.5 Config
```python
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
server_host: str = "0.0.0.0"
server_port: int = 8020
database_url: str = "sqlite+aiosqlite:///./app.db"
jwt_secret_key: str = ""
log_level: str = "INFO"
@property
def is_sqlite(self) -> bool:
return "sqlite" in self.database_url
```
## 5. БАЗА ДАННЫХ
### 5.1 Поддержка SQLite и PostgreSQL
Для портабельности между SQLite (dev) и PostgreSQL (prod) используем:
- **UUID поля:** `String(36)` во всех моделях (храним UUID как строку)
- **JSON/Array:** `JSON` вместо `JSONB` и `ARRAY`
- **Автовыбор:** через `settings.database_url` и `settings.is_sqlite`
### 5.2 Модели
```python
class UUIDMixin:
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
class TimestampMixin:
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
```
## 6. AI-ИНТЕГРАЦИЯ
### 6.1 Паттерн FallbackChain
```python
class AIProvider(ABC):
async def analyze(self, prompt: str, **kwargs) -> AIResult: ...
class FallbackChain:
def __init__(self, providers: list[AIProvider], max_retries: int = 2):
...
async def analyze(self, prompt: str, **kwargs) -> AIResult:
# Try each provider in order, max_retries per provider
# 1st retry after 2s, 2nd after 5s
# All fail → AIResult(success=False, error="All providers failed")
```
### 6.2 Где хранить промпты
- **YAML-файл** (`docs/agent_prompts.yaml`) для настроек (system_prompt, temperature, max_tokens, provider)
- **MD-файлы** (`docs/specs/agents/`) для детальных спецификаций
- Загрузка через `PromptLoader` (пытается YAML → falls back к MD)
## 7. АГЕНТЫ (IF APPLICABLE)
### 7.1 Ядро (4 агента, с первого коммита)
1. **DocAgent** — пишет документацию
2. **AuditAgent** — проверяет правила
3. **EvolutionAgent** — версионирует агентов
4. **SupervisorAgent** — следит за всеми агентами
### 7.2 Архитектура агента
```python
class BaseAgent(ABC):
name: str
version: str = "1.0.0"
description: str = ""
triggers: list[AgentTrigger]
async def run(self, context: dict | None = None) -> AgentResult: ...
async def health_check(self) -> bool: ...
def compute_checksum(self) -> str: ... # SHA256 от __file__
def bump_version(self, version_type: str = "patch") -> str: ...
```
### 7.3 Agent Versioning
- Каждый агент: независимое A.B.C
- SHA256 checksum файла агента сравнивается с хранимым
- Не совпал → авто-бамп patch + запись в `CHANGELOG/agents/<name>.md`
- EvolutionAgent бампает minor (новая capability) и major (breaking change)
- Формат changelog:
```markdown
# agent_name Changelog
<!-- checksum: sha256hash -->
## 1.0.1 (2026-05-10)
- Fixed: описание
## 1.0.0 (2026-05-09)
- Initial version
```
## 8. ФОНОВЫЕ ЗАДАЧИ
### 8.1 Celery (production) / Прямой вызов (dev)
```python
# tasks/analysis.py
@celery_app.task(bind=True, max_retries=2, name="analyze_idea")
def analyze_idea(self, idea_id: str, role: str) -> dict:
return asyncio.run(_analyze_idea_async(idea_id, role))
# services/analysis_service.py
class AnalysisService:
async def start_analysis(self, idea_id: str) -> dict:
if settings.celery_broker_url:
task = analyze_idea.delay(idea_id, role)
else:
task = await _analyze_local(idea_id, role)
...
```
## 9. ТЕСТИРОВАНИЕ
- **Фреймворк:** pytest с asyncio_mode=auto
- **Unit-тесты:** `tests/unit/` — изолированные, mocked зависимости
- **Integration-тесты:** `tests/integration/` — с БД, реальные запросы
- **Smoke-тесты:** `tests/smoke/` — минимум 1 на endpoint
- **Покрытие:** > 80% (критический код: auth, security, payments — 100%)
## 10. БЕЗОПАСНОСТЬ
- JWT: HS256, access_token 60min, refresh_token 30d
- Пароли: bcrypt (passlib)
- .env в .gitignore — всегда
- Pydantic валидация на всех входах
- RBAC: user, admin (is_superuser)
## 11. РЕШЕНИЯ (SHOULD ASK)
Перед каждым из этих выборов — остановись и спроси пользователя:
| Решение | Опции по умолчанию |
|---------|-------------------|
| База данных | SQLite (dev) → PostgreSQL (prod) |
| Фоновые задачи | Прямой вызов (dev) → Celery (prod) |
| AI провайдеры | FallbackChain с 2 провайдерами |
| Аутентификация | Email+password + JWT |
| Агенты | 4 ядерных + остальные по необходимости |
| Фронтенд | React + Vite + Tailwind + PWA |
| CI/CD | GitHub Actions |
## 12. ЧТО ДЕЛАТЬ ЕСЛИ НЕ ЗНАЕШЬ
1. Поищи в `docs/` — там описано 90% ситуаций
2. Если не нашёл — открой `notes/encountered-issues.md` — может это уже было
3. Если и там нет — посмотри на `notes/improvements.md` — может это запланированное улучшение
4. Если ничего не помогло — **спроси пользователя с рекомендацией**
---
*Этот файл сгенерирован на основе реального опыта. Обновляется при изменении проекта.*
+117
View File
@@ -0,0 +1,117 @@
# Принципы работы
Философия, на которой построен этот шаблон. Если вы разработчик — прочитайте это перед тем как писать код.
---
## Глава 1: Правила важнее кода
Код можно переписать. Архитектуру можно изменить. Но культура проекта — это то, что остаётся после любой переделки.
**Что это значит на практике:**
- Прежде чем писать код, узнай правила (`docs/00-rules.md`)
- Если не знаешь как сделать — найди похожий пример в проекте и делай так же
- Если сомневаешься — **спроси**. Лучше задать 10 вопросов, чем переписывать неделю
**Пример из жизни:** В одном проекте разработчик решил "упростить" и не писал docstrings к публичным методам. Через 3 месяца новый разработчик не мог понять что делает половина сервисов. Пришлось переписывать всё с нуля. Правило "docstrings обязательны" появилось после этого.
---
## Глава 2: Слоистая архитектура как образ мысли
Проект разделён на слои. Зависимости могут идти **только внутрь**:
```
API → Services → Integrations → Data → Core
```
**Что это значит:**
- **API** не знает про БД. Он только принимает запрос и отдаёт ответ.
- **Service** не знает про HTTP. Он реализует бизнес-логику.
- **Integration** не знает про бизнес-логику. Он только вызывает внешний API.
- **Data** не знает про внешний мир. Это модели и запросы к БД.
- **Core** — фундамент. Не зависит ни от чего.
**Почему так:**
- Можно заменить HTTP на gRPC, не трогая сервисы
- Можно заменить PostgreSQL на SQLite, не трогая API
- Можно тестировать каждый слой изолированно
---
## Глава 3: Агенты — это co-developer, а не опция
**Главный урок этого шаблона:** агенты должны жить в проекте с первого коммита.
**4 ядерных агента, которые создаются первыми:**
| Агент | Что делает | Без него |
|-------|-----------|----------|
| **DocAgent** | Пишет документацию параллельно с кодом | Документация пишется "потом" → никогда |
| **AuditAgent** | Проверяет каждый коммит на правила | Правила есть в файле, но не применяются |
| **EvolutionAgent** | Версионирует агентов, управляет развитием | Версии хаотичны, эволюция невозможна |
| **SupervisorAgent** | Следит за всеми агентами, их здоровьем | Экосистема агентов не контролируется |
**Остальные агенты подключаются по мере необходимости:**
- QATesterAgent — когда появились тесты
- FixAgent — когда пойман первый баг
- BacklogAgent — когда появился техдолг
- SecurityAgent — перед production
- SpecAgent — перед релизом
- RolloutAgent — перед деплоем
- ObserverAgent — после запуска
- UITestAgent — когда есть UI
Каждый агент появляется когда в нём возникает реальная потребность, но ядро — с первого дня.
---
## Глава 4: Документация — это код
**Если это не записано — этого не существует.**
- **ADR** фиксируют архитектурные решения. Через год никто не вспомнит "почему мы выбрали PostgreSQL".
- **CHANGELOG** — это контракт с пользователем. Каждое изменение должно быть задокументировано.
- **Decision Log** — лёгкий трекер для каждодневных решений. "Почему мы отложили OAuth".
- **Документация пишется параллельно с кодом**, а не после.
---
## Глава 5: Тестирование — не этап, а процесс
**Код без тестов — это не код, а предложение.**
- Каждый endpoint имеет минимум 1 smoke-тест
- Каждый сервис покрыт unit-тестами
- Каждый баг превращается в тест (чтобы не повторился)
- Покрытие > 80% — обязательно
---
## Глава 6: Саморазвитие
Проект должен становиться умнее без участия человека.
**Три уровня саморазвития:**
1. **Reactive** — агенты реагируют на события (pre-commit, push)
- Audit правил, авто-форматирование, проверка тестов
2. **Proactive** — агенты предлагают улучшения
- Анализ кода, предложение рефакторинга, оптимизация БД
3. **Autonomous** — агенты принимают решения
- Self-healing, auto-scaling, auto-versioning
К концу Stage 3 (cм. `docs/migration-path.md`) проект должен достичь Level 2.
---
## Глава 7: Будущее
Шаблон растёт вместе с проектами. Если вы нашли ситуацию, которую шаблон не описывает:
1. Запишите её в `notes/encountered-issues.md`
2. Если есть идея улучшения — добавьте в `notes/improvements.md` с пометкой `[ASK]`
3. Обновите соответствующий `docs/` файл
**Шаблон должен стать умнее после каждого проекта.**
+73
View File
@@ -0,0 +1,73 @@
# Шаблон проекта
Универсальный шаблон для старта любых проектов. Содержит правила, архитектуру, чеклисты, шаблоны кода и документацию, собранные на основе реального опыта.
## Быстрый старт
1. Скопировать `template/` в корень нового проекта
2. Прочитать `PRINCIPLES.md` — понять философию
3. Дать `AI_CONTEXT.md` ИИ-ассистенту — он поймёт как работать с проектом
4. Настроить `templates/.env.example``.env`
5. Начать писать код согласно `docs/03-project-structure.md`
## Карта шаблона
```
template/
├── README.md # Этот файл
├── AI_CONTEXT.md # Полная инструкция для ИИ-ассистента
├── PRINCIPLES.md # Философия и принципы работы
├── project.yaml # Машиночитаемое описание проекта
├── docs/
│ ├── 00-rules.md # Конституция проекта (главные правила)
│ ├── 01-architecture.md # Слоистая архитектура
│ ├── 02-stack.md # Технологический стек
│ ├── 03-project-structure.md # Структура папок и файлов
│ ├── 04-versioning.md # Версионирование (SemVer + agent versioning)
│ ├── 05-testing.md # Стандарты тестирования
│ ├── 06-security.md # Безопасность
│ ├── 07-performance.md # Производительность и метрики
│ ├── 08-error-handling.md # Обработка ошибок
│ ├── 09-logging.md # Логирование
│ ├── 10-documentation.md # Стандарты документации
│ ├── 11-dependencies.md # Управление зависимостями
│ ├── 12-code-review.md # Процесс ревью кода
│ ├── 13-git-flow.md # Git ветки и коммиты
│ ├── 14-data-retention.md # Политика хранения данных
│ ├── 15-migration-policy.md # Политика миграций БД
│ ├── 16-api-lifecycle.md # Жизненный цикл API
│ ├── 17-self-development.md # Саморазвитие и эволюция
│ ├── migration-path.md # Поэтапный план взросления проекта
│ ├── env-management.md # Управление переменными окружения
│ ├── api-testing-strategy.md # Стратегия тестирования API
│ └── decision-log.md # Лёгкий трекер решений
│ ├── agents/
│ │ ├── 00-agents-overview.md
│ │ ├── 01-agent-architecture.md
│ │ ├── 02-agent-versioning.md
│ │ └── templates/
│ ├── adr/
│ │ └── 000-template.md
│ ├── agent-prompts/
│ │ ├── README.md
│ │ ├── patterns.md
│ │ ├── storage.md
│ │ └── templates/
│ ├── decisions/ # Руководства по выбору технологий
│ ├── checklists/ # Чеклисты (pre-commit, review, deploy, etc.)
│ └── runbook/ # Эксплуатация (startup, backup, incident)
├── templates/ # Готовые шаблоны файлов
├── .github/ # GitHub интеграция (CI/CD, issue templates)
├── notes/ # Заметки (проблемы, улучшения)
└── examples/ # Примеры кода
```
## Ключевые принципы
- **Правила важнее кода** — код можно переписать, культуру нет
- **Агенты с первого коммита** — 4 ядерных агента живут с рождения проекта
- **Документация как код** — если это не записано, этого не существует
- **Спрашивай если сомневаешься** — все неоднозначные решения помечены `[ASK]`
- **Саморазвитие** — проект должен становиться умнее без участия человека
+357
View File
@@ -0,0 +1,357 @@
# Rules & Conventions
Конституция проекта. Применяется ко всем компонентам.
Если в специфичном компоненте нет явного описания ситуации — решение принимается по этим правилам.
Если сомневаешься — спроси.
---
## 1. Code Style Standards
**Python (PEP8 + ruff):**
- Кодировка UTF-8, отступы 4 пробела
- Максимальная длина строки: 88 символов (ruff format)
- Именование: переменные/функции — snake_case, классы — PascalCase, константы — UPPER_SNAKE_CASE
- Аннотации типов — обязательны для аргументов и возвращаемых значений всех функций
- Строки: двойные кавычки " для данных, одинарные ' для docstrings
- Импорты: stdlib → third-party → local (алфавитный порядок внутри групп). Абсолютные импорты, относительные запрещены
- Типизация: `from __future__ import annotations` во всех файлах, `X | None` вместо `Optional[X]`
- Пробелы: вокруг операторов, не внутри скобок
**SQL:**
- Ключевые слова — UPPERCASE (SELECT, FROM, WHERE)
- Имена таблиц и полей — snake_case
- Сложные запросы разбивать на строки, выравнивать JOIN и WHERE
**Оптимальный размер файла:**
- Маршруты/контроллеры: не более 500 строк → разбить на модули
- Модели: не более 200 строк
- Сервисы: не более 300 строк
**TypeScript/React:**
- Formatter: Prettier (100 символов)
- Типы: strict TypeScript, any запрещён
- Импорты: абсолютные через @/ alias
- Стили: Tailwind CSS
- Состояние: Zustand (новые сториджи) или Context API (legacy)
- Формы: react-hook-form + zod (сложные), нативный form (простые)
- Асинхронность: async/await
- Доступность: WCAG AA (eslint-plugin-jsx-a11y enforcement)
- i18n-ready: строки через constants/strings.ts, рендер через <T>
**ESLint (React/TypeScript):**
- Плагины: @eslint/js + typescript-eslint + eslint-plugin-jsx-a11y
- Парсер: @typescript-eslint/parser (flat config)
- Ключевые правила:
- `@typescript-eslint/no-explicit-any`: error
- `@typescript-eslint/strict-boolean-expressions`: error
- `@typescript-eslint/no-unused-vars`: error (кроме `_`)
- `jsx-a11y/alt-text`: error
- `jsx-a11y/aria-props`: error
- `jsx-a11y/aria-role`: error
- `jsx-a11y/label-has-associated-control`: error
- `jsx-a11y/click-events-have-key-events`: error
- `no-console`: error (кроме warn, error)
- `prefer-const`: error
- `no-var`: error
- Установка: `npm install -D eslint @eslint/js typescript-eslint eslint-plugin-jsx-a11y`
- Запуск: `npx eslint src/` (в CI после npm install)
**Testing (Vitest):**
- Фреймворк: Vitest + @testing-library/react
- Имена файлов: `*.test.ts` / `*.test.tsx` рядом с модулем
- Smoke: каждая страница рендерится без падения
- Store: каждый action тестируется
- JSON-репортёр: `vitest run --reporter=json` (для QATesterAgent)
- Установка: `npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom`
- Запуск: `npx vitest run` (в CI после npm ci)
---
## 2. Documentation
- Docstrings: Google-style для всех публичных классов, функций, методов
- TODO/FIXME: с указанием причины. `# TODO(#TASK): причина`
- Предупреждения о рисках: если код затрагивает безопасность, производительность или совместимость
- README.md: в каждой папке с кодом — краткое описание
---
## 3. Naming Conventions
**Переменные окружения:**
```
PROJECT_NAME=
PROJECT_VERSION=X.Y.Z
PROJECT_ENV=local|development|staging|production
SERVER_HOST=X.X.X.X
SERVER_PORT=8020
DATABASE_URL=...
JWT_SECRET_KEY=
```
**Индексы БД:**
```
ix_tablename_column
uq_tablename_column
fk_tablename_column
```
**Ветки Git:**
```
main → стабильная, продакшен
develop → интеграция фич
feature/* → новая функция
hotfix/* → срочное исправление
release/* → подготовка релиза
```
**Миграции БД:**
```
{action}_{table}
```
---
## 4. Git & Versioning
### 4.1 Формат
SemVer: MAJOR.MINOR.PATCH
### 4.2 CHANGELOG
```
CHANGELOG/
├── v1.0.md # 1.0.0 → 1.0.n (патчи дописываются)
├── v1.1.md # 1.1.0 → 1.1.n
└── v2.0.md # 2.0.0 → ...
```
### 4.3 Conventional Commits
```
<тип>[optional scope]: <описание>
feat: → новая функция → MINOR
fix: → исправление → PATCH
BREAKING: → несовместимость → MAJOR
docs: → документация
refactor: → рефакторинг
test: → тесты
chore: → обслуживание
```
### 4.4 Agent Versioning (если используются агенты)
Агенты версионируются независимо по A.B.C.
- **A (major)**: breaking change в публичном интерфейсе
- **B (minor)**: новая capability
- **C (patch)**: внутренние правки, авто-бамп по checksum
Changelog агентов: `CHANGELOG/agents/<name>.md`
---
## 5. Code Review
- Обязателен для всех PR в main и develop
- Минимум 1 апрув от admin/owner
- [ASK]: кто апрувит в текущем проекте?
Чеклист ревью:
- [ ] Нет секретов в коде
- [ ] Нет сырых Exception в API ответах
- [ ] Есть тесты (или TODO с причиной)
- [ ] Документация обновлена
- [ ] ADR создан при архитектурных изменениях
- [ ] CHANGELOG обновлён
---
## 6. Definition of Done (DoD)
- [ ] Код написан (соответствует стилю §1)
- [ ] Линт проходит (ruff — 0 errors)
- [ ] Тесты написаны (минимум 1 smoke)
- [ ] Тесты проходят (pytest — green)
- [ ] Документация обновлена
- [ ] .env.example обновлён (если новая переменная)
- [ ] Миграция написана (если менялась БД)
- [ ] CHANGELOG обновлён
---
## 7. Architecture (SOLID + слоистая)
**Слои (зависимости только внутрь):**
```
API → Services → Integrations → Data → Core
```
**SOLID:**
- S: каждый модуль — одна доменная область
- O: новые интеграции — новые классы
- L: сервисы подчиняются общему интерфейсу
- I: сервис принимает только нужные зависимости
- D: API зависит от абстракции Service
---
## 8. Error Handling
| Слой | Действие |
|------|---------|
| API | HTTPException с detail и status_code |
| Services | Бизнес-исключения без HTTP-статусов |
| Integrations | try/except с fallback |
| DB | Ошибки БД не всплывают выше |
---
## 9. Security Base
- .env — всегда в .gitignore
- JWT: алгоритм HS256, expire = 60 минут, refresh = 30 дней
- Пароли: bcrypt через passlib
- Pydantic валидация на всех входах
- RBAC: роли user, admin
---
## 10. Logging Standards
**Формат строки лога:**
```
[ISO8601] [LEVEL] [component] message key=val
2026-05-10T14:30:00.000Z INFO [auth] User logged in user_id=abc
```
**Уровни по слоям:**
| Слой | DEBUG | INFO | WARNING | ERROR |
|------|-------|------|---------|-------|
| API | Параметры | Request | — | 5xx |
| Service | Входные | Операция | Превышен лимит | Ошибка БД |
| Integration | Raw ответ | Успех | Timeout | Внешний API |
**Запрещено:** f-строки в logger. Только %s (lazy evaluation).
---
## 11. Sensitive Data Policy
**Никогда не логировать:**
- Пароли (даже хэш)
- JWT токены
- API keys и секреты
- Email в открытом виде
**Маскировать в логах:**
- Email: u***@mail.ru
- IP: 195.208.*.*
---
## 12. Third-party Call Fallback Pattern
```
1. Попытка (timeout: 10s)
2. Успех → return data
3. Таймаут → retry 1 (через 2s)
4. Таймаут → retry 2 (через 5s)
5. 4xx → WARNING, return None/fallback
6. 5xx → ERROR, retry → если снова 5xx → return None/fallback
7. Все retry исчерпаны → return fallback результат
```
---
## 13. Performance Budgets (примерные)
| Метрика | Лимит (p95) |
|---------|-------------|
| API response | < 500ms |
| DB query (одиночный) | < 100ms |
| DB query (агрегатный) | < 300ms |
| AI call | < 5s (иначе fallback) |
| WebUI page load | < 2s |
---
## 14. Data Retention Policy (примерная)
| Данные | Срок хранения |
|--------|---------------|
| SystemLog | 90 дней |
| SecurityEvent | 1 год |
| User data | До удаления + 30 дней |
| Session (JWT) | 24 часа |
---
## 15. Dependency Management
- **patch**: в любой момент (bugfix, security)
- **minor**: не чаще 1 раза в спринт
- **major**: только с полным регрессом
---
## 16. Async/Sync Decision Matrix
| Сценарий | Механизм |
|----------|----------|
| GET-запросы, CRUD | sync (await) |
| Отправка email | async (Celery или прямой) |
| AI вызовы | async (Celery или прямой) |
| Бэкапы | async (Celery) |
---
## 17. ADR (Architecture Decision Records)
Любое значимое архитектурное решение фиксируется в `docs/adr/NNN-title.md`.
Формат:
```markdown
# ADR-NNN: Название решения
Статус: принято
Контекст: описание проблемы
Решение: что выбрано
Последствия: плюсы и минусы
```
---
## 18. Tooling
| Инструмент | Назначение |
|------------|------------|
| ruff | Линтер (E, F, W, I, N, UP) |
| ruff format | Форматтер (line-length=88) |
| mypy | Type checker |
| pytest | Тесты (asyncio_mode=auto) |
| pre-commit | Хуки (ruff, ruff-format, trailing-whitespace) |
---
## 19. API Version Lifecycle
```
Текущая: /api/v1/* — стабильная
Deprecation: 3 месяца после выхода новой версии
Отключение: 410 Gone
```
---
## 20. Module Public API Convention
`__init__.py` содержит ТОЛЬКО публичный API модуля:
```python
from app.models.user import User
__all__ = ["User"]
```
---
*Документ создан на основе шаблона. Адаптируйте под конкретный проект.*
+112
View File
@@ -0,0 +1,112 @@
# Архитектура проекта
## Слоистая архитектура
Проект построен по принципу строгой слоистости. Зависимости могут идти **только внутрь** — от API к Core.
```
┌─────────────────────────────────────────────────────┐
│ API │
│ HTTP роуты, Pydantic валидация, OpenAPI │
│ Зависимости: Services │
├─────────────────────────────────────────────────────┤
│ Services │
│ Бизнес-логика, оркестрация │
│ Зависимости: Integrations, Data │
├─────────────────────────────────────────────────────┤
│ Integrations │
│ Внешние API, AI провайдеры, fallback chain │
│ Зависимости: Data │
├─────────────────────────────────────────────────────┤
│ Tasks │
│ Фоновые задачи (Celery или прямой вызов) │
│ Зависимости: Services, Integrations │
├─────────────────────────────────────────────────────┤
│ Agents │
│ Системные агенты (саморазвитие проекта) │
│ Зависимости: Services, Integrations │
├─────────────────────────────────────────────────────┤
│ Data │
│ Модели БД, репозитории, миграции │
│ Зависимости: Core │
├─────────────────────────────────────────────────────┤
│ Core │
│ Config, base classes, security, dependencies │
│ Зависимости: нет (фундамент) │
└─────────────────────────────────────────────────────┘
```
### Правила слоёв
1. **API** не знает про БД. Он получает `db: AsyncSession` через `Depends(get_db)`, но не создаёт сессии сам. Он не импортирует модели.
2. **Services** не знают про HTTP. Они не импортируют FastAPI, Request, Response, HTTPException. Работают с бизнес-данными через сессию БД.
3. **Integrations** не знают про бизнес-логику. Они оборачивают внешние API, управляют таймаутами и ретраями.
4. **Data** (models) — SQLAlchemy модели. Не содержат бизнес-логики. Только структура данных.
5. **Core** — фундамент. Config читает .env, base содержит абстракции, security управляет JWT, dependencies содержит FastAPI-зависимости.
---
## SOLID в проекте
### S — Single Responsibility
Каждый модуль делает одну вещь:
- `idea_service.py` — только операции с идеями
- `yandex_gpt.py` — только вызов Yandex GPT
- `auth.py` — только аутентификация
### O — Open/Closed
Новые интеграции — новые классы, а не модификация старых:
- `AIProvider` (ABC) → `YandexGPTProvider`, `GigaChatProvider`
- `BaseAgent` (ABC) → `DocAgent`, `AuditAgent`, ...
### L — Liskov Substitution
Сервисы принимают `AsyncSession` — любую реализацию (SQLite, PostgreSQL):
- Код работает одинаково на обеих БД
### I — Interface Segregation
Сервис принимает только то, что нужно:
- `IdeaService(db)` — не принимает config, security, и т.д.
- `AuthService(db, settings)` — принимает то, что реально нужно
### D — Dependency Inversion
API зависит от `IdeaService`, а не от `IdeaServicePostgres`:
- Сервисы — это абстракция над слоем данных
- Можно подменить реализацию не меняя API
---
## Dependency Injection
Сессия БД создаётся FastAPI и передаётся через Depends:
```python
async def get_db() -> AsyncSession:
async with async_session_maker() as session:
yield session
```
Сервисы получают сессию в конструкторе:
```python
class IdeaService:
def __init__(self, db: AsyncSession):
self.db = db
```
API создаёт сервис на каждый запрос:
```python
@router.get("/")
async def list_ideas(db: AsyncSession = Depends(get_db)):
service = IdeaService(db)
return await service.list_all()
```
---
## [ASK] Вопросы по архитектуре
- Нужен ли Repository Pattern (отдельный слой между сервисами и моделями)?
- Использовать ли CQRS (разделение чтения и записи)?
- Нужен ли Event Bus для межсервисного взаимодействия?
+44
View File
@@ -0,0 +1,44 @@
# Технологический стек
## Стек по умолчанию
| Компонент | Технология | Версия | Примечание |
|-----------|-----------|--------|------------|
| Язык | Python | 3.12+ | |
| Фреймворк | FastAPI | 0.115+ | async, OpenAPI |
| ORM | SQLAlchemy | 2.0+ | async |
| Валидация | Pydantic | 2.x | v2 синтаксис |
| База данных (dev) | SQLite | — | через aiosqlite |
| База данных (prod) | PostgreSQL | 14+ | через asyncpg |
| Миграции | Alembic | 1.14+ | |
| Аутентификация | JWT + bcrypt | — | passlib |
| Фронтенд | React + Vite + TS | 18/5/5 | |
| Стили | Tailwind CSS | 3.4+ | |
| PWA | vite-plugin-pwa | 0.20+ | |
| Тесты | pytest | 8+ | asyncio_mode=auto |
| Линтер | ruff | | |
| Форматтер | ruff format | | line-length=88 |
## Опциональные компоненты
| Компонент | Когда добавлять | Альтернативы |
|-----------|----------------|--------------|
| **Celery** + Redis | Для фоновых задач (AI, email, backup) | Прямой вызов в dev |
| **PostgreSQL** | Для production | SQLite в dev |
| **AI providers** | Если нужен AI-анализ | Yandex GPT, GigaChat, OpenAI |
| **OAuth2** | Если нужен вход через соцсети | Яндекс, Google, GitHub |
| **SMTP** | Если нужны email-уведомления | |
| **Docker** | Для воспроизводимого деплоя | |
| **Prometheus + Grafana** | Для мониторинга в prod | |
| **System Agents** | Для саморазвития проекта | 4 ядерных, остальные по необходимости |
## [ASK] Выбор стека
Перед началом проекта ответьте на вопросы:
1. **Будет ли проект в production?** Если да → PostgreSQL + мониторинг
2. **Нужны ли фоновые задачи?** Если да → Celery (или прямой вызов на старте)
3. **Нужен ли AI?** Если да → FallbackChain с 2+ провайдерами
4. **Нужен ли фронтенд?** Если да → React/Vite/Tailwind
5. **Нужна ли PWA?** Если да → vite-plugin-pwa + Service Worker
6. **Нужны ли агенты?** Если да → 4 ядерных с первого коммита
+151
View File
@@ -0,0 +1,151 @@
# Структура проекта
```
project/
├── app/ # Backend
│ ├── __init__.py
│ ├── main.py # FastAPI app: lifespan, middleware, routers, CORS
│ │
│ ├── api/ # HTTP слой
│ │ ├── __init__.py # api_v1_router
│ │ └── v1/ # Версионированные роуты
│ │ ├── __init__.py # Сборка всех роутеров
│ │ ├── auth.py # POST /login, /register, /refresh, /oauth
│ │ ├── users.py # GET/PATCH /me
│ │ ├── ideas.py # CRUD /ideas + POST /analyze
│ │ ├── agents.py # GET /agents + POST /run
│ │ ├── sync.py # POST /pull, /push
│ │ └── admin.py # GET /users, /health, /logs
│ │
│ ├── core/ # Фундамент
│ │ ├── __init__.py
│ │ ├── config.py # Pydantic Settings из .env
│ │ ├── base.py # SQLBase, CoreModel, UUIDMixin, TimestampMixin
│ │ ├── database.py # create_async_engine, async_session_maker, get_db
│ │ ├── security.py # create_token, decode_token, hash/verify password
│ │ ├── exceptions.py # HTTPException подклассы
│ │ ├── dependencies.py # get_db, get_current_user, require_admin
│ │ └── metrics.py # Middleware: request timer, counters
│ │
│ ├── models/ # SQLAlchemy модели
│ │ ├── __init__.py # Все модели в __all__
│ │ ├── user.py # User: id, email, password, roles
│ │ ├── idea.py # Idea: title, content, tags, status
│ │ ├── agent.py # AgentConfig: version, checksum
│ │ ├── backlog.py # BacklogTask: title, status, priority
│ │ └── log.py # LogEntry: level, source, message
│ │
│ ├── schemas/ # Pydantic схемы (Request/Response)
│ │ ├── __init__.py # Все схемы в __all__
│ │ ├── auth.py # LoginRequest, TokenResponse, etc.
│ │ ├── user.py # UserCreate, UserResponse, etc.
│ │ ├── idea.py # IdeaCreate, IdeaResponse, AnalyzeResponse
│ │ ├── agent.py # AgentRunRequest, AgentStatusResponse
│ │ ├── sync.py # SyncPullRequest, SyncResponse
│ │ └── admin.py # SystemHealth, LogEntryResponse
│ │
│ ├── services/ # Бизнес-логика
│ │ ├── __init__.py
│ │ ├── auth_service.py # Регистрация, логин, OAuth
│ │ ├── user_service.py # CRUD пользователей
│ │ ├── idea_service.py # CRUD идей
│ │ ├── agent_service.py # Управление агентами
│ │ ├── analysis_service.py # Запуск AI-анализа
│ │ └── sync_service.py # Синхронизация
│ │
│ ├── integrations/ # Внешние сервисы
│ │ ├── __init__.py
│ │ └── ai/ # AI провайдеры
│ │ ├── __init__.py # AIProvider, AIResult, FallbackChain
│ │ ├── base.py # AIProvider ABC, AIResult dataclass
│ │ ├── prompt_loader.py # Загрузка промптов из YAML/MD
│ │ ├── yandex_gpt.py # YandexGPTProvider
│ │ ├── gigachat.py # GigaChatProvider
│ │ └── fallback.py # FallbackChain
│ │
│ ├── tasks/ # Фоновые задачи
│ │ ├── __init__.py # Celery app (ленивый импорт)
│ │ └── analysis.py # analyze_idea (Celery или прямой вызов)
│ │
│ └── agents/ # Системные агенты
│ ├── __init__.py
│ ├── base.py # BaseAgent ABC, AgentResult, AgentStatus
│ ├── registry.py # AgentRegistry
│ ├── models.py # AgentState, AgentReport, AgentMetric
│ ├── triggers.py # Триггеры запуска
│ ├── doc_agent.py # Пишет документацию
│ ├── audit_agent.py # Проверяет правила
│ ├── evolution_agent.py # Версионирует агентов
│ ├── supervisor_agent.py # Следит за всеми агентами
│ └── ... # Остальные агенты по необходимости
├── webui/ # Frontend
│ ├── index.html
│ ├── package.json
│ ├── vite.config.ts # Vite + React + PWA + API proxy
│ ├── tsconfig.json
│ ├── tailwind.config.js
│ ├── postcss.config.js
│ ├── public/
│ │ ├── favicon.svg
│ │ ├── manifest.json
│ │ └── icons/
│ └── src/
│ ├── main.tsx
│ ├── App.tsx # BrowserRouter + Routes
│ ├── index.css # Tailwind directives
│ ├── vite-env.d.ts
│ ├── api/
│ │ ├── client.ts # apiFetch, setTokens, refreshAccessToken
│ │ └── ideas.ts # Типы + функции для /ideas
│ ├── auth/
│ │ └── AuthContext.tsx # useAuth() hook
│ ├── components/
│ │ ├── Layout.tsx # Header + main
│ │ └── ProtectedRoute.tsx # Auth guard
│ └── pages/
│ ├── LoginPage.tsx
│ ├── RegisterPage.tsx
│ ├── Dashboard.tsx # Список идей
│ ├── IdeaView.tsx # Просмотр + анализ
│ ├── IdeaCreate.tsx # Создание идеи
│ ├── IdeaEdit.tsx # Редактирование
│ └── AdminPage.tsx # Админ-панель
├── tests/ # Тесты
│ ├── conftest.py # Глобальные фикстуры
│ ├── unit/ # Unit-тесты
│ │ ├── conftest.py
│ │ └── test_*.py
│ ├── integration/ # Интеграционные тесты
│ │ ├── conftest.py
│ │ ├── test_api.py
│ │ └── test_db.py
│ └── smoke/ # Smoke-тесты
│ └── test_health.py
├── docs/ # Документация
│ ├── 00-rules.md
│ ├── ... (остальные файлы правил)
│ ├── adr/ # Architecture Decision Records
│ ├── agents/ # Системные агенты
│ ├── decisions/ # Руководства по выбору
│ ├── checklists/ # Чеклисты
│ └── runbook/ # Эксплуатация
├── CHANGELOG/ # Версионирование
│ ├── v1.0.md # CHANGELOG версии 1.0
│ └── agents/ # Changelog агентов
│ ├── doc_agent.md
│ └── ...
├── migrations/ # Alembic (если PostgreSQL)
│ └── versions/
├── .env.example
├── .gitignore
├── project.yaml
├── requirements.txt
└── README.md
```
+97
View File
@@ -0,0 +1,97 @@
# Версионирование
## Формат: SemVer
```
MAJOR.MINOR.PATCH
```
- **MAJOR**: несовместимые изменения API
- **MINOR**: новая функциональность (обратно совместимо)
- **PATCH**: исправления багов
## CHANGELOG
**Где хранить:** `CHANGELOG/`
**Правила:**
- Каждая MAJOR версия → новый файл: `CHANGELOG/v1.0.md`
- Каждая MINOR версия → новый файл: `CHANGELOG/v1.1.md`
- PATCH дописывается в существующий файл
```
CHANGELOG/
├── v1.0.md # 1.0.0 → 1.0.5
├── v1.1.md # 1.1.0 → 1.1.3
└── v2.0.md # 2.0.0 → ...
```
## Conventional Commits
Каждый коммит должен соответствовать формату:
```
<тип>[optional scope]: <описание>
[optional body]
[optional footer]
```
| Тип | Действие | Влияние на версию |
|-----|----------|-------------------|
| `feat` | Новая функция | MINOR |
| `fix` | Исправление | PATCH |
| `BREAKING` | В теле или `!` после типа | MAJOR |
| `docs` | Документация | — |
| `refactor` | Рефакторинг | — |
| `test` | Тесты | — |
| `chore` | Обслуживание | — |
## Agent Versioning (если используются агенты)
Каждый агент версионируется **независимо** от проекта по A.B.C.
### Правила бампа
| Компонент | Когда меняется | Кто меняет |
|-----------|---------------|------------|
| **A (major)** | Breaking change в публичном интерфейсе | EvolutionAgent |
| **B (minor)** | Новая capability (метод, роль, prompt) | EvolutionAgent |
| **C (patch)** | Внутренние правки, без изменения поведения | Сам агент (авто) |
### Механика
1. Агент запускается → вычисляет SHA256 checksum своего `__file__`
2. Сравнивает с хранимым checksum (в БД или в changelog файле)
3. Не совпал → авто-бамп patch → запись в changelog → обновление checksum
4. EvolutionAgent управляет minor/major бампами
### Хранение
```
CHANGELOG/agents/<agent_name>.md
```
Формат:
```markdown
# audit_agent Changelog
<!-- checksum: sha256hash -->
## 1.0.2 (2026-05-10)
- Fixed: описание исправления
## 1.0.1 (2026-05-09)
- Fixed: ещё одно исправление
## 1.0.0 (2026-05-08)
- Initial version
```
### Разделение ответственности
| Аспект | Владелец | Где хранится |
|--------|----------|--------------|
| Версия проекта | SpecAgent (или человек) | `project.yaml`, `CHANGELOG/v*.md` |
| Версия агента | EvolutionAgent | `AgentConfig.version` (БД) |
| Changelog проекта | SpecAgent (или человек) | `CHANGELOG/v*.md` |
| Changelog агента | EvolutionAgent | `CHANGELOG/agents/<name>.md` |
+117
View File
@@ -0,0 +1,117 @@
# Стандарты тестирования
## Философия
**Код без тестов — это не код, а предложение.** Если функцию нельзя проверить — она либо не нужна, либо её нужно переписать.
---
## Пирамида тестов
```
/\ E2E (10%): сквозные сценарии
/ \
/ \
/──────\ Integration (20%): API, БД, внешние сервисы
/ \
/──────────\ Unit (70%): изолированные модули
/ \
```
---
## Типы тестов
### Unit-тесты (`tests/unit/`)
- Тестируют один класс/функцию в изоляции
- Внешние зависимости мокаются
- Быстрые (миллисекунды)
- Пример: тест сервиса с mocked репозиторием
```python
async def test_idea_service_create():
service = IdeaService(mock_db)
idea = await service.create(user_id="1", title="Test", content="Content")
assert idea.title == "Test"
assert idea.status == "draft"
```
### Integration-тесты (`tests/integration/`)
- Тестируют взаимодействие компонентов
- Используют реальную БД (SQLite в памяти)
- Проверяют API endpoints, БД запросы
- Пример: тест регистрации пользователя
```python
async def test_register_user(async_client):
response = await async_client.post("/api/v1/auth/register", json={
"username": "test",
"email": "test@test.com",
"password": "secret123",
})
assert response.status_code == 201
data = response.json()
assert "access_token" in data
```
### Smoke-тесты (`tests/smoke/`)
- Минимум 1 тест на каждый endpoint
- Проверяют что endpoint отвечает и возвращает корректный статус
- Быстрая проверка здоровья системы
```python
async def test_health_endpoint(async_client):
response = await async_client.get("/health")
assert response.status_code == 200
assert response.json()["status"] == "healthy"
```
---
## Покрытие
- **Общее покрытие:** > 80%
- **Критический код (auth, security, payments):** 100%
- **Новый код:** без тестов не принимается в PR
---
## Что тестировать
### Обязательно (9 сценариев для каждого endpoint)
1. **Missing field** → 422
2. **Wrong type** → 422
3. **Expired/invalid token** → 401
4. **Wrong permissions** → 403
5. **Not found** → 404
6. **Conflict** → 409
7. **Success** → 200/201
8. **Rate limit** → 429 (если реализован)
9. **Idempotency** → тот же результат при повторе
### Для каждого сервиса
- Успешное выполнение
- Ошибка валидации
- Ошибка БД
- Граничные случаи (пустой список, null, максимальная длина)
---
## Конфигурация pytest
```ini
# pyproject.toml или pytest.ini
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = ["test_*.py"]
```
---
## [ASK] Вопросы по тестированию
- Нужен ли coverage порог в CI? (рекомендуется 80%)
- Использовать ли vcrpy для записи ответов внешних API? (да, для AI провайдеров)
- Нужны ли performance-тесты? (да, для критических endpoint'ов)
+86
View File
@@ -0,0 +1,86 @@
# Безопасность
## Базовые требования
- `.env` — всегда в `.gitignore`. Никогда не коммитить.
- JWT: алгоритм HS256, access_token = 60 минут, refresh_token = 30 дней
- Пароли: bcrypt через passlib
- Pydantic валидация на всех входах
- RBAC: роли user, admin
---
## Аутентификация
### JWT
```python
# app/core/security.py
def create_access_token(data: dict, expires_delta: timedelta | None = None) -> str:
to_encode = data.copy()
expire = datetime.now(timezone.utc) + (expires_delta or timedelta(minutes=60))
to_encode.update({"exp": expire, "type": "access"})
return jwt.encode(to_encode, settings.jwt_secret_key, algorithm=settings.jwt_algorithm)
def decode_token(token: str) -> dict[str, Any] | None:
try:
return jwt.decode(token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm])
except JWTError:
return None
```
### Password hashing
```python
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
```
---
## RBAC
| Роль | Права |
|------|-------|
| user | Базовые: CRUD своих данных, запуск анализа |
| admin (is_superuser) | Управление пользователями, просмотр логов, системные настройки |
Проверка прав:
```python
async def require_admin(user: Annotated[User, Depends(get_current_user)]) -> User:
if not user.is_superuser:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Admin access required")
return user
```
---
## Sensitive Data
**Никогда не логировать:**
- Пароли (даже хэш)
- JWT токены
- API keys и секреты
- Email в открытом виде (только user_id)
**Маскировать в логах:**
- Email: u***@mail.ru
- IP: 195.208.*.*
---
## [ASK] Вопросы по безопасности
- Нужен ли audit log? (рекомендуется для production)
- Нужно ли шифрование данных в покое? (да, если хранятся персональные данные)
- Нужен ли rate limiting? (да, для production)
- Нужен ли CORS? (да, если фронтенд на другом домене)
- Нужен ли CSRF? (нет, если используем JWT в Bearer header)
+77
View File
@@ -0,0 +1,77 @@
# Производительность
## Performance Budgets
| Метрика | Лимит (p95) | Примечание |
|---------|-------------|------------|
| API response (без AI) | < 500ms | |
| API response (с AI) | < 5s | Fallback после 5s |
| DB query (одиночный) | < 100ms | С индексом |
| DB query (агрегатный) | < 300ms | |
| WebUI page load | < 2s | |
| AI call | < 5s | Иначе fallback |
---
## Индексы БД
**Что индексировать:**
- Поля в WHERE и JOIN: `user_id`, `status`, `email`
- Поля сортировки: `created_at`
- Внешние ключи: `user_id`, `parent_id`
**Формат имени индекса:** `ix_tablename_column`
```sql
CREATE INDEX ix_ideas_user_id ON ideas(user_id);
CREATE INDEX ix_ideas_status ON ideas(status);
```
---
## Connection Pool
```python
engine = create_async_engine(
settings.database_url,
pool_size=10, # Постоянные соединения
max_overflow=20, # Дополнительные при пике
pool_pre_ping=True, # Проверка перед использованием
)
```
Для SQLite pool настраивать не нужно — он файловый.
---
## Метрики (если реализованы)
Собираемые метрики:
| Метрика | Тип | Описание |
|---------|-----|----------|
| `http_requests_total` | Counter | Всего запросов |
| `http_request_duration_ms` | Histogram | Время ответа (p50/p95/p99) |
| `http_requests_by_endpoint` | Counter | По endpoint'ам |
| `http_errors_total` | Counter | 4xx и 5xx |
| `db_query_duration_ms` | Histogram | Время запросов к БД |
| `ai_provider_calls` | Counter | Вызовы AI провайдеров |
| `agent_execution_duration` | Histogram | Время выполнения агентов |
**Где хранить:** в БД (таблица `agent_metrics`), в перспективе — Prometheus.
---
## Когда оптимизировать
1. **Профилировать до оптимизации.** Не гадать — измерять.
2. **Оптимизировать только горячие пути.** 90% времени уходит на 10% кода.
3. **Кэшировать только то, что реально часто читается.** Преждевременное кэширование — корень всех зол.
---
## [ASK] Вопросы по производительности
- Нужен ли Redis кэш? (да, если часто читаются одни и те же данные)
- Нужен ли CDN для статики? (да, для production)
- Нужен ли database sharding? (нет, до 10M записей)
+106
View File
@@ -0,0 +1,106 @@
# Обработка ошибок
## Матрица ошибок по слоям
| Слой | Что делаем | Пример |
|------|-----------|--------|
| **API** | HTTPException с detail и status_code | `raise HTTPException(404, detail="Not found")` |
| **Services** | Бизнес-исключения без HTTP-статусов | `raise IdeaNotFoundError(idea_id)` |
| **Integrations** | try/except с fallback | `return AIResult(success=False, error=...)` |
| **Data/DB** | Ошибки не всплывают выше | Ловим в сервисе |
---
## Иерархия исключений
```python
# app/core/exceptions.py
class AppError(Exception):
"""Базовое исключение приложения."""
def __init__(self, message: str, details: dict | None = None):
self.message = message
self.details = details or {}
class NotFoundError(AppError):
"""Ресурс не найден."""
def __init__(self, resource: str, resource_id: str):
super().__init__(f"{resource} not found: {resource_id}", {"resource": resource, "id": resource_id})
class ValidationError(AppError):
"""Ошибка валидации."""
def __init__(self, field: str, message: str):
super().__init__(message, {"field": field})
class AuthError(AppError):
"""Ошибка аутентификации."""
def __init__(self, message: str = "Authentication failed"):
super().__init__(message)
class ForbiddenError(AppError):
"""Нет прав."""
def __init__(self, message: str = "Access denied"):
super().__init__(message)
```
---
## Fallback Pattern (для внешних вызовов)
```python
# Паттерн для всех вызовов внешних API
async def call_with_fallback(provider: AIProvider, prompt: str) -> AIResult:
max_retries = 2
last_error = None
for attempt in range(max_retries + 1):
try:
result = await asyncio.wait_for(
provider.analyze(prompt),
timeout=10.0
)
if result.success:
return result
last_error = result
except asyncio.TimeoutError:
last_error = AIResult(success=False, error="Timeout")
except Exception as e:
last_error = AIResult(success=False, error=str(e))
if attempt < max_retries:
await asyncio.sleep(2 if attempt == 0 else 5)
return last_error
```
---
## Логирование ошибок
| Уровень | Когда | Пример |
|---------|-------|--------|
| DEBUG | Входящие параметры | `Request params: id=123` |
| INFO | Успешная операция | `User created: id=456` |
| WARNING | Timeout, retry | `Yandex GPT timeout, retry 1/2` |
| ERROR | Ошибка внешнего API | `GigaChat 500: Internal error` |
| CRITICAL | Исчерпаны все retry | `All AI providers failed for idea 789` |
---
## Graceful Degradation
Когда внешний сервис недоступен:
1. **DB недоступна** → 503 Service Unavailable
2. **Redis недоступен** → работаем без кэша (log WARNING)
3. **AI провайдер недоступен** → возвращаем fallback результат
4. **Celery недоступен** → выполняем задачу синхронно
---
## [ASK] Вопросы по обработке ошибок
- Нужны ли пользовательские исключения для всех бизнес-сценариев?
- Нужен ли sentry или аналогичный мониторинг ошибок?
- Как обрабатывать ошибки валидации на фронтенде?
+78
View File
@@ -0,0 +1,78 @@
# Логирование
---
## Формат строки лога
```
[ISO8601] [LEVEL] [component] message key=val
```
Пример:
```
2026-05-10T14:30:00.000Z INFO [auth] User logged in user_id=abc123
2026-05-10T14:30:01.000Z WARNING [ai] Yandex GPT timeout retry=1 max_retries=2
2026-05-10T14:30:02.000Z ERROR [sync] Sync failed for user_id=abc123 error="Connection refused"
```
---
## Уровни по слоям
| Слой | DEBUG | INFO | WARNING | ERROR |
|------|-------|------|---------|-------|
| **API** | Параметры запроса | Request обработан | — | 5xx ошибки |
| **Service** | Входные данные | Операция выполнена | Превышен лимит | Ошибка БД |
| **Integration** | Raw ответ провайдера | Успешный вызов | Timeout, retry | Внешний API ошибка |
| **Agent** | Checksum вычислен | Агент выполнен | Версия не совпала | Ошибка выполнения |
---
## Правила
- **Запрещены f-строки в logger.** Только %s (lazy evaluation):
```python
# ПЛОХО:
logger.info(f"User {user_id} logged in")
# ХОРОШО:
logger.info("User %s logged in", user_id)
```
- **Структурированные данные** передавайте как extra:
```python
logger.info("Idea analyzed", extra={"idea_id": idea_id, "duration_ms": duration})
```
---
## Sensitive Data
**Никогда не логировать:**
- Пароли (даже хэш)
- JWT токены
- API keys и секреты
- Email в открытом виде (логировать user_id)
- IP адреса полностью (маскировать: 195.208.*.*)
---
## Конфигурация
```python
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s.%(msecs)03dZ %(levelname)s [%(name)s] %(message)s",
datefmt="%Y-%m-%dT%H:%M:%S",
)
```
---
## [ASK] Вопросы по логированию
- Структурированное логирование (JSON) или текстовое? (JSON — для production)
- Отправлять логи в централизованную систему? (рекомендуется для production)
- Нужен ли audit log для операций с данными? (да, если регуляторные требования)
+91
View File
@@ -0,0 +1,91 @@
# Стандарты документации
---
## Docstrings
**Формат:** Google-style для всех публичных классов, функций, методов.
```python
def calculate_roi(investment: float, return_value: float, years: int = 1) -> float:
"""Calculate Return on Investment.
Args:
investment: Initial investment amount
return_value: Total return after period
years: Investment period in years (default: 1)
Returns:
ROI as a percentage (e.g., 150.0 for 150%)
Raises:
ValueError: If investment is zero or negative
"""
if investment <= 0:
raise ValueError("Investment must be positive")
return ((return_value - investment) / investment) * 100
```
### Когда писать docstrings
- Всегда для публичных классов и методов
- Для сложных приватных методов (более 10 строк)
- Для модулей: краткое описание в начале файла
---
## TODO и FIXME
```python
# TODO(#TASK-42): Реализовать rate limiting
# FIXME(#BUG-7): Некорректный подсчёт при пустом списке
```
---
## README.md
Каждая папка `app/*` должна содержать README.md с кратким описанием:
- Назначение модуля
- Ключевые классы/функции
- Пример использования (если неочевидно)
---
## ADR (Architecture Decision Records)
Каждое архитектурное решение фиксируется в `docs/adr/NNN-title.md`.
ADR нужен когда:
- Выбирается технология (БД, фреймворк, провайдер)
- Меняется архитектура (новый слой, новый паттерн)
- Принимается решение с долгосрочными последствиями
ADR не нужен когда:
- Обычный багфикс
- Косметические изменения
- Выбор имени переменной
---
## CHANGELOG
CHANGELOG — это контракт с пользователем. Каждое изменение, влияющее на работу:
### Для пользователей:
- Новые функции
- Изменения API
- Исправления багов
- Изменения зависимостей
### Для разработчиков:
- Рефакторинг (если влияет на API модуля)
- Изменения конфигурации
- Обновления БД
---
## [ASK] Вопросы по документации
- Генерировать документацию автоматически? (Sphinx, MkDocs — рекомендуется)
- Нужна ли API документация для фронтенд-разработчиков? (да, OpenAPI доступен в /docs)
- Какой формат для диаграмм? (Mermaid — рекомендуется, читается и человеком и ИИ)
+66
View File
@@ -0,0 +1,66 @@
# Управление зависимостями
---
## Формат
**Рекомендуемый:** `requirements.txt`
```
# === Core ===
fastapi==0.115.6
uvicorn[standard]==0.34.0
pydantic==2.10.3
pydantic-settings==2.7.0
# === Database ===
sqlalchemy[asyncio]==2.0.36
aiosqlite==0.20.0 # dev (SQLite)
asyncpg==0.30.0 # prod (PostgreSQL)
alembic==1.14.1
# === Auth ===
python-jose[cryptography]==3.3.0
passlib[bcrypt]==1.7.4
# === AI ===
httpx==0.28.1
pyyaml==6.0.2
# === Tasks (опционально) ===
celery==5.4.0
redis==5.2.1
# === Dev ===
pytest==8.3.4
pytest-asyncio==0.24.0
ruff==0.8.4
```
---
## Правила обновления
| Тип | Когда | Проверка |
|-----|-------|----------|
| **patch** | В любой момент (bugfix, security) | CI passes |
| **minor** | Не чаще 1 раза в спринт | Full regression |
| **major** | Только с полным регрессом | + migration guide |
---
## Аудит зависимостей
Периодически проверять уязвимости:
```bash
pip-audit
safety check
```
---
## [ASK] Вопросы по зависимостям
- `requirements.txt` или `pyproject.toml`? (pyproject.toml — современный стандарт)
- `pip` или `poetry`/`uv`? (uv — быстрее, poetry — управление зависимостями)
- Нужна ли заморозка версий (`pip freeze > requirements-lock.txt`)? (да, для production)
+59
View File
@@ -0,0 +1,59 @@
# Code Review
---
## Обязательность
- Все PR в `main` и `develop` проходят code review
- Минимум 1 апрув от admin/owner
---
## Чеклист ревью
### Безопасность
- [ ] Нет секретов, ключей, паролей в коде
- [ ] Нет чувствительных данных в логах
- [ ] Входные данные проходят Pydantic валидацию
- [ ] Проверены права доступа (RBAC)
### Качество кода
- [ ] Нет сырых Exception в API ответах (заменены на HTTPException)
- [ ] Есть обработка ошибок для внешних вызовов (try/except)
- [ ] Docstrings написаны (Google-style)
- [ ] Аннотации типов проставлены
- [ ] Ruff проходит (0 errors)
- [ ] mypy проходит (0 errors)
### Тесты
- [ ] Есть тесты на новую функциональность
- [ ] Есть smoke-тест на новые endpoint'ы
- [ ] Тесты проходят
### Документация
- [ ] .env.example обновлён (если новая переменная)
- [ ] CHANGELOG обновлён
- [ ] ADR создан (если архитектурное изменение)
---
## Как писать комментарии
```markdown
**Вопрос:** Зачем здесь этот блок? Кажется неиспользуемым.
— Я бы предложил вынести в отдельный метод.
**Предложение:** Этот фрагмент дублируется в 3 местах.
— Давай вынесем в общий хелпер в core/utils.py.
**Замечание (блокирующее):** Здесь пароль попадает в лог.
— Нужно убрать логирование password. См. §11 Sensitive Data Policy.
```
---
## [ASK] Вопросы по ревью
- Использовать GitHub Code Owners? (рекомендуется для больших команд)
- Добавить авто-ревью (агент)? (рекомендуется: AuditAgent проверяет базовые правила)
- Сколько максимум строк на PR? (рекомендуется < 500 строк)
+84
View File
@@ -0,0 +1,84 @@
# Git Flow
---
## Ветки
```
main # Стабильная, production-ready
develop # Интеграция фич
feature/* # Новая функция (ветвится от develop)
hotfix/* # Срочное исправление (ветвится от main)
release/* # Подготовка релиза (ветвится от develop)
```
### Когда какую ветку использовать
| Ситуация | Ветка | Цель |
|----------|-------|------|
| Начало работы над фичой | `feature/idea-analysis` | develop |
| Исправление бага в production | `hotfix/crash-on-empty` | main |
| Подготовка релиза | `release/1.2.0` | main |
| Эксперимент | `experiment/new-auth` | — |
---
## Conventional Commits
```
<тип>[optional scope]: <описание>
[optional body]
[optional footer]
```
### Типы
| Тип | Пример | Влияние на версию |
|-----|--------|-------------------|
| `feat` | `feat: add AI analysis endpoint` | MINOR |
| `fix` | `fix: handle empty idea list` | PATCH |
| `BREAKING` | `feat!: change API response format` | MAJOR |
| `docs` | `docs: update README` | — |
| `refactor` | `refactor: extract IdeaService` | — |
| `test` | `test: add smoke tests for auth` | — |
| `chore` | `chore: update dependencies` | — |
### Примеры
```
feat(api): add POST /ideas/{id}/analyze endpoint
- Celery task for async analysis
- Fallback to direct call if Celery unavailable
- Store results in AgentReport table
Closes #42
```
```
fix: validate email format on registration
BREAKING: removed support for dotless emails
```
---
## Commit Message
```
50 символов: краткое описание (императив, без точки)
72 символа: тело коммита при необходимости.
Можно писать несколько строк.
- Каждый пункт с дефиса
- Описываем ЧТО и ЗАЧЕМ, а не КАК
```
---
## [ASK] Вопросы по Git
- Git Flow или GitHub Flow? (GitHub Flow проще: main + feature/* + PR)
- Нужны ли релизные ветки? (да, если несколько версий в поддержке)
- Squash при merge? (рекомендуется: 1 PR = 1 коммит в develop)
+31
View File
@@ -0,0 +1,31 @@
# Политика хранения данных
---
## Сроки хранения
| Тип данных | Срок | Причина |
|-----------|------|---------|
| System Logs | 90 дней | Отладка, аудит |
| Security Events | 1 год | Регуляторные требования |
| User Data | До удаления + 30 дней | Возможность восстановления |
| Session (JWT) | 24 часа | Безопасность |
| AI Analysis Results | 90 дней | История анализа |
| Agent Reports | 180 дней | Саморазвитие агентов |
| Backlog Tasks | 1 год | Планирование |
| Notifications | 30 дней | Актуальность |
---
## Удаление данных
**Hard delete:** для временных данных (логи, сессии)
**Soft delete:** для пользовательских данных (is_active = False)
---
## [ASK] Вопросы по хранению
- Какие регуляторные требования применимы? (152-ФЗ, GDPR, CCPA)
- Нужна ли архивация вместо удаления? (рекомендуется для audit trail)
- Как часто чистить старые данные? (cron раз в день)
+48
View File
@@ -0,0 +1,48 @@
# Политика миграций БД
---
## Инструмент: Alembic
Миграции управляются через Alembic.
```bash
# Создать миграцию
alembic revision --autogenerate -m "add_users_table"
# Применить
alembic upgrade head
# Откатить
alembic downgrade -1
```
---
## Правила
1. **Одна миграция на одно изменение.** Не смешивать разные изменения в одной миграции.
2. **Обратная совместимость.** Миграция должна иметь downgrade.
3. **Тестирование.** Каждая миграция тестируется (upgrade + downgrade).
4. **Именование:** `{revision}_{action}_{table}.py`
- `a1b2c3d4e5f6_add_content_to_ideas.py`
---
## Названия миграций
```
create_{table}
add_{column}_to_{table}
remove_{column}_from_{table}
add_index_on_{table}_{column}
add_fk_{table}_{column}
```
---
## [ASK] Вопросы по миграциям
- Автоматические миграции на production? (не рекомендуется — только через CI после проверки)
- Data migration (перенос данных) vs schema migration? (data migration = отдельный скрипт)
- Как бекапить БД перед миграцией? (pg_dump / sqlite3 .backup)
+42
View File
@@ -0,0 +1,42 @@
# Жизненный цикл API
---
## Версионирование
API версионируется через URL:
```
/api/v1/ideas # Текущая стабильная
/api/v2/ideas # Будущая версия
```
---
## Жизненный цикл
```
Стабильная (v1) → Deprecation → 410 Gone
```
| Фаза | Длительность | Действие |
|------|-------------|----------|
| **Стабильная** | Неопределённо | Полная поддержка |
| **Deprecation** | 3 месяца после выхода v2 | WARNING в заголовке `Sunset: ...` |
| **Gone** | — | HTTP 410 Gone |
---
## Поддержка
- Одновременно поддерживаются **не более 2 версий**
- Новая версия = новый префикс (`/api/v2/`)
- Старая версия продолжает работать 3 месяца
---
## [ASK] Вопросы по API
- Сколько версий поддерживать одновременно? (рекомендуется 2: текущая + предыдущая)
- Нужна ли HATEOAS? (нет, если фронтенд отдельно)
- Как документировать breaking changes? (CHANGELOG + ADR)
+143
View File
@@ -0,0 +1,143 @@
# Саморазвитие и эволюция проекта
---
## Зачем проекту саморазвитие
Проект, который не развивается, умирает. Но развитие требует ресурсов, которых у команды может не быть. Решение: **агенты автоматизируют развитие.**
1. **Проект живёт дольше команды** — агенты продолжают работу независимо
2. **Автоматизация рутины** — тесты, документация, ревью
3. **Адаптация** — проект сам подстраивается под новые требования
---
## Три уровня саморазвития
### Level 1: Reactive (базовый)
Агенты реагируют на события:
- Pre-commit: AuditAgent проверяет правила
- Push: SecurityAgent проверяет зависимости
- Cron: DocAgent обновляет документацию
**Начинаем с этого уровня.**
### Level 2: Proactive (целевой)
Агенты предлагают улучшения:
- EvolutionAgent анализирует код и предлагает рефакторинг
- ObserverAgent собирает метрики и предлагает оптимизацию
- FixAgent анализирует ошибки и предлагает исправления
**Достигаем к Stage 3 (см. migration-path.md).**
### Level 3: Autonomous (будущее)
Агенты принимают решения:
- Self-healing: авто-откат при росте ошибок
- Auto-versioning: автоматический бамп версий
- Auto-scaling: масштабирование под нагрузку
---
## Ядро агентов (создаются с первого коммита)
4 агента, которые должны жить в проекте всегда:
| Агент | Роль | Триггеры | Без него |
|-------|------|----------|----------|
| **DocAgent** | Пишет документацию | pre-commit, manual | Документация пишется "потом" → никогда |
| **AuditAgent** | Проверяет правила | pre-commit, push, cron | Правила не применяются |
| **EvolutionAgent** | Версионирует агентов | cron, event, manual | Агенты не эволюционируют |
| **SupervisorAgent** | Следит за всеми агентами | cron, event, manual | Экосистема не контролируется |
### Подробнее о каждом
**DocAgent:**
- При каждом коммите проверяет, что документация соответствует коду
- Если находит недокументированный публичный метод — добавляет docstring
- Обновляет ADR при архитектурных изменениях
**AuditAgent:**
- Проверяет каждый коммит на соответствие `docs/00-rules.md`
- Проверяет: стиль кода, наличие тестов, docstrings, .env.example
- Пишет отчёт о нарушениях
**EvolutionAgent:**
- Отслеживает версии всех агентов
- При изменении checksum агента — бампит версию
- При добавлении новой capability — бампит minor
- При breaking change — бампит major
**SupervisorAgent:**
- Регулярно проверяет health всех агентов
- Собирает метрики выполнения (длительность, успешность)
- При падении агента — перезапускает или шлёт алерт
- Формирует сводный отчёт о состоянии экосистемы
---
## Расширение агентов
По мере роста проекта добавляются:
| Агент | Когда | Зачем |
|-------|-------|-------|
| QATesterAgent | Появились тесты | Поддерживать качество тестов |
| FixAgent | Пойман первый баг | Анализировать и исправлять |
| BacklogAgent | Появился техдолг | Управлять задачами |
| SecurityAgent | Перед production | Проверять безопасность |
| SpecAgent | Перед релизом | Управлять версией |
| RolloutAgent | Перед деплоем | Постепенный rollout |
| ObserverAgent | После запуска | Собирать метрики |
| UITestAgent | Есть UI | Визуальное тестирование |
---
## Agent Versioning
Каждый агент версионируется независимо по A.B.C.
**Почему независимо:** агенты изменяются с разной скоростью. DocAgent может меняться каждый день, а SecurityAgent — раз в месяц.
**Как работает:**
1. Агент запускается → вычисляет SHA256 своего файла (`compute_checksum()`)
2. Сравнивает с хранимым checksum
3. Если не совпал → авто-бамп patch + запись в changelog
4. EvolutionAgent анализирует изменения и решает: это minor (новая capability) или major (breaking change)?
**Хранение:** `CHANGELOG/agents/<name>.md`
```markdown
# doc_agent Changelog
<!-- checksum: a1b2c3d4e5f6... -->
## 1.2.0 (2026-05-10)
- Added: поддержка YAML-формата для промптов
## 1.1.3 (2026-05-09)
- Fixed: обработка пустых docstrings
## 1.0.0 (2026-05-01)
- Initial version
```
---
## Триггеры запуска агентов
| Триггер | Когда | Какие агенты |
|---------|-------|-------------|
| `pre_commit` | Перед каждым коммитом | AuditAgent, DocAgent |
| `push` | При пуше в remote | SecurityAgent, BacklogAgent, SpecAgent |
| `tag_creation` | При создании git-тега | RolloutAgent, SpecAgent |
| `cron` | По расписанию (daily) | EvolutionAgent, SupervisorAgent, ObserverAgent |
| `manual` | Вручную из админки | Любой |
| `api` | Через API | Любой |
| `event` | При событии (ошибка, деплой) | FixAgent, RolloutAgent |
---
## [ASK] Вопросы по саморазвитию
- Сколько агентов нужно на старте? (рекомендация: 4 ядерных, остальные по необходимости)
- Как часто запускать EvolutionAgent? (рекомендация: ежедневно по cron)
- Кто пишет агентов? (рекомендация: команда, начиная с самого простого — DocAgent)
- Нужен ли SupervisorAgent на старте? (да — замкнутый круг: агенты без контроля = хаос)
+50
View File
@@ -0,0 +1,50 @@
# ADR-{NNN}: {Название решения}
**Статус:** {черновик | принято | отклонено | заменено}
**Дата:** {YYYY-MM-DD}
---
## Контекст
{Опишите проблему: что заставило принять решение, какие требования, какая мотивация}
## Рассматривались
- **Вариант А**: {описание}
- Плюсы: {список}
- Минусы: {список}
- **Вариант Б**: {описание}
- Плюсы: {список}
- Минусы: {список}
- **Вариант В** (если есть): {описание}
- Плюсы: {список}
- Минусы: {список}
## Решение
{Выбранный вариант} — {краткое обоснование почему}
## Последствия
### Положительные
- {пункт}
- {пункт}
### Отрицательные
- {пункт}
- {пункт}
### Миграция
{Что нужно сделать чтобы перейти на это решение}
## Ответственный
**Decision maker:** {роль: Owner / Architect / Team}
**Review date:** {когда пересмотреть: дата или условие}
---
## Связанные ADR
- ADR-{NNN}: {Название}
+64
View File
@@ -0,0 +1,64 @@
# Управление промптами агентов
---
## Принцип
Промпты — это код. Они версионируются, хранятся в репозитории и проходят code review.
Никаких hardcoded промптов в Python-коде.
---
## Где хранить
### Вариант A: YAML (рекомендован)
`docs/agent_prompts.yaml`
```yaml
coordinator:
system_prompt: "Ты — координатор. Твоя задача..."
provider: yandex_gpt
temperature: 0.7
max_tokens: 2000
```
**Плюсы:** Простота редактирования, структурированность, легко парсить.
**Минусы:** Сложные промпты с примерами неудобно читать в YAML.
### Вариант B: Markdown
`docs/specs/agents/coordinator.md`
```markdown
## Prompt Template
```
Ты — координатор. Твоя задача...
```
```
**Плюсы:** Читаемость, поддержка форматирования, примеры.
**Минусы:** Сложнее парсить, нет структуры.
### Рекомендация
**YAML для настроек + MD для детальных спецификаций.**
`PromptLoader` пробует YAML, если не нашёл — падает на MD.
---
## Структура YAML
```yaml
coordinator:
system_prompt: "текст промпта"
provider: "yandex_gpt" # какой провайдер
temperature: 0.7 # креативность (0.0-1.0)
max_tokens: 2000 # макс. длина ответа
model: "yandexgpt/latest" # конкретная модель (опционально)
```
---
## [ASK]
- Какой формат выбрать? (рекомендация: YAML для быстрых промптов, MD для сложных)
- Нужна ли валидация промптов? (да, проверять что все placeholder'ы заполнены)
- Кто редактирует промпты? (разработчики + AI-агенты через EvolutionAgent)
+61
View File
@@ -0,0 +1,61 @@
# Паттерны промптов
---
## 1. System + User разделение
```python
system_prompt = "Ты — бизнес-аналитик. Анализируй идеи."
user_prompt = f"Название: {idea.title}\nОписание: {idea.content}"
# Формирование:
full_prompt = f"{system_prompt}\n\n{user_prompt}"
```
**Используется:** AIProvider.format_prompt()
---
## 2. Structured output
```python
system_prompt = """
Ты — финансовый консультант.
Ответ верни ТОЛЬКО в формате JSON:
{
"roi": число,
"risk_level": "low|medium|high",
"recommendations": [строка, ...]
}
"""
```
---
## 3. Few-shot (примеры)
```python
system_prompt = """
Ты — UI-дизайнер. Анализируй интерфейс.
Пример хорошего анализа:
Интерфейс: Экран входа
Проблема: Кнопка "Забыли пароль" не видна
Решение: Переместить под форму входа
Рекомендация: Высокий приоритет
Теперь проанализируй:
"""
```
---
## Параметры
| Параметр | Значение | Когда менять |
|----------|----------|-------------|
| `temperature: 0.1-0.3` | Низкая креативность | Юридические, финансовые промпты |
| `temperature: 0.5-0.7` | Средняя | Стандартный анализ |
| `temperature: 0.8-1.0` | Высокая | Мозговой штурм, креатив |
| `max_tokens: 500` | Короткий ответ | Классификация |
| `max_tokens: 4000` | Длинный ответ | Детальный анализ |
+103
View File
@@ -0,0 +1,103 @@
# Хранение и загрузка промптов
---
## Загрузчик (PromptLoader)
```python
from pathlib import Path
import yaml, re
AGENT_SPECS_DIR = Path("docs/specs/agents")
AGENT_PROMPTS_YAML = Path("docs/agent_prompts.yaml")
def get_prompt_config(role: str) -> dict | None:
"""Get prompt config for a role."""
# 1. Пробуем YAML
config = _load_from_yaml(role)
if config:
return config
# 2. Пробуем MD
return _load_from_spec(role)
def _load_from_yaml(role: str) -> dict | None:
"""Load from docs/agent_prompts.yaml."""
if not AGENT_PROMPTS_YAML.exists():
return None
data = yaml.safe_load(AGENT_PROMPTS_YAML.read_text(encoding="utf-8"))
return data.get(role) if data else None
def _load_from_spec(role: str) -> dict | None:
"""Load from docs/specs/agents/<role>.md."""
spec_path = AGENT_SPECS_DIR / f"{role}.md"
if not spec_path.exists():
return None
content = spec_path.read_text(encoding="utf-8")
match = re.search(r"## Prompt Template\n+```\n(.+?)\n```", content, re.DOTALL)
if not match:
return None
return {
"system_prompt": match.group(1).strip(),
"provider": "yandex_gpt",
"temperature": 0.7,
"max_tokens": 2000,
}
```
---
## Пример YAML-файла
`docs/agent_prompts.yaml`
```yaml
coordinator:
system_prompt: "Ты — координатор..."
provider: yandex_gpt
temperature: 0.7
max_tokens: 2000
business_analyst:
system_prompt: "Ты — бизнес-аналитик..."
provider: yandex_gpt
temperature: 0.5
max_tokens: 3000
legal_expert:
system_prompt: "Ты — юрист..."
provider: gigachat # Для юридических вопросов
temperature: 0.3
max_tokens: 3000
```
---
## Пример MD-файла
`docs/specs/agents/business_analyst.md`
```markdown
# Бизнес-аналитик
**Провайдер:** Yandex GPT
**Температура:** 0.5
**Макс. токенов:** 3000
## Prompt Template
```
Ты — бизнес-аналитик.
Проанализируй идею и оцени:
1. Целевую аудиторию
2. ROI
3. Сроки реализации
...
```
```
---
## [ASK]
- Какой формат использовать по умолчанию? (рекомендация: YAML + MD fallback)
- Нужна ли валидация placeholder'ов в промптах? (да, {...} должны быть заменены)
- Нужна ли версионирование промптов? (да, через git — каждый промпт MD/YAML файл)
@@ -0,0 +1,19 @@
# {Role Name}
**Провайдер:** {yandex_gpt | gigachat}
**Температура:** {0.1-1.0}
**Макс. токенов:** {500-4000}
## Описание
{Краткое описание роли AI-агента. Что делает, какие вопросы решает.}
## Prompt Template
```text
Ты — {role_name}. {описание}.
{инструкции}
{формат ответа}
```
@@ -0,0 +1,14 @@
# Шаблон промпта в YAML
# Используйте как основу для нового AI-агента
role_name:
system_prompt: |
Ты — {role_name}. {описание роли}.
{инструкции}
{формат ответа}
provider: yandex_gpt # или gigachat
temperature: 0.7 # 0.1-1.0
max_tokens: 2000 # макс. длина
model: "" # опционально: конкретная модель
@@ -0,0 +1,61 @@
# Обзор системных агентов
---
## Что такое системный агент
Системный агент — это программа, которая автоматизирует поддержку и развитие проекта.
В отличие от AI-агента (который анализирует пользовательские данные), системный агент работает **над проектом**: пишет документацию, проверяет правила, версионирует код.
---
## Когда внедрять агентов
**С первого коммита.** 4 ядерных агента создаются сразу.
Остальные — по мере возникновения потребности.
---
## Отличие системного агента от AI-агента
| Характеристика | Системный агент | AI-агент |
|---------------|-----------------|-----------|
| Что делает | Поддерживает проект | Анализирует данные пользователя |
| Кто запускает | Триггеры (pre-commit, cron) | Пользователь (через UI) |
| Результат | Чистый код, docs, версии | Анализ идеи, рекомендации |
| Пример | DocAgent пишет docstrings | Координатор анализирует идею |
| Версионируется | Да (A.B.C независимо) | Нет |
---
## Ядро (4 агента, обязательны)
| # | Агент | Роль | Триггеры |
|---|-------|------|----------|
| 1 | **DocAgent** | Пишет документацию | pre-commit, manual |
| 2 | **AuditAgent** | Проверяет правила | pre-commit, push, cron |
| 3 | **EvolutionAgent** | Версионирует агентов | cron, event, manual |
| 4 | **SupervisorAgent** | Следит за всеми агентами | cron, event, manual |
---
## Расширение (по необходимости)
| # | Агент | Когда добавлять |
|---|-------|----------------|
| 5 | **QATesterAgent** | Появились тесты |
| 6 | **FixAgent** | Пойман первый баг |
| 7 | **BacklogAgent** | Появился техдолг |
| 8 | **SecurityAgent** | Перед production |
| 9 | **SpecAgent** | Перед релизом |
| 10 | **RolloutAgent** | Перед деплоем |
| 11 | **ObserverAgent** | После запуска |
| 12 | **UITestAgent** | Есть UI |
---
## [ASK] Вопросы по агентам
- Сколько агентов нужно сейчас? (рекомендация: 4 ядерных, потом по необходимости)
- Есть ли ресурс на разработку агентов? (DocAgent ≈ 2 часа, AuditAgent ≈ 4 часа)
- Кто будет поддерживать агентов? (те же разработчики)
@@ -0,0 +1,107 @@
# Архитектура агентов
---
## BaseAgent
Все агенты наследуются от `BaseAgent`:
```python
class BaseAgent(ABC):
name: str # Уникальное имя агента
version: str = "1.0.0" # Текущая версия
description: str = "" # Описание для registry
triggers: list[AgentTrigger] # Когда запускается
async def run(self, context: dict | None = None) -> AgentResult:
"""Выполнить задачу агента."""
async def health_check(self) -> bool:
"""Проверить что агент работоспособен."""
def compute_checksum(self) -> str:
"""SHA256 от __file__ агента."""
def bump_version(self, version_type: str = "patch") -> str:
"""Увеличить версию (major/minor/patch)."""
```
---
## Жизненный цикл
```
IDLE → RUNNING → [DONE | ERROR] → IDLE
↘ OFFLINE
```
1. Агент запускается (триггер или вручную)
2. Статус → RUNNING
3. Выполняется `run(context)`
4. Статус → IDLE (успех) или ERROR (ошибка)
5. Результат сохраняется в AgentReport
---
## AgentResult
```python
class AgentResult:
success: bool # Успешно ли выполнен
message: str # Сообщение для лога
data: dict[str, Any] # Произвольные данные результата
errors: list[str] # Список ошибок
duration_ms: int # Время выполнения
timestamp: datetime # Когда выполнен
```
---
## AgentRegistry
Регистрация всех агентов в едином реестре:
```python
class AgentRegistry:
def register(self, agent: BaseAgent): ...
def get(self, name: str) -> BaseAgent | None: ...
def list_agents(self) -> list[dict]: ...
async def run_agent(self, name: str, context=None) -> AgentResult: ...
async def run_all(self, context=None) -> dict[str, AgentResult]: ...
```
---
## Триггеры
| Триггер | Когда | Пример |
|---------|-------|--------|
| `MANUAL` | Вручную из админки | Запуск DocAgent |
| `PRE_COMMIT` | Перед git commit | AuditAgent проверяет правила |
| `PUSH` | git push | SecurityAgent проверяет зависимости |
| `TAG_CREATION` | git tag | SpecAgent обновляет CHANGELOG |
| `CRON` | По расписанию | EvolutionAgent ежедневный анализ |
| `API` | Через API-endpoint | Запуск из админ-панели |
| `EVENT` | Событие в системе | FixAgent при ошибке |
---
## Хранение промптов
Промпты агентов хранятся в `docs/agent_prompts.yaml` или в отдельных MD-файлах в `docs/specs/agents/`.
Загрузка через `PromptLoader`:
```python
def get_prompt_config(role: str) -> dict | None:
# 1. Попробовать YAML (docs/agent_prompts.yaml)
# 2. Не найдено → загрузить из MD (docs/specs/agents/<role>.md)
# 3. Не найдено → None
```
---
## [ASK] Вопросы по архитектуре
- Нужен ли AgentRegistry? (да, обязателен для SupervisorAgent)
- Хранить состояние агентов в БД или в памяти? (в БД для отказоустойчивости)
- Как передавать контекст агенту? (через `context: dict` — гибко, но без типизации)
@@ -0,0 +1,81 @@
# Версионирование агентов
---
## Принцип
Каждый агент версионируется **независимо** от проекта и от других агентов по A.B.C (SemVer).
---
## Правила бампа
| Компонент | Когда | Кто |
|-----------|-------|-----|
| **A (major)** | Breaking change в публичном интерфейсе (сигнатура `run()`, публичные методы) | EvolutionAgent |
| **B (minor)** | Новая capability (новый метод, новый prompt, новая роль) | EvolutionAgent |
| **C (patch)** | Внутренние правки без изменения поведения | Сам агент (авто) |
---
## Механика
```
Каждый Agent.run()
→ compute_checksum() — SHA256 от __file__ агента
→ сравнивает с AgentConfig.checksum в БД
→ не совпал → bump_version("patch") → запись в changelog → обновление БД
→ совпал → ничего
EvolutionAgent
→ анализирует код агента
→ нашёл новую capability → bump_version("minor")
→ нашёл breaking change → bump_version("major")
```
---
## Хранение checksum
Checksum хранится в двух местах:
1. **В БД** (`AgentConfig.checksum`) — для быстрого сравнения
2. **В changelog файле** (`<!-- checksum: ... -->`) — для git history
---
## Changelog
Файл: `CHANGELOG/agents/<agent_name>.md`
```markdown
# audit_agent Changelog
<!-- checksum: a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890 -->
## 1.0.2 (2026-05-10)
- Fixed: ruff output parsing for Windows paths
## 1.0.1 (2026-05-09)
- Fixed: missing error handling in health_check
## 1.0.0 (2026-05-08)
- Initial version
```
---
## Разделение ответственности
| Аспект | Владелец | Где хранится |
|--------|----------|--------------|
| Версия проекта | SpecAgent / человек | `project.yaml`, `CHANGELOG/v*.md` |
| Версия агента | EvolutionAgent | `AgentConfig.version` (БД) |
| Changelog проекта | SpecAgent / человек | `CHANGELOG/v*.md` |
| Changelog агента | EvolutionAgent | `CHANGELOG/agents/<name>.md` |
---
## [ASK] Вопросы по версионированию
- Версионировать агентов с первого коммита? (да — привычка, потом не внедрить)
- Допустим ли ручной бамп версии? (да, EvolutionAgent — автоматизация, но человек может и вручную)
- Нужна ли блокировка бампа (если checksum не совпал — не запускать)? (нет, только предупреждение)
@@ -0,0 +1,34 @@
# Шаблон changelog агента
Используйте для инициализации changelog нового агента.
Формат файла: `CHANGELOG/agents/{agent_name}.md`
```markdown
# {agent_name} Changelog
<!-- checksum: {sha256_hash} -->
## 1.0.0 ({date})
- Initial version
```
## Пример
```markdown
# doc_agent Changelog
<!-- checksum: a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890 -->
## 1.2.1 (2026-05-11)
- Fixed: update README on file rename
- Fixed: handle empty docstrings gracefully
## 1.2.0 (2026-05-10)
- Added: YAML prompt loading support
- Added: cross-reference validation
## 1.1.0 (2026-05-09)
- Added: auto-generate README for new modules
## 1.0.0 (2026-05-01)
- Initial version
```
@@ -0,0 +1,69 @@
# Шаблон кода агента
Используйте этот шаблон для создания нового системного агента.
```python
"""Agent: {name}{description}."""
from datetime import datetime, timezone
from typing import Any
from app.agents.base import BaseAgent, AgentResult, AgentTrigger
class {Name}Agent(BaseAgent):
"""{Description} agent.
Triggers: {triggers}
"""
name = "{name}"
version = "1.0.0"
description = "{description}"
triggers = [AgentTrigger.MANUAL]
async def run(self, context: dict[str, Any] | None = None) -> AgentResult:
"""Execute agent task.
Args:
context: Optional context with execution parameters
Returns:
AgentResult with execution outcome
"""
start = datetime.now(timezone.utc)
errors: list[str] = []
data: dict[str, Any] = {}
try:
# === AGENT LOGIC HERE ===
# 1. Do the work
# 2. Collect results
# 3. Handle errors
pass
except Exception as e:
errors.append(str(e))
duration = int((datetime.now(timezone.utc) - start).total_seconds() * 1000)
result = AgentResult(
success=len(errors) == 0,
message=f"{self.name} completed with {len(errors)} errors",
data=data,
errors=errors,
duration_ms=duration,
)
# Auto-version check
new_version = await self._check_version()
if new_version:
result.data["version_bumped"] = True
result.data["new_version"] = new_version
return result
async def health_check(self) -> bool:
"""Check if agent can execute."""
return True
```
+117
View File
@@ -0,0 +1,117 @@
# Стратегия тестирования API
---
## 9 обязательных сценариев для каждого endpoint
### 1. Missing field → 422
```python
async def test_create_missing_field(async_client):
response = await async_client.post("/api/v1/ideas", json={})
assert response.status_code == 422
```
### 2. Wrong type → 422
```python
async def test_create_wrong_type(async_client):
response = await async_client.post("/api/v1/ideas", json={
"title": 123, # Должна быть строка
"content": "test",
})
assert response.status_code == 422
```
### 3. Expired/invalid token → 401
```python
async def test_unauthorized(async_client):
response = await async_client.get("/api/v1/ideas", headers={
"Authorization": "Bearer invalid_token"
})
assert response.status_code == 401
```
### 4. Wrong permissions → 403
```python
async def test_forbidden(async_client, user_token):
response = await async_client.get(
"/api/v1/admin/users",
headers={"Authorization": f"Bearer {user_token}"},
)
assert response.status_code == 403
```
### 5. Not found → 404
```python
async def test_not_found(async_client, user_token):
response = await async_client.get(
"/api/v1/ideas/nonexistent",
headers={"Authorization": f"Bearer {user_token}"},
)
assert response.status_code == 404
```
### 6. Conflict → 409
```python
async def test_duplicate_email(async_client):
# Создать первого пользователя
await async_client.post("/api/v1/auth/register", json={...})
# Попробовать создать с тем же email
response = await async_client.post("/api/v1/auth/register", json={...})
assert response.status_code == 409
```
### 7. Success → 200/201
```python
async def test_create_success(async_client, user_token):
response = await async_client.post(
"/api/v1/ideas",
json={"title": "Test", "content": "Content"},
headers={"Authorization": f"Bearer {user_token}"},
)
assert response.status_code == 201
data = response.json()
assert data["title"] == "Test"
```
### 8. Rate limit → 429 (если реализован)
```python
async def test_rate_limit(async_client, user_token):
for _ in range(100):
await async_client.get("/api/v1/ideas", headers={...})
response = await async_client.get("/api/v1/ideas", headers={...})
assert response.status_code == 429
```
### 9. Idempotency → тот же результат при повторе
```python
async def test_idempotent_delete(async_client, user_token, idea_id):
response1 = await async_client.delete(f"/api/v1/ideas/{idea_id}", headers={...})
response2 = await async_client.delete(f"/api/v1/ideas/{idea_id}", headers={...})
assert response1.status_code == 204
assert response2.status_code == 404 # Уже удалено
```
---
## Структура тестов
```
tests/
├── conftest.py # Глобальные фикстуры
├── unit/ # изолированные тесты
├── integration/
│ ├── conftest.py # Фикстуры для API тестов
│ ├── test_auth.py # 9 сценариев для auth
│ ├── test_ideas.py # 9 сценариев для ideas
│ └── test_admin.py # 9 сценариев для admin
└── smoke/
└── test_health.py # smoke-тесты
```
---
## [ASK]
- Все ли 9 сценариев нужны для каждого endpoint? (рекомендация: да, но можно начать с успех + not found + unauthorized)
- Нужны ли тесты на idempotency? (да, для DELETE и PATCH)
- Как часто прогонять? (при каждом PR — обязательно, при каждом push — желательно)
+19
View File
@@ -0,0 +1,19 @@
# Pre-commit чеклист
Перед каждым коммитом:
- [ ] `ruff check .` — 0 errors
- [ ] `ruff format --check .` — форматирование в порядке
- [ ] `mypy app/` — 0 errors (если настроен)
- [ ] `pytest` — все тесты зелёные
- [ ] CHANGELOG обновлён (если изменение влияет на пользователя)
- [ ] .env.example обновлён (если новая переменная)
- [ ] Нет секретов и токенов в коде (grep на api_key, secret, password)
- [ ] Нет TODO/FIXME без тикета
- [ ] Миграция написана (если менялась БД)
- [ ] Docstrings написаны (для новых публичных методов)
**Автоматически (pre-commit hooks):**
- `ruff` — линтинг и форматирование
- `trailing-whitespace` — удаление лишних пробелов
- `check-added-large-files` — проверка больших файлов
@@ -0,0 +1,25 @@
# Code Review чеклист
## Безопасность
- [ ] Нет секретов, ключей, паролей в коде
- [ ] Нет чувствительных данных в логах
- [ ] Входные данные проходят Pydantic валидацию
- [ ] Проверены права доступа (RBAC)
## Качество
- [ ] Нет сырых Exception в API ответах
- [ ] Есть обработка ошибок для внешних вызовов
- [ ] Docstrings написаны (Google-style)
- [ ] Аннотации типов проставлены
- [ ] Ruff проходит (0 errors)
- [ ] mypy проходит (0 errors)
## Тесты
- [ ] Есть тесты на новую функциональность
- [ ] Есть smoke-тест на новые endpoint'ы
- [ ] Тесты проходят
## Документация
- [ ] .env.example обновлён
- [ ] CHANGELOG обновлён
- [ ] ADR создан (если архитектурное изменение)
+28
View File
@@ -0,0 +1,28 @@
# Pre-deploy чеклист
## База данных
- [ ] Миграции написаны и протестированы (upgrade + downgrade)
- [ ] Резервная копия БД создана
- [ ] Проверено что данные не потеряются
## Конфигурация
- [ ] .env настроен для production
- [ ] Все секреты установлены (не дефолтные)
- [ ] CORS настроен на реальный домен
- [ ] LOG_LEVEL = WARNING (не DEBUG)
- [ ] DEBUG = False
## Инфраструктура
- [ ] SSL сертификаты (Let's Encrypt)
- [ ] Nginx настроен (или аналог)
- [ ] systemd unit создан (если без Docker)
## CI/CD
- [ ] CI проходит (lint + test)
- [ ] CD скопировал артефакты на сервер
- [ ] Health check проходит после деплоя
## Мониторинг
- [ ] Health endpoint работает
- [ ] Логи пишутся в файл
- [ ] Алерты настроены (если нужны)
@@ -0,0 +1,28 @@
# Incident Response чеклист
## Immediate (первые 5 минут)
1. [ ] Определить severity
- **Critical**: сервис недоступен, данные потеряны
- **Major**: функциональность severely impacted
- **Minor**: не влияет на пользователей
2. [ ] Остановить кровотечение
- Rollback до последней стабильной версии
- Отключить проблемную функциональность
- Переключить на fallback
3. [ ] Уведомить команду
## Investigation (15-30 минут)
4. [ ] Проверить логи (app, nginx, system)
5. [ ] Проверить метрики (когда началось, что изменилось)
6. [ ] Проверить последний деплой / изменения
7. [ ] Воспроизвести проблему (если возможно)
## Resolution
8. [ ] Применить исправление
9. [ ] Проверить что сервис восстановлен
10. [ ] Уведомить о восстановлении
## Postmortem (в течение 24 часов)
11. [ ] Написать postmortem
12. [ ] Создать задачу на предотвращение
13. [ ] Добавить мониторинг / тест на этот сценарий
@@ -0,0 +1,28 @@
# Definition of Done
Задача считается выполненной только когда ВСЕ пункты отмечены:
## Код
- [ ] Код написан (соответствует стилю из 00-rules.md §1)
- [ ] Линт проходит (ruff — 0 errors)
- [ ] Форматирование соблюдено (ruff format)
## Тесты
- [ ] Тесты написаны (минимум 1 smoke-тест)
- [ ] Тесты проходят (pytest — green)
- [ ] Покрытие новых строк > 80%
## Документация
- [ ] Docstrings написаны (Google-style)
- [ ] .env.example обновлён (если новая переменная)
- [ ] CHANGELOG обновлён (если изменение влияет на API/пользователя)
- [ ] ADR создан (если архитектурное изменение)
## Инфраструктура
- [ ] Миграция написана (если менялась БД)
- [ ] Миграция протестирована (upgrade + downgrade)
## Процесс
- [ ] PR создан
- [ ] Code review пройден (минимум 1 апрув)
- [ ] Ветка смержена в develop/main
+57
View File
@@ -0,0 +1,57 @@
# Decision Log
Лёгкий трекер каждодневных решений.
В отличие от ADR (фиксируют архитектуру), Decision Log фиксирует **контекст** — почему мы сделали тот или иной выбор.
Через 3 месяца никто не вспомнит "почему мы взяли SQLite", а Decision Log напомнит.
---
## Формат записи
```markdown
## {YYYY-MM-DD}: {Решение}
**Контекст:** {Почему встал вопрос, какие были ограничения}
**Решение:** {Что выбрали}
**Альтернативы:** {Что рассматривали, почему не взяли}
**Кто:** {Кто принял решение}
**Статус:** {действует | пересмотреть через N | заменено}
```
---
## Пример
```markdown
## 2026-05-10: Выбрали SQLite для разработки
**Контекст:** У команды Windows, PostgreSQL требует установки и настройки.
На старте важна скорость — поднять проект за 5 минут, а не за час.
**Решение:** SQLite + aiosqlite для локальной разработки.
PostgreSQL — только на production.
**Альтернативы:**
- PostgreSQL + Docker — работает, но Docker не у всех
- PostgreSQL native — адская установка на Windows
**Кто:** @owner
**Статус:** действует. Пересмотреть перед production.
```
---
## Когда создавать запись
- Выбрали технологию (БД, провайдер, фреймворк)
- Отложили функциональность (не делаем OAuth сейчас)
- Изменили подход (было sessions, стало JWT)
- Архитектурный компромисс (знаем что не идеально, но время поджимает)
---
## [ASK]
- Вести Decision Log в Markdown или в YAML? (Markdown — читаемость)
- Хранить в репозитории или в Notion/wiki? (в репозитории — git history + доступность)
- Кто заполняет? (тот, кто принял решение, сразу)
+60
View File
@@ -0,0 +1,60 @@
# Выбор базы данных
---
## Decision Tree
```mermaid
graph TD
A[Какую БД?] --> B{Многопользовательская?}
B -->|Нет / прототип| C[SQLite]
B -->|Да| D{Нужен JSONB?}
D -->|Да| E[PostgreSQL]
D -->|Нет| F{Нужен full-text search?}
F -->|Да| E
F -->|Нет| G[SQLite / PostgreSQL]
```
---
## Варианты
### SQLite
| | |
|---|---|
| **Когда** | Прототип, dev, однопользовательское |
| **Плюсы** | Не требует установки, встроенная, ноль конфигурации |
| **Минусы** | Нет конкурентной записи, нет JSONB, нет ARRAY, нет полнотекстового поиска |
| **Драйвер** | aiosqlite |
### PostgreSQL
| | |
|---|---|
| **Когда** | Production, многопользовательское, аналитика |
| **Плюсы** | ACID, JSONB, ARRAY, full-text search, масштабирование |
| **Минусы** | Требует установки, настройки, памяти |
| **Драйвер** | asyncpg |
---
## Рекомендация
**SQLite для разработки, PostgreSQL для production.**
Обе БД поддерживаются через SQLAlchemy с минимальными отличиями в моделях.
### Что нужно для портабельности
```python
# Вместо PostgreSQL-specific типов используем универсальные:
UUID String(36)
JSONB JSON
ARRAY JSON
```
---
## [ASK]
- Какая БД нужна на старте? (рекомендация: SQLite)
- Когда переходить на PostgreSQL? (перед production)
- Нужна ли поддержка обеих БД одновременно? (желательно — unit-тесты на SQLite быстрее)
+59
View File
@@ -0,0 +1,59 @@
# Выбор схемы аутентификации
---
## Decision Tree
```mermaid
graph TD
A[Схема auth?] --> B{Нужен вход через соцсети?}
B -->|Нет| C[Email + пароль]
B -->|Да| D{OAuth2}
D --> E[Выбрать провайдеров]
C --> F[Выбрать JWT или Session]
F -->|SPA/PWA| G[JWT + refresh token]
F -->|SSR| H[Session + cookie]
```
---
## Варианты
### Email + пароль
| | |
|---|---|
| **Плюсы** | Простота, не зависит от third-party, полный контроль |
| **Минусы** | Пользователь должен помнить пароль, риск утечки |
| **Хэширование** | bcrypt через passlib |
### OAuth2 (Яндекс, Google, GitHub, Apple)
| | |
|---|---|
| **Плюсы** | Удобство для пользователя, нет паролей на нашей стороне |
| **Минусы** | Зависимость от провайдера, нужны client_id/secret, нужен публичный URL для callback |
| **Схема** | Один пользователь = один провайдер (нельзя привязать два) |
### JWT vs Session
| | JWT | Session |
|---|---|---|
| **Хранение** | На клиенте (localStorage) | На сервере (Redis/БД) |
| **Масштабирование** | Не нужна общая session storage | Нужен Redis |
| **Отзыв токена** | Сложно (до expire) | Мгновенно |
| **SPA/PWA** | Идеально | Сложнее |
---
## Рекомендация
**Email + пароль + JWT** для старта.
OAuth2 добавить перед production (если нужен).
JWT с refresh token для SPA/PWA, session для SSR.
---
## [ASK]
- Нужен ли вход через соцсети? (рекомендация: Яндекс для РФ, Google для международных)
- JWT или Session? (рекомендация: JWT + refresh token)
- Сколько провайдеров OAuth? (рекомендация: 1-2, не больше)
@@ -0,0 +1,91 @@
# Интеграция AI
---
## Паттерн: FallbackChain
```
Запрос → Provider 1 → Успех → результат
Ошибка → Provider 2 → Успех → результат
Ошибка → Fallback результат
```
### Реализация
```python
class FallbackChain:
def __init__(self, providers: list[AIProvider], max_retries: int = 2):
self.providers = providers
self.max_retries = max_retries
async def analyze(self, prompt: str, **kwargs) -> AIResult:
last_error = None
for provider in self.providers:
for attempt in range(self.max_retries + 1):
try:
result = await provider.analyze(prompt, **kwargs)
if result.success:
return result
last_error = result
except Exception as e:
last_error = AIResult(success=False, error=str(e))
if attempt < self.max_retries:
await asyncio.sleep(2 if attempt == 0 else 5)
return last_error or AIResult(success=False, error="All providers failed")
```
---
## Таймауты и ретраи (следуя §12 правил)
```
1. Попытка (timeout: 10s)
2. Успех → return
3. Таймаут → retry 1 (через 2s)
4. Таймаут → retry 2 (через 5s)
5. 4xx → WARNING, return fallback
6. 5xx → ERROR, retry → fallback
7. Все retry исчерпаны → return fallback
```
---
## Хранение промптов
**Рекомендуемый формат:** YAML (`docs/agent_prompts.yaml`)
```yaml
coordinator:
system_prompt: "Ты — координатор проекта..."
provider: yandex_gpt
temperature: 0.7
max_tokens: 2000
business_analyst:
system_prompt: "Ты — бизнес-аналитик..."
provider: yandex_gpt
temperature: 0.5
max_tokens: 3000
```
**Альтернатива:** MD-файлы в `docs/specs/agents/` (для детальных спецификаций)
---
## Провайдеры
| Провайдер | Когда | Аутентификация |
|-----------|-------|---------------|
| Yandex GPT | РФ, хорошая русская речь | IAM token или API key |
| GigaChat (Sber) | РФ, юридические/финансовые темы | OAuth client credentials |
| OpenAI | Международные проекты | API key |
| Локальная модель | Оффлайн, конфиденциальность | Не требуется |
---
## [ASK]
- Какие AI провайдеры нужны? (рекомендация: минимум 2 для fallback)
- Нужен ли fallback chain? (да — обязателен для отказоустойчивости)
- Где хранить промпты? (рекомендация: YAML — простота редактирования)
- Нужен ли локальный AI? (да, если конфиденциальность критична)
+76
View File
@@ -0,0 +1,76 @@
# Выбор фронтенда
---
## Decision Tree
```mermaid
graph TD
A[Фронтенд?] --> B{SPA или SSR?}
B -->|SPA| C[React + Vite + TS]
B -->|SSR| D[Next.js]
C --> E{Нужен оффлайн?}
E -->|Да| F[PWA + vite-plugin-pwa]
E -->|Нет| G[Без PWA]
```
---
## Варианты
### React + Vite + TypeScript
| | |
|---|---|
| **Когда** | SPA, PWA, мобильное приложение |
| **Плюсы** | Популярный, большая экосистема, Vite быстрый, PWA-ready |
| **Минусы** | SPA — медленный первый заход (но PWA решает) |
### Next.js
| | |
|---|---|
| **Когда** | SSR, SEO, контентный сайт |
| **Плюсы** | SSR, SEO, App Router |
| **Минусы** | Сложнее деплой, не подходит для PWA |
---
## Стили
| Решение | Когда |
|---------|-------|
| **Tailwind CSS** | Всегда (рекомендовано) |
| CSS Modules | Если Tailwind не подходит |
| CSS-in-JS | Не рекомендуется (производительность) |
---
## Состояние
| Решение | Когда |
|---------|-------|
| **React Context + hooks** | Маленькое приложение (< 5 страниц) |
| **zustand** | Среднее приложение (рекомендовано) |
| **RTK** | Большое приложение с множеством запросов |
---
## PWA
**Когда нужен:**
- Приложение должно работать оффлайн
- Пользователи на мобильных устройствах
- Нужно push-уведомления
**Технологии:**
- `vite-plugin-pwa` — генерация service worker
- `manifest.json` — установка на домашний экран
- IndexedDB — оффлайн-хранение
---
## [ASK]
- Нужен ли фронтенд вообще? (API-first или full-stack?)
- SPA или SSR? (SPA+PWA для приложений, SSR для контента)
- Нужна ли PWA? (да, если мобильные пользователи и оффлайн)
- Какой Router? (react-router-dom — стандарт)
+82
View File
@@ -0,0 +1,82 @@
# Стратегия деплоя
---
## Decision Tree
```mermaid
graph TD
A[Как деплоить?] --> B{Один сервер?}
B -->|Да| C[Docker-compose]
B -->|Нет| D{Нужна оркестрация?}
D -->|Да| E[Kubernetes]
D -->|Нет| F[Docker-compose + несколько серверов]
C --> G{VPS или облако?}
G -->|VPS| H[Ubuntu + systemd]
G -->|Облако| I[Docker + cloud provider]
```
---
## Варианты
### Docker-compose (рекомендован для старта)
```yaml
services:
app:
build: .
ports: ["8020:8020"]
env_file: .env
db:
image: postgres:14
volumes: ["pgdata:/var/lib/postgresql/data"]
redis:
image: redis:7
worker:
build: .
command: celery -A app.tasks worker -l info
```
### Systemd (без Docker, VPS)
```ini
[Unit]
Description=VoIdea API
[Service]
ExecStart=/home/voidea/venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8020
WorkingDirectory=/home/voidea
Restart=always
[Install]
WantedBy=multi-user.target
```
---
## CI/CD
**Рекомендуется:** GitHub Actions
```yaml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- run: pip install -r requirements.txt
- run: ruff check
- run: pytest
```
---
## [ASK]
- Docker или без Docker? (Docker для воспроизводимости)
- VPS или облако? (VPS дешевле, облако масштабируемее)
- CI/CD какой? (GitHub Actions — бесплатно для публичных репозиториев)
- Нужен ли staging? (да, перед production)
+49
View File
@@ -0,0 +1,49 @@
# Мониторинг и алертинг
---
## Базовый мониторинг (нужен всегда)
### Health endpoints
```python
GET /health {"status": "healthy", "version": "1.0.0", "db": "connected"}
GET /api/v1/health {"status": "healthy", "api_version": "v1"}
```
### Метрики
Собираются через middleware и хранятся в БД:
- Время ответа (p50/p95/p99)
- Количество запросов (всего, по endpoint'ам)
- Количество ошибок (4xx, 5xx)
- Статус внешних сервисов (БД, Redis, AI провайдеры)
---
## Production мониторинг
### Prometheus + Grafana (рекомендовано)
| Компонент | Метрики |
|-----------|---------|
| Application | Время ответа, ошибки, request rate |
| Database | Connection pool, query time |
| Redis | Memory, hits/misses |
| Celery | Task queue length, execution time |
| System | CPU, RAM, disk, network |
### Алерты
| Условие | Действие |
|---------|----------|
| error rate > 1% | Уведомление в Telegram/Slack |
| API response p95 > 1s | Уведомление |
| DB connection pool > 80% | Предупреждение |
| Service down | PagerDuty / звонок |
---
## [ASK]
- Нужен ли мониторинг на старте? (базовый — да, Prometheus — перед production)
- Отправлять ли алерты? (да, если есть кто-то кто на них реагирует)
- Какой канал для алертов? (Telegram — простой, PagerDuty — профессиональный)
+88
View File
@@ -0,0 +1,88 @@
# Управление переменными окружения
---
## Принцип
Все настройки, которые меняются между окружениями (local, staging, production) — в переменных окружения. Никаких hardcoded значений в коде.
---
## Формат: .env
```bash
# === Core ===
PROJECT_NAME=MyProject
PROJECT_VERSION=1.0.0
PROJECT_ENV=local
# === Server ===
SERVER_HOST=0.0.0.0
SERVER_PORT=8020
# === Database ===
DATABASE_URL=sqlite+aiosqlite:///./app.db
# DATABASE_URL=postgresql+asyncpg://user:pass@localhost/dbname
# === JWT ===
JWT_SECRET_KEY=your-secret-key-here
JWT_ALGORITHM=HS256
# === Logging ===
LOG_LEVEL=INFO
```
---
## Валидация при старте
```python
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
project_name: str = "MyProject"
database_url: str = "sqlite+aiosqlite:///./app.db"
jwt_secret_key: str = ""
@property
def is_sqlite(self) -> bool:
return "sqlite" in self.database_url
def validate_for_production(self) -> None:
"""Проверить что критические переменные установлены."""
if self.project_env == "production":
assert self.jwt_secret_key, "JWT_SECRET_KEY not set"
assert "postgresql" in self.database_url, "Use PostgreSQL in production"
```
---
## Синхронизация .env.example
`.env.example` должен быть в репозитории и обновляться при каждом добавлении переменной.
Правила:
- Все переменные с комментариями
- Чувствительные значения пустые (пароли, ключи)
- Секции разделены комментариями (`# === Database ===`)
- Примеры значений в комментариях
---
## Secrets management
| Окружение | Где хранить секреты |
|-----------|-------------------|
| Local | `.env` (в .gitignore) |
| Staging | GitHub Secrets / 1Password |
| Production | GitHub Secrets / Vault |
---
## [ASK]
- Какой метод управления секретами? (рекомендация: .env + GitHub Secrets)
- Нужен ли Vault? (нет, < 10 разработчиков)
- Как часто менять JWT_SECRET_KEY? (при утечке или раз в год)
+141
View File
@@ -0,0 +1,141 @@
# Поэтапный план взросления проекта
Проект не строится сразу целиком. Он проходит этапы — от прототипа до саморазвивающейся системы.
Агенты живут с первого коммита. Новые агенты добавляются когда возникает потребность.
---
## Stage 0: Foundation — Ядро
**Начинаем здесь.** Проект только родился.
### Код
- FastAPI + SQLite + базовая auth
- Минимальный набор правил (00-rules.md)
- Базовые CRUD endpoints
- Pydantic схемы на все входы
### Агенты (создаются в первую очередь)
- **DocAgent** — пишет документацию параллельно с кодом
- **AuditAgent** — проверяет каждый коммит на правила
- **EvolutionAgent** — версионирует агентов
- **SupervisorAgent** — следит за всеми агентами
### Инфраструктура
- SQLite (aiosqlite)
- Прямой вызов фоновых задач (без Celery)
### До Stage 1
Сразу после того, как есть первый endpoint и auth.
---
## Stage 1: Growth — Рост
Проект обрастает функциональностью.
### Добавляемый код
- Полноценные сервисы
- Интеграции (AI провайдеры)
- Фронтенд (если нужен)
- Тесты
### Добавляемые агенты
- **QATesterAgent** — когда появились тесты (авто-проверка покрытия)
- **FixAgent** — когда пойман первый баг (анализ ошибок)
- **BacklogAgent** — когда появился техдолг (управление TODO/FIXME)
### Инфраструктура
- Те же SQLite + прямой вызов
- Тестовое покрытие > 50%
### До Stage 2
Перед первым production-релизом.
---
## Stage 2: Production-ready
Проект готов к реальным пользователям.
### Добавляемый код
- PostgreSQL + asyncpg
- Redis + Celery для фоновых задач
- Мониторинг (health + метрики)
- Полная документация
### Добавляемые агенты
- **SecurityAgent** — проверка конфигов, зависимостей
- **SpecAgent** — управление версией проекта, CHANGELOG
- **RolloutAgent** — постепенное развёртывание
### Инфраструктура
- PostgreSQL
- Redis + Celery worker
- CI/CD (lint → test → build → deploy)
- SSL (Let's Encrypt)
- .env для production + staging
### До Stage 3
После запуска, когда появились первые пользователи и метрики.
---
## Stage 3: Autonomous — Саморазвитие
Проект начинает развиваться самостоятельно.
### Добавляемый код
- Metrics middleware
- Prometheus/Grafana (или встроенные метрики)
- Agent report dashboard
- Self-healing механизмы
### Добавляемые агенты
- **ObserverAgent** — сбор метрик использования
- **UITestAgent** — визуальное тестирование (если есть UI)
### Инфраструктура
- A/B тестирование
- Auto-scaling (при необходимости)
- Автоматический откат при росте ошибок
### До Stage 4
Когда > 1000 пользователей или > 3 разработчиков.
---
## Stage 4: Evolution — Эволюция
Проект развивается автономно.
### Уровень саморазвития
- Агенты не только предлагают, но и применяют изменения
- EvolutionAgent принимает решения о рефакторинге
- FixAgent применяет исправления (с PR на ревью)
- ObserverAgent на основе метрик предлагает roadmap
### Инфраструктура
- Полный мониторинг с алертами
- Автоматическое масштабирование
- Disaster recovery plan
- Postmortem культура
---
## Сводная таблица
| Stage | БД | Задачи | Агентов | Тесты | Мониторинг | Саморазвитие |
|-------|----|--------|---------|-------|-----------|-------------|
| 0 | SQLite | Прямой | 4 | > 20% | Нет | Reactive |
| 1 | SQLite | Прямой | 7 | > 50% | Нет | Reactive |
| 2 | PostgreSQL | Celery | 9 | > 80% | Базовый | Reactive |
| 3 | PostgreSQL | Celery | 11 | > 80% | Prometheus | Proactive |
| 4 | PostgreSQL | Celery | 11+ | > 90% | Full | Autonomous |
---
## [ASK] На каком вы этапе?
Оцените текущее состояние проекта и выберите целевой этап.
Рекомендация: начинайте со Stage 0, не прыгайте через этапы.
+35
View File
@@ -0,0 +1,35 @@
# Runbook: Запуск проекта
---
## Первый запуск
```bash
# 1. Клонировать репозиторий
git clone <repo> && cd <repo>
# 2. Настроить окружение
cp .env.example .env
# Редактировать .env: JWT_SECRET_KEY, DATABASE_URL
# 3. Установить зависимости
pip install -r requirements.txt
# 4. Запустить
uvicorn app.main:app --reload --host 0.0.0.0 --port 8020
```
## Проверка
```bash
curl http://localhost:8020/health
# → {"status": "healthy"}
curl http://localhost:8020/docs
# → Swagger UI
```
## Остановка
```bash
Ctrl+C # или kill $(pgrep -f uvicorn)
```
+36
View File
@@ -0,0 +1,36 @@
# Runbook: Резервное копирование
---
## SQLite
```bash
# Ручной бэкап
cp app.db app.db.backup.$(date +%Y%m%d)
# Автоматический (cron)
0 3 * * * cp /path/to/app.db /path/to/backups/app.db.$(date +\%Y\%m\%d)
```
## PostgreSQL
```bash
# Ручной бэкап
pg_dump -U voidea -d voidea > backup.$(date +%Y%m%d).sql
# Восстановление
psql -U voidea -d voidea < backup.sql
# Автоматический (cron)
0 3 * * * pg_dump -U voidea -d voidea | gzip > /backups/db.$(date +\%Y\%m\%d).sql.gz
```
## Что бэкапить
- Базу данных (ежедневно)
- .env (секреты, отдельно, в Vault/1Password)
- User uploaded files (если есть)
## Хранение
- Последние 7 дней: локально
- Последние 30 дней: S3/облако
- Старше 30 дней: удалять
+53
View File
@@ -0,0 +1,53 @@
# Runbook: Инциденты
---
## Сервис недоступен
```bash
# 1. Проверить что процесс жив
ps aux | grep uvicorn
# 2. Проверить логи
journalctl -u voidea -n 50 --no-pager
# 3. Перезапустить
systemctl restart voidea
# 4. Проверить
curl http://localhost:8020/health
# 5. Если не помогло → rollback
git checkout <previous-stable-tag>
systemctl restart voidea
```
## База данных недоступна
```bash
# 1. Проверить PostgreSQL
systemctl status postgresql
# 2. Проверить логи
journalctl -u postgresql -n 50
# 3. Перезапустить
systemctl restart postgresql
# 4. Если повреждена → восстановить из backup
# psql -U voidea -d voidea < backup.sql
```
## Высокая загрузка CPU
```bash
# 1. Найти процесс
top -o %CPU
# 2. Найти endpoint
tail -n 100 /var/log/voidea/access.log
# 3. Временно отключить (если endpoint не критичен)
# 4. Разбираться после восстановления
```
+28
View File
@@ -0,0 +1,28 @@
# Runbook: Масштабирование
---
## Когда масштабироваться
| Метрика | Действие |
|---------|----------|
| CPU > 80% постоянно | Добавить ядер/воркеров |
| RAM > 80% | Увеличить RAM |
| DB > 10M записей | Индексы → шардинг |
| Response time p95 > 1s | Кэширование → реплики БД |
## Как масштабировать
### Vertical (проще)
```bash
# Увеличить ресурсы VPS
# Затем перезапустить
systemctl restart voidea
```
### Horizontal (сложнее)
```bash
# 1. Поставить load balancer (Nginx)
# 2. Запустить несколько инстансов
# 3. Настроить shared session/кэш (Redis)
```
+41
View File
@@ -0,0 +1,41 @@
# Runbook: Обновление
---
## Обновление с нулевым даунтаймом
```bash
# 1. Задеплоить новую версию на второй порт (8021)
# 2. Проверить health нового инстанса
curl http://localhost:8021/health
# 3. Переключить Nginx на новый порт
# 4. Остановить старый инстанс
```
## Обновление зависимостей
```bash
# 1. Обновить requirements.txt
pip install --upgrade -r requirements.txt
# 2. Проверить
ruff check .
pytest
# 3. Закоммитить
git add requirements.txt && git commit -m "chore: update dependencies"
```
## Откат
```bash
# 1. Откатить код
git revert HEAD
# 2. Откатить БД (если была миграция)
alembic downgrade -1
# 3. Перезапустить
systemctl restart voidea
```
+127
View File
@@ -0,0 +1,127 @@
# Шаблон проекта — машиночитаемое описание
# Формат: YAML
# Используется CI/CD, генераторами и ИИ-ассистентами для понимания структуры
template:
version: "1.0.0"
description: "Универсальный шаблон для старта любых проектов"
defaults:
language: python
python_version: "3.12"
database: sqlite
async_framework: fastapi
orm: sqlalchemy
frontend: react
frontend_build: vite
styling: tailwind
testing: pytest
architecture:
layers:
- name: api
depends_on: [services]
description: "HTTP роуты, Pydantic валидация, OpenAPI документация"
- name: services
depends_on: [integrations, data]
description: "Бизнес-логика, оркестрация"
- name: integrations
depends_on: [data]
description: "Внешние API, AI провайдеры, fallback chain"
- name: tasks
depends_on: [services, integrations]
description: "Фоновые задачи (Celery или прямой вызов)"
- name: agents
depends_on: [services, integrations]
description: "Системные агенты (саморазвитие проекта)"
- name: data
depends_on: [core]
description: "Модели БД, репозитории, миграции"
- name: core
description: "Config, base classes, security, dependencies"
layers_frontend:
- name: pages
depends_on: [components]
- name: components
depends_on: [api, auth]
- name: api
description: "HTTP-клиент к backend"
- name: auth
description: "JWT токены, AuthContext"
agents:
core:
- name: DocAgent
description: "Пишет документацию параллельно с кодом"
version: "1.0.0"
triggers: [pre_commit, manual]
- name: AuditAgent
description: "Проверяет каждый коммит на соответствие правилам"
version: "1.0.0"
triggers: [pre_commit, manual]
- name: EvolutionAgent
description: "Версионирует агентов, управляет их развитием"
version: "1.0.0"
triggers: [cron, manual, event]
- name: SupervisorAgent
description: "Следит за всеми агентами, их здоровьем и версиями"
version: "1.0.0"
triggers: [cron, event, manual]
optional:
- name: QATesterAgent
when: "tests_exist"
- name: FixAgent
when: "first_bug"
- name: BacklogAgent
when: "tech_debt_exists"
- name: SecurityAgent
when: "pre_production"
- name: SpecAgent
when: "pre_release"
- name: RolloutAgent
when: "pre_deploy"
- name: ObserverAgent
when: "post_launch"
- name: UITestAgent
when: "ui_exists"
triggers:
- name: pre_commit
description: "Запускается при каждом коммите"
- name: push
description: "Запускается при пуше в remote"
- name: tag_creation
description: "Запускается при создании git-тега"
- name: cron
description: "Запускается по расписанию (daily/hourly)"
- name: manual
description: "Запускается вручную из админ-панели"
- name: api
description: "Запускается через API-вызов"
- name: event
description: "Запускается при возникновении события"
conventions:
naming:
classes: PascalCase
functions: snake_case
constants: UPPER_SNAKE_case
files: snake_case
env_vars: UPPER_SNAKE_case
db_tables: snake_case
db_indexes: "ix_tablename_column"
db_unique: "uq_tablename_column"
git_branches: "feature/*, hotfix/*, release/*"
imports:
style: "absolute"
order: ["stdlib", "third_party", "local"]
formatting:
python_line_length: 88
js_line_length: 100
quote_style: "double для данных, single для docstrings"
docstrings: "google-style"
rules_ref: "docs/00-rules.md"
decisions_ref: "docs/decisions/"
checklists_ref: "docs/checklists/"
+41
View File
@@ -0,0 +1,41 @@
# === Core ===
PROJECT_NAME=
PROJECT_VERSION=1.0.0
PROJECT_ENV=local
# === Server ===
SERVER_HOST=0.0.0.0
SERVER_PORT=8020
# SERVER_EXTERNAL_URL=http://your-domain.com:8020
# === Database ===
# [ASK]: SQLite для dev или PostgreSQL?
# DATABASE_URL=sqlite+aiosqlite:///./app.db
# DATABASE_URL=postgresql+asyncpg://user:pass@localhost/dbname
# === JWT ===
JWT_SECRET_KEY=
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
JWT_REFRESH_TOKEN_EXPIRE_DAYS=30
# === AI (опционально) ===
# AI_PROVIDER_KEY=
# AI_FALLBACK_MODEL=yandex_gpt
# AI_TIMEOUT=10
# === OAuth (опционально) ===
# OAUTH_YANDEX_ID=
# OAUTH_YANDEX_SECRET=
# OAUTH_GOOGLE_ID=
# OAUTH_GOOGLE_SECRET=
# === Email (опционально) ===
# SMTP_HOST=
# SMTP_PORT=587
# SMTP_USER=
# SMTP_PASS=
# === Logging ===
LOG_LEVEL=INFO
# LOG_LEVEL=DEBUG
+38
View File
@@ -0,0 +1,38 @@
# Python
__pycache__/
*.py[cod]
*.egg-info/
dist/
*.egg
.venv/
venv/
env/
# Node
node_modules/
webui/dist/
# Environment
.env
.env.local
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Logs
logs/
*.log
# Database
*.db
*.sqlite3
# Documentation build
docs/_build/
@@ -0,0 +1,16 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
args: [--maxkb=500]
- id: check-merge-conflict
+12
View File
@@ -0,0 +1,12 @@
# Changelog
Все заметные изменения в этом проекте.
Формат: [Keep a Changelog](https://keepachangelog.com/)
Версионирование: [SemVer](https://semver.org/)
## [1.0.0] - {date}
### Added
- Первый релиз проекта
- Базовая функциональность
+35
View File
@@ -0,0 +1,35 @@
# Conventional Commits — шпаргалка
```
<тип>[optional scope]: <описание>
[optional body]
[optional footer]
```
## Типы
| Тип | Описание | Версия |
|-----|----------|--------|
| `feat` | Новая функция | MINOR |
| `fix` | Исправление бага | PATCH |
| `BREAKING` | Несовместимое изменение | MAJOR |
| `docs` | Документация | — |
| `style` | Форматирование | — |
| `refactor` | Рефакторинг | — |
| `test` | Тесты | — |
| `chore` | Обслуживание | — |
## Примеры
```
feat(auth): add OAuth2 login with Yandex
fix: handle empty list in idea search
BREAKING: change API response format
docs: update README with setup instructions
refactor: extract IdeaService from api/ideas.py
```
+11
View File
@@ -0,0 +1,11 @@
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM builder AS production
WORKDIR /app
COPY . .
EXPOSE 8020
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8020"]
+27
View File
@@ -0,0 +1,27 @@
# {Project Name}
{Одна строка описания проекта}
## Быстрый старт
```bash
cp .env.example .env
# Редактировать .env
pip install -r requirements.txt
uvicorn app.main:app --reload
```
## Разработка
Проект следует правилам, описанным в `docs/`. Обязательно прочитайте:
1. `docs/00-rules.md` — основные правила
2. `docs/03-project-structure.md` — структура проекта
3. `docs/01-architecture.md` — архитектура
## API
- `/docs` — Swagger UI
- `/redoc` — ReDoc
- `/openapi.json` — OpenAPI spec
+43
View File
@@ -0,0 +1,43 @@
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8020:8020"
env_file: .env
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
worker:
build:
context: .
dockerfile: Dockerfile
command: celery -A app.tasks worker -l info
env_file: .env
depends_on:
- db
- redis
db:
image: postgres:14
environment:
POSTGRES_DB: voidea
POSTGRES_USER: voidea
POSTGRES_PASSWORD: ${DB_PASS}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U voidea"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7
volumes:
pgdata: