# ARCHITECTURE.md — Стек и архитектура проекта ## Стек технологий | Слой | Технология | Назначение | |------|-----------|------------| | Framework | Nuxt 4.5 (Nitro) | Full-stack SSR/CSR, файловый роутинг, server routes | | Language | TypeScript | Строгая типизация, общая кодовая база | | ORM | Prisma 8 (orm-postgres) | Типобезопасный ORM с SQL-first контрактами | | Database | PostgreSQL 16 | Основная реляционная БД | | Migrations | Prisma 8 | SQL-миграции через Prisma (файлы в `prisma/`) | | Validation | Zod | Валидация данных на границах (API, route params, env vars) | | AI/Orchestration | LangGraph.js 1.4 + PostgresSaver | StateGraph для пайплайна анализа, checkpointing в Postgres | | State | Pinia | Управление состоянием на клиенте | | Build | Vite 8 | Сборка клиентской части | | Package manager | pnpm | Управление зависимостями | | Linting | ESLint + @nuxt/eslint + stylistic | Статический анализ кода | | Pre-commit | husky + lint-staged | Автоформатирование и проверка перед коммитом | | Unit Testing | Vitest | Unit-тесты, интеграционные тесты | | E2E Testing | Playwright | End-to-end тесты + CLI для AI-агента | | Error Monitoring | Sentry (@sentry/nuxt) | Ошибки, stack trace, release tracking | | Structured Logging | evlog | Один широкий event на запрос, structured JSON | | Runtime | Node.js (LTS) | Серверный рантайм | | Language Runtime | tsx | Запуск .ts файлов (CLI worker, миграции) | ## Структура проекта ``` app/ # Frontend (Vue 3) features/ # Feature-based organization ideas/ # Карточка идеи (компонент + composable + тесты) funnel/ # Воронка create-idea/ # Создание идеи voice-input/ # Голосовой ввод components/ # Shared UI-компоненты (кнопки, карточки) ui/ # shadcn-vue composables/ # Глобальные composable (useAuth, useToast) pages/ # Тонкие обёртки () layouts/ middleware/ utils/ stores/ # Pinia-сторы server/ # Backend (Nitro) api/ # API-маршруты (auto-imported by Nitro) ideas/ # CRUD идей + запуск анализа jobs/ # Управление задачами очереди utils/ api/ # API helpers (error.ts — единый apiError) db.ts # Синглтон postgres.js ideas.ts # Хелперы для ideas, лимит 10 активных llm.ts # LLM-клиент (z-ai/glm-5.3-flash через routerai.ru) stt.ts # STT через routerai.ru queue/ # Очередь задач + LangGraph-воркер llm-executor.ts # LLM-исполнитель (вызов LLM + Zod-валидация) plugins/ # Nitro-плагины (db-migrate, worker) shared/ # Общий код (app/ + server/) schemas/ # Zod schemas — единый источник правды roles/ # Zod-схемы для валидации ответов LLM-ролей types/ utils/ e2e/ # Playwright E2E-тесты smoke.spec.ts # Smoke-тесты: homepage, meta, request-id config/ # Конфиги пайплайна (steps, лимиты, очереди) roles/ # Конфиги ролей (промпты, параметры, Zod-схемы) components/ # Каталог компонентов (LLM, STT, валидатор) src/prisma/ # Prisma 8 contract, db.ts entry point docs/ # Документация services/ # Микросервисы (изолированные контейнеры) validator/ # Валидатор правил (node:http, POST /validate, GET /version) sentry.client.config.ts # Sentry client-side init sentry.server.config.ts # Sentry server-side init playwright.config.ts # Playwright конфиг (Chromium, webServer) ``` ## Архитектура потока данных (TZ §6) ``` UI (app/) → API (Nitro routes) → Postgres (карточки, версии, аудио, источники, прогоны, расчёты) ↓ очередь + LangGraph воркер (persistent worker) ↓ ИИ-решения (routerai.ru) и микросервисы (валидатор правил) ↓ журнал прогонов → расчётный модуль → отчёт → MVP ``` ### Наблюдаемость (Observability) ``` Запрос → evlog (один широкий event) → stdout (JSON) ↓ Sentry (ошибки + stack trace) ↓ X-Request-Id header (генерируется evlog) ``` - **evlog**: один event на каждый API-запрос со всем контекстом (user, idea, step, duration). Конфиг: `evlog/nuxt` модуль, `include: ['/api/**']` - **Sentry**: автоматическая инструментация client + server через `@sentry/nuxt/module`. DSN через `runtimeConfig`. Source maps заливаются через Vite plugin - **Playwright**: E2E-тесты в `e2e/`, Chromium-only. `webServer` автоматически поднимает `pnpm dev`. CLI (`@playwright/cli`) для AI-агента ### Очередь и воркер (TZ §8) - **Очередь**: кастомная на PostgreSQL (`queue_jobs`), поддержка приоритетов (high/medium/low), anti-starvation, лимит 10 активных идей - **Воркер**: LangGraph.js `StateGraph` с `Annotation.Root`, checkpointing через `@langchain/langgraph-checkpoint-postgres` (`PostgresSaver`) - **Состояние на сервере**: закрытие вкладки не останавливает выполнение; перезапуск воркера продолжает с последнего чекпоинта - **Управление**: пауза/продолжение/отмена/повтор шага/смена приоритета — через API (`/api/jobs/:id/*`) - **Режимы запуска**: - `WORKER_MODE=true` — Nitro-плагин запускает воркер в фоне (docker-compose worker service) - `pnpm run worker` — standalone CLI (`worker-cli.ts`) - **Executor Registry**: плагинная архитектура исполнителей шагов (`registerExecutor`), fixture-реализация для прототипа, реальные ИИ-вызовы подключены (этап 5) ### Проверенные сценарии (автотесты + ручная проверка) | Сценарий | Тест | Статус | |----------|------|--------| | Enqueue идемпотентно | queue.test.ts | ✅ | | Claim с приоритетами | queue.test.ts | ✅ | | Anti-starvation | queue.test.ts | ✅ | | Параллельный claim | queue.test.ts | ✅ | | Key release при re-enqueue | queue.test.ts | ✅ | | Полный прогон (7 шагов) | worker.test.ts | ✅ | | Crash-restart (resume) | worker.test.ts | ✅ | | Pause + resume | worker.test.ts | ✅ | | Cancel | worker.test.ts | ✅ | | Failure + retry | worker.test.ts | ✅ | | Retry-step (time-travel) | worker.test.ts | ✅ | | Priority воркер | worker.test.ts | ✅ | | API create + enqueue + status | ручная (curl) | ✅ | | Retry-step через API | ручная (curl) | ✅ | | Homepage loads | smoke.spec.ts | ✅ | | Meta title | smoke.spec.ts | ✅ | | API request-id header | smoke.spec.ts | ✅ | ### LangGraph.js — детали - **Версия**: 1.4.14 (текущая стабильная) - **Checkpointing**: `@langchain/langgraph-checkpoint-postgres@1.0.5` через `pg.Pool` - **Паттерн time-travel**: `graph.invoke(null, historicalConfig)` для replay с исторического чекпоинта - **Примечание**: `graph.stream(null, config)` выбрасывает ошибку для已完成ных потоков; для time-travel используется `invoke` - **Anti-starvation**: формула `basePriority × 10 - attempts × 2 + ageInCycles × 0.5`, clamp 0–100 ### LLM-слой (этап 5) - **Модель**: `z-ai/glm-5.3-flash` через routerai.ru (OpenAI-compatible `/v1/chat/completions`) - **Клиент**: `server/utils/llm.ts` — `callLlm(schema, options)` с Zod-валидацией ответа - **Конфиги ролей**: `config/roles/` — system/user промпты, параметры (temperature, maxTokens, timeout), Zod-схемы для валидации - **Валидация**: битый ответ модели → `LlmError` → retry (если retries > 0) - **Маркировка**: LLM-прогоны помечаются `LLM:` (не `FIXTURE:`) в логах #### Роли пайплайна | Роль | Executor | Temperature | MaxTokens | Timeout | |------|----------|-------------|-----------|---------| | Оркестратор | `llm` | 0.3 | 1024 | 60s | | Аналитик идеи | `llm` | 0.3 | 2048 | 60s | | Аналитик рынка | `llm` | 0.5 | 4096 | 90s | | Стратег-аналитик | `llm` | 0.5 | 3072 | 90s | | Аналитик эффективности | `calc` (детерминированный) | — | — | 30s | | Критик | `llm` | 0.3 | 2048 | 60s | | Редактор отчёта | `fixture` | — | — | 30s | ### Микросервис-валидатор (TZ §9/§11) - **Назначение**: Проверка правил классификации (обязательные поля, допустимые значения, согласованность) - **Стек**: `node:http` + `zod` (0 зависимостей frameworks) - **Контракт**: - `POST /validate` → `{ valid: boolean, errors: string[] }` - `GET /version` → `{ version: string }` - **Правила**: - Обязательные поля: `category`, `priority`, `responsibleDepartment` - Допустимые категории: `вопрос`, `жалоба`, `запрос`, `предложение` - Допустимые приоритеты: `low`, `medium`, `high` - Согласованность: категория `жалоба` → приоритет не ниже `medium` - **Изоляция**: отдельный контейнер в docker-compose, без доступа к ключам оркестратора - **Клиент**: `server/utils/validator-client.ts` — вызов с протоколом прогона ### Каталог компонентов (TZ §9) - **Расположение**: `config/components/` - **Компоненты**: LLM, STT, Валидатор - **Для каждого**: назначение, API, схема входа/выхода, версия, зависимости, ограничения, метрики ### Протокол прогона (TZ §9) - **Таблицы**: `runs` (прогон), `run_calls` (вызовы компонентов) - **Запись**: каждый вызов LLM/валидатора → `run_calls` (входы, выходы, длительность, ошибки) - **Маркировка**: `is_fixture` в `runs`, `FIXTURE:` / `LLM:` в логах - **Сравнение**: 2 варианта на одном датасете через `server/utils/comparison.ts` ### Расчётный модуль (TZ §5, этап 7) - **Расположение**: `server/utils/efficiency/` — детерминированный код, LLM не участвует в вычислении - **Executor**: `'calc'` (`server/queue/calc-executor.ts`) — шаг `efficiency_model` пайплайна - **Компоненты**: - `prng.ts` — seeded PRNG (mulberry32) — детерминизм bootstrap - `dataset.ts` — генератор модельного датасета 200 обращений (пометка `simulation`, TZ §15) - `stats.ts` — bootstrap CI 95% разницы средних (10 000 ресемплов, фиксированный seed) - `model.ts` — формулы (variant_minutes, effect_per_ticket, effect_volume), 3 сценария, чувствительность ±20% - `decision.ts` — пороги → автоматическое влияние на рекомендацию (эффект < 0.5 мин → postpone; качество < 85% или CI включает ноль → validate_first) - `compute.ts` — оркестрация + warnings - **Хранение**: таблица `calculations` (model_version, formula, params, seed, input_summary, result, warnings) - **Воспроизводимость**: тот же вход + seed → битово идентичный результат (тест `compute.test.ts`) ## Версионирование API Стратегия: **версионирование через URL** (фаза 2+). ``` /api/ideas # Текущий CRUD + анализ (stage 2-4) /api/jobs/:id # Управление задачами очереди (stage 4) /api/v1/... # Будущее версионирование (stage 9+) ``` ## Конфигурация и безопасность - **DATABASE_URL**: только через переменные окружения, не хранится в коде - **API ключи** (routerai.ru): только на сервере, через `NITRO_*` env vars - **SENTRY_DSN**: через `runtimeConfig`, не хардкод - **Prompt injection**: текст идеи — данные, а не инструкции (защита на уровне промптов) - **Файлы аудио**: загружаются на сервер, хранятся временно, удаляются после обработки - **Pre-commit hooks**: husky + lint-staged запускают `eslint --fix` на каждом коммите ## Скрипты ```bash # Разработка pnpm dev # Nuxt dev server pnpm build # Production build pnpm preview # Local preview # Проверки (запускать после каждого изменения!) pnpm lint # ESLint pnpm lint:fix # ESLint + автофикс pnpm typecheck # Type checking (vue-tsc через Nuxt) pnpm test # Vitest (unit + integration) pnpm e2e # Playwright E2E-тесты pnpm e2e:ui # Playwright UI mode # База данных pnpm db:migrate # Применить миграции pnpm db:down # Откатить последнюю миграцию pnpm db:status # Статус миграций pnpm db:new # Создать новую миграцию # Очередь pnpm worker # Запустить воркер ``` ## Пакеты (ключевые зависимости) | Пакет | Версия | Назначение | |-------|--------|------------| | `nuxt` | 4.5.2 | Framework | | `@langchain/langgraph` | 1.4.14 | StateGraph для пайплайна | | `@langchain/langgraph-checkpoint-postgres` | 1.0.5 | Checkpointing в Postgres | | `postgres` | 3.4.9 | SQL-first Postgres driver | | `pg` | 8.23.0 | node-postgres (только для LangGraph checkpointer) | | `@sentry/nuxt` | 10.73.0 | Error monitoring (Sentry) | | `evlog` | 2.28.1 | Structured logging (wide events) | | `zod` | 4.5.4 | Валидация данных | | `tsx` | 4.23.13 | TS execution (CLI, worker) | | `vitest` | 3.2.7 | Unit + integration тесты | | `@playwright/test` | 1.63.0 | E2E тесты | | `@playwright/cli` | 0.1.19 | Playwright CLI для AI-агента | | `husky` | 9.1.7 | Git hooks | | `lint-staged` | 17.5.0 | Запуск линтера на staged файлах | | `eslint` | 10.10.0 | Статический анализ | | `tailwindcss` | 4.3.3 | CSS framework | ## Agent Skills Проект использует AI-агентов сHTTPRequestOperation скиллами: ``` .agents/skills/ ├── analyze-logs # Анализ логов из .evlog/logs/ ├── build-audit-logs # Аудит-трейлы с evlog └── review-logging-patterns # Ревью кода на паттерны логирования .claude/skills/ └── playwright-cli # Управление браузером через CLI ``` Правила для агентов — в `AGENTS.md` (включая evlog-конвенции в блоке ``).