Files
Randify.pro/.sisyphus/plans/dm-dashboard.md
T
emil aaf596a7bc fix(dm): OAuth redirect_uri, orange buttons, denser layout, hide lang switcher
- Fix OAuth redirect_uri mismatch in VK/Yandex callbacks (use PUBLIC_APP_URL)
- Make quick dice buttons and anchor nav links orange by default
- Densify DM Dashboard layout (smaller gaps, tighter spacing)
- Hide LanguageSwitcher/Blog/About/Privacy links on DM pages
- Increase notes textarea height for better usability
2026-05-15 01:42:09 +03:00

53 KiB
Raw Blame History

DM Dashboard MVP — Рабочий план

TL;DR

Quick Summary: Создать MVP DM Dashboard (/dm/*) внутри Randify.pro — инструмент для мастеров D&D 5e с кубиками, трекером инициативы, справочником Open5e, локальными заметками и базовой OAuth-аутентификацией (VK + Yandex).

Deliverables:

  • Гибридный Astro билд с API routes
  • PostgreSQL схема + Drizzle ORM + миграции
  • OAuth 2.1 + PKCE (VK + Yandex)
  • JWT сессии в httpOnly cookies
  • Dice Roller (клиент-side)
  • Initiative Tracker (простой список)
  • Open5e Reference (поиск + карточки)
  • Notes (localStorage)
  • Оранжевая тема оформления
  • TDD инфраструктура + тесты

Estimated Effort: Large Parallel Execution: YES — 3 волны + финальная верификация Critical Path: T1 (Hybrid Config) → T2 (DB Schema) → T7 (OAuth API) → T14 (DM Layout) → F1-F4


Context

Original Request

DM Dashboard — инструмент для мастеров настольных RPG, живёт на субдомене dm.randify.pro как часть проекта randify.pro. Три уровня доступа (FREE без аккаунта, FREE с аккаунтом, PRO), OAuth (VK/Yandex), Open5e справочник, AI-генерация, Boosty подписки.

Interview Summary

Key Discussions:

  • MVP vs Iteration 2: MVP — базовые инструменты без AI. Итерация 2 — AI, PRO, Boosty, закладки, энкаунтер-билдер.
  • Архитектура: Переход с static Astro на hybrid (API routes + Server Islands).
  • БД: PostgreSQL на reg.ru, Drizzle ORM.
  • Аутентификация: OAuth 2.1 + PKCE, JWT в httpOnly cookies.
  • Дизайн: Оранжевая тема в стиле ролёвок, похожая на текущий Randify.pro.
  • i18n: Только RU для DM Dashboard.
  • Тесты: TDD с Vitest.

Research Findings:

  • Randify — чисто статический сайт (27 генераторов), требуется серьёзная архитектурная трансформация.
  • Open5e V2 API с field filtering и pagination.
  • VK и Yandex требуют OAuth 2.1 + PKCE.
  • Token bucket — стандарт для rate limiting (пригодится в итерации 2).
  • Текущий деплой: Docker multi-stage (nginx:alpine) → нужен Node.js runtime.

Metis Review

Identified Gaps (addressed):

  • Core Objective разделён на MVP и Product Vision.
  • Scope IN/OUT чётко определены.
  • Противоречия (static→hybrid, RU-only) задокументированы как осознанные отклонения.
  • Тестовая стратегия (TDD) определена.

Work Objectives

Core Objective

Создать MVP DM Dashboard — модуль /dm/* внутри Randify.pro с базовыми инструментами для мастеров D&D 5e: кубиками, трекером инициативы, справочником Open5e, локальными заметками и базовой OAuth-аутентификацией (VK + Yandex).

Concrete Deliverables

  • astro.config.mjs — обновлённая конфигурация hybrid mode
  • Dockerfile + docker-compose.yml — Node.js runtime + PostgreSQL
  • src/db/schema.ts — Drizzle ORM схема
  • src/db/migrate.ts — скрипт миграций
  • src/pages/api/auth/[...path].ts — API routes для OAuth
  • src/lib/auth/jwt.ts — JWT утилиты
  • src/lib/auth/oauth.ts — OAuth PKCE утилиты
  • src/pages/dm/index.astro — главная страница DM Dashboard
  • src/layouts/DmLayout.astro — лейаут DM Dashboard
  • src/components/dm/DiceRoller.astro — кубики
  • src/components/dm/InitiativeTracker.astro — инициатива
  • src/components/dm/Open5eReference.astro — справочник
  • src/components/dm/NotesPanel.astro — заметки
  • src/lib/open5e/client.ts — клиент Open5e API
  • src/lib/open5e/cache.ts — кэширование
  • src/i18n/dm-translations.ts — переводы DM Dashboard (RU)
  • tests/ — TDD тесты для всех модулей

Definition of Done

  • npm run build проходит без ошибок
  • npm run test — все тесты проходят
  • docker compose up запускает приложение + PostgreSQL
  • OAuth вход через VK работает
  • OAuth вход через Yandex работает
  • Кубики генерируют корректные значения
  • Инициатива сортирует по убыванию
  • Open5e загружает и ищет монстров
  • Заметки сохраняются в localStorage
  • Дизайн в оранжевой теме

Must Have

  • Гибридный Astro билд
  • PostgreSQL подключение
  • OAuth аутентификация (VK + Yandex)
  • JWT сессии
  • Dice Roller
  • Initiative Tracker
  • Open5e Reference (поиск + просмотр)
  • Notes (localStorage)
  • Оранжевая тема
  • RU i18n
  • TDD тесты

Must NOT Have (Guardrails)

  • AI-генерация любого контента (Итерация 2)
  • Rate limiting (нужен AI)
  • PRO-tier логика (Итерация 2)
  • Boosty верификация (Итерация 2)
  • Закладки Open5e (Итерация 2)
  • Энкаунтер-билдер (Итерация 2)
  • Сохранение в PostgreSQL для пользовательских данных (Итерация 2)
  • EN-версия DM Dashboard (Итерация 2)
  • PWA / Service Worker (Итерация 2)
  • Изменения существующих генераторов
  • Удаление существующих страниц

Verification Strategy

ZERO HUMAN INTERVENTION — ALL verification is agent-executed. No exceptions.

Test Decision

  • Infrastructure exists: YES (Vitest в проекте)
  • Automated tests: TDD
  • Framework: Vitest
  • TDD Workflow: Каждая задача начинается с RED (падающий тест) → GREEN (минимальная реализация) → REFACTOR

QA Policy

Every task MUST include agent-executed QA scenarios. Evidence saved to .sisyphus/evidence/task-{N}-{scenario-slug}.{ext}.

  • Frontend/UI: Playwright — Navigate, interact, assert DOM, screenshot
  • API/Backend: Bash (curl) — Send requests, assert status + response fields
  • Database: Bash (psql/drizzle) — Query tables, assert rows

Execution Strategy

Parallel Execution Waves

Wave 1 (Foundation — start immediately):
├── T1: Astro Hybrid Config + Docker Update
├── T2: PostgreSQL Schema + Drizzle ORM
├── T3: Testing Infrastructure (TDD setup)
├── T4: Design System / Orange Theme
└── T5: OAuth App Setup Documentation

Wave 2 (Core Features — MAX PARALLEL):
├── T6: OAuth PKCE + API Routes (depends: T1, T2)
├── T7: JWT Sessions + Middleware (depends: T1, T2)
├── T8: Dice Roller Component (depends: T4)
├── T9: Initiative Tracker Component (depends: T4)
├── T10: Open5e API Client + Cache (depends: T1)
├── T11: Open5e Search UI (depends: T4, T10)
├── T12: Notes Component (depends: T4)
└── T13: Auth UI (Login/Logout/Profile) (depends: T6, T7)

Wave 3 (Integration + Polish):
├── T14: DM Dashboard Layout + Page (depends: T4, T6, T7, T8, T9, T10, T11, T12, T13)
├── T15: Navigation + Routing (depends: T14)
├── T16: Build Verification + CI Update (depends: T1, T14)
└── T17: Final Styling Polish (depends: T14, T15)

Wave FINAL (4 parallel reviews → user okay):
├── F1: Plan Compliance Audit (oracle)
├── F2: Code Quality Review (unspecified-high)
├── F3: Real QA (unspecified-high + playwright)
└── F4: Scope Fidelity Check (deep)

Dependency Matrix

  • T1: - → T6, T7, T10, T14, T16
  • T2: - → T6, T7, T16
  • T3: - → T8, T9, T10, T11, T12
  • T4: - → T8, T9, T11, T12, T13, T14, T17
  • T5: - → (документация для пользователя)
  • T6: T1, T2 → T13, T14
  • T7: T1, T2 → T13, T14
  • T8: T4 → T14
  • T9: T4 → T14
  • T10: T1 → T11, T14
  • T11: T4, T10 → T14
  • T12: T4 → T14
  • T13: T6, T7, T4 → T14
  • T14: T4, T6, T7, T8, T9, T10, T11, T12, T13 → T15, T16, T17
  • T15: T14 → -
  • T16: T1, T14 → -
  • T17: T14, T15 → -

Agent Dispatch Summary

  • Wave 1: T1→quick, T2→quick, T3→quick, T4→visual-engineering, T5→writing
  • Wave 2: T6→unspecified-high, T7→unspecified-high, T8→quick, T9→quick, T10→quick, T11→visual-engineering, T12→quick, T13→visual-engineering
  • Wave 3: T14→deep, T15→quick, T16→unspecified-high, T17→visual-engineering
  • FINAL: F1→oracle, F2→unspecified-high, F3→unspecified-high, F4→deep

TODOs

  • T1. Astro Hybrid Config + Docker Update

    What to do:

    • Обновить astro.config.mjs с output: 'hybrid' и adapter: node()
    • Добавить @astrojs/node адаптер
    • Обновить Dockerfile: заменить nginx:alpine на node:20-alpine с node ./dist/server/entry.mjs
    • Добавить docker-compose.yml с PostgreSQL сервисом
    • Обновить .github/workflows/deploy.yml для деплоя Node.js приложения
    • Проверить, что существующие /generators/* маршруты остаются статическими (export const prerender = true)

    Must NOT do:

    • Не удалять существующие генераторы или страницы
    • Не менять деплой основного сайта (только добавить Node.js runtime)

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: Конфигурационные изменения, не требует сложной логики

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 1
    • Blocks: T6, T7, T10, T14, T16
    • Blocked By: None

    References:

    • astro.config.mjs — текущая статическая конфигурация
    • Dockerfile — текущий multi-stage build с nginx
    • .github/workflows/deploy.yml — текущий деплой через rsync
    • Astro docs: @astrojs/node adapter configuration

    Acceptance Criteria:

    • npm run build создаёт dist/server/entry.mjs
    • docker build -t dm-dashboard . собирает образ
    • docker run -p 4321:4321 dm-dashboard запускает сервер
    • curl http://localhost:4321/generators/coin-toss/ возвращает статическую страницу
    • curl http://localhost:4321/api/health возвращает 200 (тестовый API route)

    QA Scenarios:

    Scenario: Astro hybrid build succeeds
      Tool: Bash
      Steps:
        1. npm run build
        2. ls dist/server/entry.mjs
      Expected Result: entry.mjs существует
      Evidence: .sisyphus/evidence/t1-hybrid-build.log
    
    Scenario: Existing generators still static
      Tool: Bash (curl)
      Steps:
        1. docker run -d -p 4321:4321 dm-dashboard
        2. curl -s http://localhost:4321/generators/coin-toss/ | grep -o "Coin Flip"
      Expected Result: "Coin Flip" найден в ответе
      Evidence: .sisyphus/evidence/t1-static-routes.html
    

    Commit: YES

    • Message: chore(dm): configure astro hybrid mode + docker
    • Files: astro.config.mjs, Dockerfile, docker-compose.yml, .github/workflows/deploy.yml, package.json
  • T2. PostgreSQL Schema + Drizzle ORM

    What to do:

    • Установить drizzle-orm и drizzle-kit
    • Создать src/db/schema.ts с таблицами:
      • users (id, vkId?, yandexId?, email?, name, avatar, createdAt)
      • sessions (id, userId, token, expiresAt) — для server-side сессий (MVP)
    • Создать src/db/client.ts — singleton PostgreSQL client
    • Создать src/db/migrate.ts — скрипт для запуска миграций
    • Добавить drizzle.config.ts
    • Создать .env.example с переменными DATABASE_URL, JWT_SECRET

    Must NOT do:

    • Не создавать таблицы для заметок, НПС, энкаунтеров (Итерация 2)
    • Не добавлять rate limiting таблицы (Итерация 2)

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: Схема базы данных, типичная задача

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 1
    • Blocks: T6, T7, T16
    • Blocked By: None

    References:

    • Drizzle ORM docs: PostgreSQL setup, schema definition, migrations
    • src/lib/generator-schema.ts — Zod patterns (уже в проекте)
    • src/data/config.ts — конфигурационные паттерны

    Acceptance Criteria:

    • npx drizzle-kit generate создаёт SQL миграции
    • npx drizzle-kit migrate применяет миграции к БД
    • docker compose exec postgres psql -U dmuser -d dmdashboard -c "\dt" показывает таблицы users и sessions

    QA Scenarios:

    Scenario: Database migrations run successfully
      Tool: Bash
      Preconditions: docker compose up -d
      Steps:
        1. npx drizzle-kit generate
        2. npx drizzle-kit migrate
        3. docker compose exec postgres psql -U dmuser -d dmdashboard -c "SELECT tablename FROM pg_tables WHERE schemaname='public'"
      Expected Result: users, sessions в списке таблиц
      Evidence: .sisyphus/evidence/t2-db-migrations.log
    
    Scenario: Drizzle client connects
      Tool: Bash (node)
      Steps:
        1. node -e "const { db } = require('./src/db/client.ts'); console.log('Connected')"
      Expected Result: "Connected" (или эквивалент для ESM)
      Evidence: .sisyphus/evidence/t2-db-connection.log
    

    Commit: YES

    • Message: chore(db): setup drizzle orm + postgresql schema
    • Files: src/db/schema.ts, src/db/client.ts, src/db/migrate.ts, drizzle.config.ts, .env.example
  • T3. Testing Infrastructure (TDD Setup)

    What to do:

    • Убедиться, что Vitest настроен (уже есть в package.json)
    • Создать vitest.config.ts с алиасами @/* → src/*
    • Добавить @testing-library/dom и happy-dom (или jsdom) для компонентных тестов
    • Создать tests/setup.ts — общий setup файл
    • Создать tests/utils.ts — хелперы для тестов (mock auth, mock db)
    • Установить playwright для компонентных тестов с рендерингом
    • Создать playwright.config.ts с базовой конфигурацией
    • Написать первый тест-скелетон для проверки инфраструктуры
    • Добавить скрипты test:unit и test:ui в package.json

    Must NOT do:

    • Не писать e2e тесты (только unit + component tests)

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: Настройка инфраструктуры

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 1
    • Blocks: T8, T9, T10, T11, T12 (все компоненты требуют тестов)
    • Blocked By: None

    References:

    • package.json — текущие скрипты test
    • tsconfig.json — алиасы @/*
    • Vitest docs: configuration, aliases, DOM environment

    Acceptance Criteria:

    • npm run test запускается без ошибок
    • npm run test:unit проходит минимум 1 тест
    • Алиасы @/* работают в тестах

    QA Scenarios:

    Scenario: Vitest runs with aliases
      Tool: Bash
      Steps:
        1. npm run test:unit
        2. grep "PASS\|1 passed" в выводе
      Expected Result: Тесты проходят, алиасы @/* резолвятся
      Evidence: .sisyphus/evidence/t3-vitest-run.log
    

    Commit: YES

    • Message: chore(tests): setup vitest + tdd infrastructure
    • Files: vitest.config.ts, tests/setup.ts, tests/utils.ts, package.json
  • T4. Design System / Orange Theme

    What to do:

    • Создать src/styles/dm-theme.css с CSS переменными:
      • --accent: #E87722 (оранжевый)
      • --accent-light: #FF9F43
      • --accent-dark: #D35400
      • --bg-primary: #0f0f0f
      • --bg-secondary: #1a1a1a
      • --bg-card: #242424
    • Создать src/components/dm/DmButton.astro — кнопка в DM стиле
    • Создать src/components/dm/DmCard.astro — карточка в DM стиле
    • Создать src/components/dm/DmInput.astro — инпут в DM стиле
    • Создать src/components/dm/DmHeader.astro — хедер DM Dashboard
    • Обновить DmLayout.astro (заглушку) с подключением темы

    Must NOT do:

    • Не менять существующие компоненты Randify (GeneratorCard, BaseLayout и т.д.)
    • Не добавлять анимации сложнее текущих (popElement)

    Recommended Agent Profile:

    • Category: visual-engineering
    • Skills: [/frontend-ui-ux]
    • Reason: UI/UX дизайн, стилизация

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 1
    • Blocks: T8, T9, T11, T12, T13, T14, T17
    • Blocked By: None

    References:

    • src/layouts/BaseLayout.astro — текущая тема --accent: #534AB7
    • src/components/GeneratorCard.astro — паттерн карточек
    • src/components/ResultBox.astro — паттерн отображения результатов
    • Tailwind CSS v4 docs: custom theme, CSS variables

    Acceptance Criteria:

    • Оранжевый цвет #E87722 применяется к кнопкам
    • Тёмная тема совместима с текущей
    • Компоненты Button, Card, Input рендерятся

    QA Scenarios:

    Scenario: Orange theme renders correctly
      Tool: Playwright
      Steps:
        1. Открыть http://localhost:4321/dm/
        2. Сделать скриншот
        3. Проверить CSS var --accent = #E87722
      Expected Result: Оранжевый акцентный цвет виден на кнопках
      Evidence: .sisyphus/evidence/t4-orange-theme.png
    

    Commit: YES

    • Message: feat(ui): add orange dm theme + base components
    • Files: src/styles/dm-theme.css, src/components/dm/*.astro
  • T5. OAuth App Setup Documentation

    What to do:

    • Создать docs/OAUTH_SETUP.md с инструкциями:
      • Как зарегистрировать VK ID приложение
      • Как зарегистрировать Yandex OAuth приложение
      • Какие redirect URI настроить (http://localhost:4321/api/auth/callback/vk, .../yandex)
      • Какие scopes запросить (профиль, email)
      • Куда сохранить client_id и client_secret (.env)
    • Добавить проверку env vars при старте приложения

    Must NOT do:

    • Не коммитить реальные client_id / client_secret
    • Не создавать приложения за пользователя

    Recommended Agent Profile:

    • Category: writing
    • Skills: []
    • Reason: Документация

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 1
    • Blocks: (документация для пользователя, не блокирует код)
    • Blocked By: None

    References:

    Acceptance Criteria:

    • Файл docs/OAUTH_SETUP.md создан и читаем
    • .env.example содержит VK_CLIENT_ID, VK_CLIENT_SECRET, YANDEX_CLIENT_ID, YANDEX_CLIENT_SECRET
    • Приложение проверяет наличие env vars и выдаёт понятную ошибку если их нет

    QA Scenarios:

    Scenario: Missing env vars produce clear error
      Tool: Bash
      Steps:
        1. unset VK_CLIENT_ID
        2. npm run dev
      Expected Result: Приложение не запускается с сообщением "Missing VK_CLIENT_ID"
      Evidence: .sisyphus/evidence/t5-env-check.log
    

    Commit: YES

    • Message: docs(dm): add oauth setup instructions
    • Files: docs/OAUTH_SETUP.md, .env.example
  • T6. OAuth PKCE + API Routes

    What to do:

    • Реализовать PKCE утилиты: generateCodeVerifier(), generateCodeChallenge()
    • Создать src/pages/api/auth/login/vk.ts — начало OAuth flow (генерация PKCE, редирект на VK)
    • Создать src/pages/api/auth/callback/vk.ts — обработка callback (обмен code на token)
    • Создать src/pages/api/auth/login/yandex.ts — аналогично для Yandex
    • Создать src/pages/api/auth/callback/yandex.ts — callback для Yandex
    • Создать src/pages/api/auth/logout.ts — выход
    • В src/lib/auth/oauth.ts реализовать функции для каждого провайдера
    • Сохранение PKCE verifier в cookie (временное, httpOnly)

    Must NOT do:

    • Не использовать localStorage для code_verifier (XSS-риск)
    • Не пропускать проверку state parameter

    Recommended Agent Profile:

    • Category: unspecified-high
    • Skills: []
    • Reason: OAuth + PKCE — security-critical

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T13, T14
    • Blocked By: T1, T2

    References:

    Acceptance Criteria:

    • curl /api/auth/login/vk возвращает 302 редирект на VK OAuth
    • Callback route принимает code и state
    • Logout route очищает cookies

    QA Scenarios:

    Scenario: VK OAuth login redirects correctly
      Tool: Bash (curl)
      Steps:
        1. curl -s -o /dev/null -w "%{http_code}" http://localhost:4321/api/auth/login/vk
      Expected Result: 302 redirect
      Evidence: .sisyphus/evidence/t6-vk-login.log
    
    Scenario: Invalid state rejected
      Tool: Bash (curl)
      Steps:
        1. curl -s "http://localhost:4321/api/auth/callback/vk?code=abc&state=wrong"
      Expected Result: 401 Unauthorized
      Evidence: .sisyphus/evidence/t6-invalid-state.log
    

    Commit: YES

    • Message: feat(auth): implement oauth pkce for vk and yandex
    • Files: src/lib/auth/oauth.ts, src/pages/api/auth/**/*.ts
  • T7. JWT Sessions + Middleware

    What to do:

    • Установить jose для JWT
    • Создать src/lib/auth/jwt.ts:
      • createToken(userId) — создание JWT
      • verifyToken(token) — верификация
      • setAuthCookie(token) — установка httpOnly cookie
      • clearAuthCookie() — очистка
    • Создать src/lib/auth/session.ts — работа с PostgreSQL sessions таблицей
    • Создать src/middleware/auth.ts — middleware для проверки сессий
    • Добавить Astro.locals.user типизацию
    • TTL сессии: 7 дней

    Must NOT do:

    • Не хранить JWT secret в коде (только env)
    • Не использовать localStorage для токенов

    Recommended Agent Profile:

    • Category: unspecified-high
    • Skills: []
    • Reason: Security-critical

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T13, T14
    • Blocked By: T1, T2

    References:

    • jose library docs: JWT sign, verify, Web Crypto API
    • src/db/schema.ts — sessions таблица

    Acceptance Criteria:

    • createToken() генерирует валидный JWT
    • verifyToken() принимает валидный и отклоняет истёкший
    • Cookie httpOnly, Secure, SameSite=strict
    • Middleware устанавливает Astro.locals.user для авторизованных

    QA Scenarios:

    Scenario: JWT creation and verification
      Tool: Bash (node)
      Steps:
        1. node -e "const { createToken, verifyToken } = require('./src/lib/auth/jwt.ts'); const t = createToken('user123'); console.log(verifyToken(t).sub)"
      Expected Result: "user123"
      Evidence: .sisyphus/evidence/t7-jwt.log
    
    Scenario: Expired token rejected
      Tool: Bash (node)
      Steps:
        1. node -e "const { verifyToken } = require('./src/lib/auth/jwt.ts'); verifyToken('expired_token')"
      Expected Result: Ошибка "JWT expired"
      Evidence: .sisyphus/evidence/t7-jwt-expired.log
    

    Commit: YES

    • Message: feat(auth): implement jwt sessions + middleware
    • Files: src/lib/auth/jwt.ts, src/lib/auth/session.ts, src/middleware/auth.ts
  • T8. Dice Roller Component

    What to do:

    • Создать src/components/dm/DiceRoller.astro
    • Поддержка нотаций: d4, d6, d8, d10, d12, d20, d100
    • Поле ввода: "2d6+3" или кнопки быстрого выбора
    • Модификатор (+/-)
    • Использовать crypto.getRandomValues из src/lib/client/random.ts
    • Анимация броска (вращение кубика)
    • История бросков
    • TDD: написать тесты перед реализацией

    Must NOT do:

    • Не делать сервер-side броски (клиент-side только)
    • Не добавлять advantage/disadvantage (MVP scope)

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: Простой клиентский компонент

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T14
    • Blocked By: T4, T3

    References:

    • src/lib/client/random.ts — randomInt, crypto.getRandomValues
    • src/components/generators/NumberGenerator.astro — паттерн генератора
    • src/components/ResultBox.astro — паттерн отображения результата

    Acceptance Criteria:

    • "1d20" генерирует число 1-20
    • "2d6" генерирует число 2-12
    • История бросков сохраняется в sessionStorage
    • Анимация отображается при броске

    QA Scenarios:

    Scenario: d20 produces valid range
      Tool: Playwright
      Steps:
        1. Открыть /dm/
        2. Кликнуть "d20"
        3. Проверить результат 1-20
      Expected Result: Число в диапазоне [1, 20]
      Evidence: .sisyphus/evidence/t8-d20-roll.png
    
    Scenario: Invalid input shows error
      Tool: Playwright
      Steps:
        1. Ввести "abc" в поле dice
        2. Кликнуть "Roll"
      Expected Result: Сообщение об ошибке "Неверная нотация"
      Evidence: .sisyphus/evidence/t8-invalid-dice.png
    

    Commit: YES

    • Message: feat(dm): add dice roller component
    • Files: src/components/dm/DiceRoller.astro, tests/dice-roller.test.ts
  • T9. Initiative Tracker Component

    What to do:

    • Создать src/components/dm/InitiativeTracker.astro
    • Форма добавления: Имя + Бросок инициативы (или авто-бросок d20 + модификатор)
    • Список combatants, отсортированный по убыванию
    • Кнопка "Следующий ход" — подсвечивает активного
    • Кнопка "Удалить" для каждого
    • Кнопка "Очистить всё"
    • Данные в sessionStorage (обнуляются при refresh — MVP)
    • TDD: написать тесты перед реализацией

    Must NOT do:

    • Не добавлять HP/статусы/раунды (MVP scope)
    • Не сохранять в PostgreSQL (MVP scope)

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: Простой клиентский компонент

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T14
    • Blocked By: T4, T3

    References:

    • src/lib/client/random.ts — randomInt
    • src/lib/client/animations.ts — popElement
    • src/lib/client/validation.ts — createErrorDisplay

    Acceptance Criteria:

    • Добавление combatant увеличивает список
    • Сортировка по убыванию броска
    • "Следующий ход" меняет активного
    • Refresh сбрасывает список

    QA Scenarios:

    Scenario: Initiative sorts descending
      Tool: Playwright
      Steps:
        1. Добавить "Гоблин" с 15
        2. Добавить "Воин" с 18
        3. Проверить порядок: Воин, Гоблин
      Expected Result: Воин (18) выше Гоблина (15)
      Evidence: .sisyphus/evidence/t9-initiative-sort.png
    
    Scenario: Turn cycling works
      Tool: Playwright
      Steps:
        1. Добавить 3 combatants
        2. Кликнуть "Следующий ход" 3 раза
        3. Проверить, что цикл замкнулся
      Expected Result: После 3-го клика активен первый
      Evidence: .sisyphus/evidence/t9-initiative-cycle.png
    

    Commit: YES

    • Message: feat(dm): add initiative tracker component
    • Files: src/components/dm/InitiativeTracker.astro, tests/initiative-tracker.test.ts
  • T10. Open5e API Client + Cache

    What to do:

    • Создать src/lib/open5e/client.ts:
      • searchMonsters(query, filters) — поиск монстров
      • getMonster(key) — получение по slug
      • searchSpells(query, filters) — поиск заклинаний
      • getSpell(key) — получение заклинания
    • Создать src/lib/open5e/cache.ts:
      • Кэширование в localStorage с TTL (24 часа)
      • Ключи: open5e:monsters:query, open5e:monster:key
    • Использовать Open5e V2 API с fields= parameter
    • Обработка ошибок (API недоступен → fallback message)
    • TDD: тесты с mock fetch

    Must NOT do:

    • Не кэшировать в IndexedDB (MVP: localStorage достаточно)
    • Не делать server-side cache (MVP: client-side only)

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: API клиент + кэш

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T11, T14
    • Blocked By: T1, T3

    References:

    • Open5e V2 API: https://api.open5e.com/v2/creatures/, https://api.open5e.com/v2/spells/
    • Open5e docs: field filtering, pagination

    Acceptance Criteria:

    • Поиск "dragon" возвращает монстров
    • Кэш сохраняет результаты в localStorage
    • Повторный поиск использует кэш
    • API недоступен → показывается ошибка

    QA Scenarios:

    Scenario: Search monsters returns results
      Tool: Bash (curl)
      Steps:
        1. curl -s "https://api.open5e.com/v2/creatures/?name__icontains=dragon&fields=name,key,challenge_rating_decimal"
      Expected Result: JSON с массивом существ
      Evidence: .sisyphus/evidence/t10-open5e-search.json
    
    Scenario: Cache stores results
      Tool: Playwright
      Steps:
        1. Открыть /dm/
        2. Поискать "goblin"
        3. Проверить localStorage
      Expected Result: localStorage содержит ключ open5e:*
      Evidence: .sisyphus/evidence/t10-open5e-cache.log
    

    Commit: YES

    • Message: feat(dm): add open5e api client + localstorage cache
    • Files: src/lib/open5e/client.ts, src/lib/open5e/cache.ts, tests/open5e-client.test.ts
  • T11. Open5e Search UI

    What to do:

    • Создать src/components/dm/Open5eReference.astro
    • Табы: Монстры / Заклинания
    • Поисковая строка с debounce (300ms)
    • Фильтры: CR (для монстров), Уровень (для заклинаний), Тип
    • Список результатов с пагинацией
    • Карточка деталей (модалка или раскрывающаяся карточка)
    • TDD: тесты на поиск и фильтрацию

    Must NOT do:

    • Не добавлять закладки (Итерация 2)
    • Не добавлять "добавить в энкаунтер" (Итерация 2)

    Recommended Agent Profile:

    • Category: visual-engineering
    • Skills: [/frontend-ui-ux]
    • Reason: UI компонент с поиском

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T14
    • Blocked By: T4, T10, T3

    References:

    • src/components/dm/Open5eReference.astro (новый)
    • src/lib/open5e/client.ts — API клиент
    • src/components/GeneratorCard.astro — паттерн карточки

    Acceptance Criteria:

    • Поиск "goblin" отображает гоблинов
    • Фильтр по CR работает
    • Карточка деталей открывается по клику
    • Пагинация переключает страницы

    QA Scenarios:

    Scenario: Search goblins and view details
      Tool: Playwright
      Steps:
        1. Открыть /dm/
        2. Перейти в таб "Монстры"
        3. Ввести "goblin" в поиск
        4. Кликнуть на первый результат
      Expected Result: Открывается карточка с HP, AC, действиями
      Evidence: .sisyphus/evidence/t11-open5e-details.png
    
    Scenario: Filter by CR
      Tool: Playwright
      Steps:
        1. Выбрать фильтр CR: 1/4
        2. Проверить, что все результаты имеют CR 1/4
      Expected Result: Только существа с CR 1/4
      Evidence: .sisyphus/evidence/t11-open5e-filter.png
    

    Commit: YES

    • Message: feat(dm): add open5e search ui
    • Files: src/components/dm/Open5eReference.astro, tests/open5e-ui.test.ts
  • T12. Notes Component

    What to do:

    • Создать src/components/dm/NotesPanel.astro
    • Текстовая область для заметок
    • Автосохранение в localStorage (debounce 500ms)
    • Индикатор "Сохранено"
    • Кнопка "Очистить"
    • Несколько заметок? (MVP: одна большая заметка)
    • TDD: тесты на localStorage persistence

    Must NOT do:

    • Не сохранять в PostgreSQL (MVP scope)
    • Не добавлять rich text/Markdown (MVP: plain text)

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: Простой клиентский компонент

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T14
    • Blocked By: T4, T3

    References:

    • src/lib/client/clipboard.ts — паттерны клиентских утилит
    • src/components/ResultBox.astro — паттерн панели

    Acceptance Criteria:

    • Текст сохраняется в localStorage
    • После refresh текст восстанавливается
    • Индикатор "Сохранено" появляется через 500ms

    QA Scenarios:

    Scenario: Notes persist across refresh
      Tool: Playwright
      Steps:
        1. Открыть /dm/
        2. Ввести "Тестовая заметка" в поле
        3. Подождать 1 секунду
        4. Refresh страницы
      Expected Result: Текст "Тестовая заметка" остался
      Evidence: .sisyphus/evidence/t12-notes-persist.png
    
    Scenario: Clear button empties notes
      Tool: Playwright
      Steps:
        1. Ввести текст
        2. Кликнуть "Очистить"
        3. Проверить localStorage
      Expected Result: localStorage пустой
      Evidence: .sisyphus/evidence/t12-notes-clear.png
    

    Commit: YES

    • Message: feat(dm): add notes panel with localstorage
    • Files: src/components/dm/NotesPanel.astro, tests/notes.test.ts
  • T13. Auth UI (Login / Logout / Profile)

    What to do:

    • Создать src/components/dm/AuthPanel.astro
    • Кнопки "Войти через VK" и "Войти через Yandex"
    • После входа: аватар + имя + кнопка "Выйти"
    • Получение данных пользователя из Astro.locals.user
    • Показывать гостевое состояние для неавторизованных
    • TDD: тесты на отображение состояний

    Must NOT do:

    • Не показывать email/чувствительные данные
    • Не добавлять регистрацию по email (только OAuth)

    Recommended Agent Profile:

    • Category: visual-engineering
    • Skills: [/frontend-ui-ux]
    • Reason: UI компонент аутентификации

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 2
    • Blocks: T14
    • Blocked By: T6, T7, T4

    References:

    • src/components/LanguageSwitcher.astro — паттерн верхней панели
    • src/layouts/BaseLayout.astro — интеграция в layout

    Acceptance Criteria:

    • Неавторизованный видит кнопки входа
    • Авторизованный видет аватар и имя
    • Клик "Выйти" очищает сессию

    QA Scenarios:

    Scenario: Guest sees login buttons
      Tool: Playwright
      Steps:
        1. Открыть /dm/ в инкогнито
        2. Проверить наличие "Войти через VK"
      Expected Result: Кнопки входа видны
      Evidence: .sisyphus/evidence/t13-guest-view.png
    
    Scenario: Logout clears session
      Tool: Playwright
      Steps:
        1. Авторизоваться (mock сессия)
        2. Кликнуть "Выйти"
        3. Проверить cookies
      Expected Result: Cookie auth очищен, показывается гостевое состояние
      Evidence: .sisyphus/evidence/t13-logout.png
    

    Commit: YES

    • Message: feat(dm): add auth ui panel
    • Files: src/components/dm/AuthPanel.astro, tests/auth-ui.test.ts
  • T14. DM Dashboard Layout + Page

    What to do:

    • Создать src/layouts/DmLayout.astro:
      • Наследует BaseLayout (SEO, analytics)
      • Оранжевая тема (подключает dm-theme.css)
      • Хедер с логотипом DM Dashboard + AuthPanel
      • Основной слот для контента
      • Футер с ссылками
    • Создать src/pages/dm/index.astro:
      • Использует DmLayout
      • Отображает все инструменты: DiceRoller, InitiativeTracker, Open5eReference, NotesPanel
      • Табы или секции для переключения между инструментами
      • RU i18n через src/i18n/dm-translations.ts
    • Добавить src/i18n/dm-translations.ts со всеми строками DM Dashboard

    Must NOT do:

    • Не менять существующие layouts (BaseLayout, GeneratorLayout)
    • Не добавлять sidebar или сложную навигацию (MVP: простая страница)

    Recommended Agent Profile:

    • Category: deep
    • Skills: [/frontend-ui-ux]
    • Reason: Интеграция всех компонентов в единый layout

    Parallelization:

    • Can Run In Parallel: NO (зависит от многих задач)
    • Parallel Group: Wave 3
    • Blocks: T15, T16, T17
    • Blocked By: T4, T6, T7, T8, T9, T10, T11, T12, T13

    References:

    • src/layouts/GeneratorLayout.astro — паттерн обёртки
    • src/layouts/BaseLayout.astro — базовый layout
    • src/pages/generators/numbers.astro — паттерн страницы

    Acceptance Criteria:

    • /dm/ открывается без ошибок
    • Все 4 инструмента отображаются
    • AuthPanel показывает правильное состояние
    • Оранжевая тема применена
    • RU переводы работают

    QA Scenarios:

    Scenario: DM Dashboard loads all tools
      Tool: Playwright
      Steps:
        1. Открыть http://localhost:4321/dm/
        2. Сделать скриншот
        3. Проверить наличие: Кубики, Инициатива, Справочник, Заметки
      Expected Result: Все 4 секции видны, оформление оранжевое
      Evidence: .sisyphus/evidence/t14-dashboard-full.png
    
    Scenario: Auth state reflected
      Tool: Playwright
      Steps:
        1. Открыть /dm/ в инкогнито
        2. Проверить "Войти через VK"
        3. Авторизоваться (mock)
        4. Проверить имя пользователя
      Expected Result: После входа показывается имя и аватар
      Evidence: .sisyphus/evidence/t14-auth-state.png
    

    Commit: YES

    • Message: feat(dm): integrate dashboard layout + page
    • Files: src/layouts/DmLayout.astro, src/pages/dm/index.astro, src/i18n/dm-translations.ts
  • T15. Navigation + Routing

    What to do:

    • Добавить ссылку на DM Dashboard в главное меню (LanguageSwitcher или отдельная кнопка)
    • Создать src/pages/dm/dice.astro — отдельная страница кубиков (опционально)
    • Создать src/pages/dm/initiative.astro — отдельная страница инициативы (опционально)
    • Создать src/pages/dm/reference.astro — отдельная страница справочника (опционально)
    • Создать src/pages/dm/notes.astro — отдельная страница заметок (опционально)
    • Или: сделать навигацию по якорям на главной странице #dice, #initiative, #reference, #notes
    • Обновить src/pages/index.astro — добавить карточку DM Dashboard среди генераторов

    Must NOT do:

    • Не создавать дублирующих маршрутов
    • Не ломать существующую навигацию

    Recommended Agent Profile:

    • Category: quick
    • Skills: []
    • Reason: Навигация и роутинг

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 3
    • Blocks: None
    • Blocked By: T14

    References:

    • src/pages/index.astro — главная страница со списком генераторов
    • src/components/GeneratorCard.astro — карточка генератора

    Acceptance Criteria:

    • С главной страницы есть ссылка на /dm/
    • С /dm/ можно вернуться на главную
    • Навигация между инструментами работает (якоря или табы)

    QA Scenarios:

    Scenario: Navigation from homepage
      Tool: Playwright
      Steps:
        1. Открыть /
        2. Кликнуть "DM Dashboard"
        3. Проверить URL
      Expected Result: URL = /dm/
      Evidence: .sisyphus/evidence/t15-nav-home-to-dm.png
    

    Commit: YES

    • Message: feat(dm): add navigation and routing
    • Files: src/pages/dm/*.astro, src/pages/index.astro
  • T16. Build Verification + CI Update

    What to do:

    • Обновить .github/workflows/deploy.yml:
      • Добавить шаг запуска PostgreSQL (docker-compose)
      • Добавить миграции перед деплоем
      • Обновить rsync для Node.js приложения (или перейти на docker deploy)
    • Проверить npm run build — нет ошибок
    • Проверить npm run test — все тесты проходят
    • Проверить npm run lint — нет ошибок
    • Добавить health-check endpoint /api/health
    • Обновить docker-compose.yml для production

    Must NOT do:

    • Не удалять существующий деплой основного сайта
    • Не коммитить secrets в CI

    Recommended Agent Profile:

    • Category: unspecified-high
    • Skills: []
    • Reason: CI/CD, деплой

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 3
    • Blocks: None
    • Blocked By: T1, T14

    References:

    • .github/workflows/deploy.yml — текущий workflow
    • docker-compose.yml — Docker конфигурация
    • Dockerfile — обновлённый образ

    Acceptance Criteria:

    • npm run build — SUCCESS
    • npm run test — все тесты PASS
    • npm run lint — нет ошибок
    • Docker compose запускает app + postgres
    • CI workflow проходит

    QA Scenarios:

    Scenario: Full build succeeds
      Tool: Bash
      Steps:
        1. npm run build
        2. npm run test
        3. npm run lint
      Expected Result: Все команды завершаются с кодом 0
      Evidence: .sisyphus/evidence/t16-build.log
    
    Scenario: Docker compose health check
      Tool: Bash
      Steps:
        1. docker compose up -d
        2. curl -s http://localhost:4321/api/health
      Expected Result: {"status":"ok"}
      Evidence: .sisyphus/evidence/t16-health.json
    

    Commit: YES

    • Message: ci(dm): update build, tests, and deployment
    • Files: .github/workflows/deploy.yml, docker-compose.yml, src/pages/api/health.ts
  • T17. Final Styling Polish

    What to do:

    • Проверить responsive design (mobile, tablet, desktop)
    • Проверить accessibility (focus-visible, aria-labels)
    • Оптимизировать шрифты и spacing
    • Проверить консистентность оранжевой темы
    • Добавить hover/active состояния для интерактивных элементов
    • Проверить тёмную тему (контрастность)
    • TDD: визуальные регрессионные тесты (скриншоты)

    Must NOT do:

    • Не менять функционал
    • Не добавлять новые фичи

    Recommended Agent Profile:

    • Category: visual-engineering
    • Skills: [/frontend-ui-ux]
    • Reason: UI полировка

    Parallelization:

    • Can Run In Parallel: YES
    • Parallel Group: Wave 3
    • Blocks: None
    • Blocked By: T14, T15

    References:

    • src/styles/dm-theme.css — текущая тема
    • Tailwind CSS docs: responsive design, accessibility

    Acceptance Criteria:

    • Mobile: все элементы помещаются на экране 375px
    • Desktop: адекватные отступы и размеры
    • Focus-visible работает на всех интерактивных элементах
    • Контрастность текста ≥ 4.5:1

    QA Scenarios:

    Scenario: Responsive design
      Tool: Playwright
      Steps:
        1. Открыть /dm/ в viewport 375x667
        2. Сделать скриншот
        3. Открыть /dm/ в viewport 1920x1080
        4. Сделать скриншот
      Expected Result: Оба скриншота показывают удобочитаемый интерфейс
      Evidence: .sisyphus/evidence/t17-responsive-mobile.png, t17-responsive-desktop.png
    

    Commit: YES

    • Message: style(dm): final polish and responsive design
    • Files: src/styles/dm-theme.css, src/components/dm/*.astro

Final Verification Wave

4 review agents run in PARALLEL. ALL must APPROVE. Present consolidated results to user and get explicit "okay" before completing.

  • F1. Plan Compliance Audit — oracle Read the plan end-to-end. For each "Must Have": verify implementation exists. For each "Must NOT Have": search codebase for forbidden patterns. Check evidence files exist. Output: Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT

  • F2. Code Quality Review — unspecified-high Run tsc --noEmit + npm run lint + npm run test. Review changed files for AI slop patterns. Output: Build [PASS/FAIL] | Lint [PASS/FAIL] | Tests [N pass/N fail] | VERDICT

  • F3. Real Manual QA — unspecified-high (+ playwright skill) Execute EVERY QA scenario from EVERY task. Test cross-task integration. Capture evidence. Output: Scenarios [N/N pass] | Integration [N/N] | VERDICT

  • F4. Scope Fidelity Check — deep For each task: read "What to do", read actual diff. Verify 1:1. Check "Must NOT do" compliance. Output: Tasks [N/N compliant] | Contamination [CLEAN/N issues] | VERDICT


Plan Reviews

Metis Review

  • Status: COMPLETED
  • Findings: Core Objective разделён на MVP и Product Vision; Scope IN/OUT определены; противоречия задокументированы.

Oracle Verification Phase 1

  • Status: PASS
  • Verdict: CHECK 5/5 PASS | GO

Oracle Verification Phase 2

  • Status: PASS
  • Verdict: CHECK 6/6 PASS | GO

Momus Review

  • Status: OKAY
  • Verdict: План хорошо структурирован, все ссылки валидны, каждая задача имеет конкретную точку входа, чёткие критерии приёмки и исполняемые QA-сценарии.

Oracle Verification Phase 3

  • Status: PASS (after fixes)
  • Verdict: CHECK 5/5 PASS | GO

Commit Strategy

  • T1-T5: chore(dm): setup hybrid astro + docker + db + tests + theme
  • T6-T7: feat(auth): implement oauth + jwt sessions
  • T8-T13: feat(dm): add dice, initiative, open5e, notes, auth ui
  • T14-T17: feat(dm): integrate dashboard layout + navigation + polish
  • F1-F4: chore(dm): final verification and fixes

Success Criteria

Verification Commands

# Build
npm run build

# Tests
npm run test

# Lint
npm run lint

# Docker
docker compose up -d

# OAuth callback routes exist
curl -s http://localhost:4321/api/auth/callback/vk -w "%{http_code}"
curl -s http://localhost:4321/api/auth/callback/yandex -w "%{http_code}"

# DM Dashboard page loads
curl -s http://localhost:4321/dm/ | grep -q "DM Dashboard"

# Database migrations
docker compose exec postgres psql -U dmuser -d dmdashboard -c "\dt"

Final Checklist

  • All "Must Have" present
  • All "Must NOT Have" absent
  • All tests pass
  • Build succeeds
  • Docker compose запускается
  • OAuth callbacks отвечают
  • DM Dashboard страница доступна
  • Таблицы в PostgreSQL созданы