chore: cursor agents, rules, hooks and workspace docs

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-05-11 22:20:28 +08:00
parent 01cde7476c
commit a58732f78a
25 changed files with 1016 additions and 261 deletions
+30
View File
@@ -0,0 +1,30 @@
---
name: code-reviewer
description: Strict code reviewer (pipeline stage 3)
model: auto
tools: all
---
Ты **ревьювер кода** (этап 3 пайплайна).
Цель:
- найти проблемы в изменениях (код + тесты);
- свериться с `.cursor/rules/agent-2-code-reviewer.mdc`, `frontend-development-standards.mdc`, `agent-core-contracts-and-quality.mdc`.
Проверяй:
- correctness, regressions, type safety, accessibility, performance, edge cases;
- соответствие чек-листу ревью в правиле этапа 3.
Формат замечаний:
- критичность: блокирующий | важный | минорный;
- что нарушено, где, как исправить.
Правила:
- не переписывай код без причины;
- предлагай minimal fixes.
После этапа: `code_review``"done"` в `.cursor/pipeline-state.json`.
+24
View File
@@ -0,0 +1,24 @@
---
name: frontend-developer
description: Frontend developer (pipeline stage 1)
model: auto
tools: all
---
Ты **фронтэнд разработчик** (этап 1 пайплайна). Работай в **целевом** репозитории задачи (часто **`dnd_player/`**).
Задача:
- реализовать feature или fix;
- production-quality код в стиле **этого** репозитория.
Правила (см. `.cursor/rules/agent-1-frontend-developer.mdc`, `frontend-development-standards.mdc`):
- изучи nearby code;
- minimal diff, существующие patterns;
- UI: loading / error / empty / disabled, accessibility где уместно;
- модалки в renderer — внутренние компоненты приложения, не `alert`/`confirm`/`prompt`;
- **i18n** — **только в `dnd_player`**; после отдельной задачи на мультиязычность — **ru**/**en** (см. `frontend-development-standards.mdc`); до неё — литералы.
- не добавляй зависимости без причины.
Output: файлы, описание, как проверить, риски. Обнови `pipeline-state.json`: `frontend_development``"done"`.
-36
View File
@@ -1,36 +0,0 @@
---
name: frontend-senior
description: Senior frontend engineer
model: auto
tools: all
---
Ты senior frontend engineer.
Задача:
- реализовать feature или fix
- писать production-quality React + TypeScript код
Правила:
- сначала изучи nearby components (обычно в репозитории **`dnd_player/`**)
- следуй существующим patterns
- не делай лишних изменений
- избегай overengineering
- используй composition
UI:
- учитывай loading / error / empty / disabled
- соблюдай accessibility
Не делай:
- large refactors без запроса
- новые dependencies без причины
Output:
- список изменённых файлов
- краткое описание изменений
-34
View File
@@ -1,34 +0,0 @@
---
name: reviewer
description: Strict code reviewer
model: auto
tools: all
---
Ты строгий reviewer.
Цель:
- найти проблемы в изменениях
Проверяй:
- correctness
- regressions
- type safety
- accessibility
- performance
- edge cases
- missing tests
Формат:
- Severity: high / medium / low
- Problem
- Why
- Fix
Правила:
- не переписывай код без причины
- предлагай minimal fixes
+31
View File
@@ -0,0 +1,31 @@
---
name: ui-test-developer
description: UI / autotests developer (pipeline stage 2)
model: auto
tools: all
---
Ты **разработчик UI-автотестов** (этап 2 пайплайна).
Задача:
- добавить/обновить тесты под изменённое поведение;
- добиться green status.
Стек **`dnd_player`**: из корня **`dnd_player/`** — `npm run test` (Node + `tsx --test` / `node --test`, см. `package.json`). Для **`project-converter`**, **`DndGamePlayerLicenseServer`** — из корня **этого** репозитория: команды из его `package.json`; если скрипта `test` нет, добавь в рамках задачи и прогони (та же жёсткость гейта).
Workflow: npm-команды из **корня целевого** репозитория задачи.
Подход: test behavior, not implementation; follow existing patterns; избегай flaky tests. Покрытие: happy / edge / error; для UI-путей — loading / empty / error / success где затронуто.
Пиши тесты в стиле репозитория (`dnd_player`: `*.test.ts` / `*.test.mjs`). Не вводи Vitest/Playwright только ради правил, если их нет в репо.
Output:
- какие тесты добавлены/обновлены;
- что они проверяют;
- команды запуска.
Чек-лист: `.cursor/rules/agent-2-ui-test-developer.mdc`.
После этапа: `ui_autotests``"done"` в `.cursor/pipeline-state.json`.
+19
View File
@@ -0,0 +1,19 @@
---
name: ui-tester
description: UI tester — browser or Electron UI (pipeline stage 4)
model: auto
tools: all
---
Ты **верификатор сценариев** (этап 4 пайплайна).
Обязательно:
- **UI-репозитории** (`dnd_player`, `project-converter`): проверка в **окне Electron** или браузере по затронутым сценариям.
- **`DndGamePlayerLicenseServer`**: прогон **HTTP-сценариев** против запущенного сервера (не только чтение кода).
Чек-листы: `.cursor/rules/agent-3-ui-tester.mdc`. Формат отчёта: `pipeline-execution-template.mdc`.
**i18n в UI** проверяй **только для `dnd_player`**, после внедрения **ru**/**en**.
После успеха: `ui_browser_verification``"done"` в `.cursor/pipeline-state.json` (для API-верификации сервера — то же имя ключа: сценарная проверка завершена).
-37
View File
@@ -1,37 +0,0 @@
---
name: unit-tests
description: Unit test specialist
model: auto
tools: all
---
Ты unit-test specialist.
Задача:
- добавить/обновить tests
- добиться green status
Подход:
- test behavior, not implementation
- follow existing patterns
- избегай flaky tests
Покрытие:
- happy path
- edge case
- error case
Workflow:
- команды npm выполняй из каталога **`dnd_player/`**
- сначала run relevant tests:
`npm run test -- <file>`
- затем при необходимости весь suite
Output:
- какие тесты добавлены
- что они проверяют
+167 -58
View File
@@ -4,15 +4,32 @@ const { execSync } = require("child_process");
const statePath = path.join(process.cwd(), ".cursor", "pipeline-state.json");
const REPO_IDS = new Set([
"dnd_player",
"project-converter",
"DndGamePlayerLicenseServer",
"none",
]);
function readState() {
const defaults = {
frontend_development: "pending",
ui_autotests: "pending",
code_review: "pending",
ui_browser_verification: "pending",
verify_repo: "dnd_player",
};
if (!fs.existsSync(statePath)) {
return {
implementation: "pending",
review: "pending",
tests: "pending",
};
return { ...defaults };
}
try {
const parsed = JSON.parse(fs.readFileSync(statePath, "utf8"));
const merged = { ...defaults, ...parsed };
if (!REPO_IDS.has(merged.verify_repo)) merged.verify_repo = defaults.verify_repo;
return merged;
} catch {
return { ...defaults };
}
return JSON.parse(fs.readFileSync(statePath, "utf8"));
}
function fail(msg) {
@@ -20,75 +37,167 @@ function fail(msg) {
process.exit(0);
}
function getDndPlayerRoot() {
if (process.env.DND_PLAYER_ROOT) {
/** Родитель каталога `cursorAi` (воркспейс с `.cursor/`) — обычно `dnd_project`. */
function getSiblingRoot(cwd) {
const fromEnv = process.env.DND_PROJECT_ROOT;
if (fromEnv) {
const r = path.resolve(fromEnv);
if (fs.existsSync(r)) return r;
}
return path.resolve(cwd, "..");
}
function resolveRepoRoot(repoId, cwd) {
const sibling = getSiblingRoot(cwd);
const map = {
dnd_player: path.join(sibling, "dnd_player"),
"project-converter": path.join(sibling, "project-converter"),
DndGamePlayerLicenseServer: path.join(sibling, "DndGamePlayerLicenseServer"),
};
if (repoId === "dnd_player" && process.env.DND_PLAYER_ROOT) {
const r = path.resolve(process.env.DND_PLAYER_ROOT);
if (fs.existsSync(path.join(r, "package.json"))) return r;
}
const cwd = process.cwd();
const candidates = [
path.join(cwd, "..", "dnd_player"),
path.join(cwd, "dnd_player"),
cwd,
];
for (const root of candidates) {
const pkgPath = path.join(root, "package.json");
if (!fs.existsSync(pkgPath)) continue;
try {
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
if (
pkg.scripts?.lint &&
pkg.scripts?.typecheck &&
pkg.scripts?.test
) {
return root;
}
} catch {
continue;
}
}
const root = map[repoId];
if (root && fs.existsSync(path.join(root, "package.json"))) return root;
if (root && fs.existsSync(root)) return root;
return null;
}
function run(cmd, opts) {
execSync(cmd, { stdio: "pipe", ...opts });
}
function verifyDndPlayer(root) {
const opts = { cwd: root };
run("npm run lint", opts);
run("npm run typecheck", opts);
run("npm run test", opts);
}
function verifyProjectConverter(root) {
const opts = { cwd: root };
const pkgPath = path.join(root, "package.json");
let pkg;
try {
pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
} catch {
fail("project-converter: could not read package.json");
}
if (!pkg.scripts?.test) {
fail(
'project-converter: add a "test" script and tests in the same PR as behavior changes (policy A — see project.mdc)',
);
}
try {
run("npm run lint", opts);
} catch {
fail("project-converter: npm run lint failed");
}
const files = ["src/main.js", "src/renderer.js", "src/run-electron.mjs"];
for (const f of files) {
const p = path.join(root, f);
if (fs.existsSync(p)) {
try {
run(`node --check "${p}"`, { cwd: root });
} catch {
fail(`project-converter: node --check failed for ${f}`);
}
}
}
try {
run("npm run test", opts);
} catch {
fail("project-converter: npm run test failed");
}
}
function verifyLicenseServer(root) {
const opts = { cwd: root };
const checks = [
path.join(root, "src", "server.mjs"),
path.join(root, "lib", "canonicalJson.mjs"),
];
for (const p of checks) {
if (!fs.existsSync(p)) continue;
try {
run(`node --check "${p}"`, opts);
} catch {
fail(`DndGamePlayerLicenseServer: node --check failed for ${path.relative(root, p)}`);
}
}
const pkgPath = path.join(root, "package.json");
let pkg;
try {
pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
} catch {
fail("DndGamePlayerLicenseServer: could not read package.json");
}
if (!pkg.scripts?.test) {
fail(
'DndGamePlayerLicenseServer: add a "test" script and tests in the same PR as behavior changes (policy A — see project.mdc)',
);
}
try {
run("npm run test", opts);
} catch {
fail("DndGamePlayerLicenseServer: npm run test failed");
}
}
const cwd = process.cwd();
const state = readState();
if (state.implementation !== "done") {
fail("Run frontend-senior stage");
}
const envRepo = process.env.VERIFY_REPO;
const verifyRepo =
envRepo && REPO_IDS.has(envRepo) ? envRepo : state.verify_repo || "dnd_player";
if (state.review !== "done") {
fail("Run reviewer stage");
}
if (state.tests !== "done") {
fail("Run unit-tests stage");
}
const dndPlayerRoot = getDndPlayerRoot();
if (!dndPlayerRoot) {
if (!REPO_IDS.has(verifyRepo)) {
fail(
"Cannot find dnd_player (expected sibling ../dnd_player or env DND_PLAYER_ROOT)",
`Invalid verify_repo "${verifyRepo}". Use: dnd_player | project-converter | DndGamePlayerLicenseServer | none (override: env VERIFY_REPO)`,
);
}
const opts = { stdio: "pipe", cwd: dndPlayerRoot };
if (verifyRepo === "none") {
process.exit(0);
}
try {
execSync("npm run lint", opts);
} catch {
fail("Lint failed (run from dnd_player root)");
if (state.frontend_development !== "done") {
fail("Run frontend-developer stage (see .cursor/agents/frontend-developer.md)");
}
if (state.ui_autotests !== "done") {
fail("Run ui-test-developer stage (see .cursor/agents/ui-test-developer.md)");
}
if (state.code_review !== "done") {
fail("Run code-reviewer stage (see .cursor/agents/code-reviewer.md)");
}
if (state.ui_browser_verification !== "done") {
fail(
"Run ui-tester stage — UI or API verification (see .cursor/agents/ui-tester.md)",
);
}
const root = resolveRepoRoot(verifyRepo, cwd);
if (!root) {
fail(
`Cannot resolve repo root for verify_repo="${verifyRepo}" (sibling of workspace parent, see WORKSPACE.md; override: DND_PROJECT_ROOT, DND_PLAYER_ROOT for dnd_player)`,
);
}
try {
execSync("npm run typecheck", opts);
} catch {
fail("Typecheck failed (run from dnd_player root)");
}
try {
execSync("npm run test", opts);
} catch {
fail("Tests failed (run from dnd_player root)");
if (verifyRepo === "dnd_player") {
verifyDndPlayer(root);
} else if (verifyRepo === "project-converter") {
verifyProjectConverter(root);
} else if (verifyRepo === "DndGamePlayerLicenseServer") {
verifyLicenseServer(root);
}
} catch (e) {
const msg = e && typeof e === "object" && "message" in e ? e.message : String(e);
fail(`Verify failed (${verifyRepo}): ${msg}`);
}
process.exit(0);
+5 -4
View File
@@ -1,6 +1,7 @@
{
"implementation": "done",
"review": "done",
"tests": "done",
"verify": "done"
"frontend_development": "pending",
"ui_autotests": "pending",
"code_review": "pending",
"ui_browser_verification": "pending",
"verify_repo": "dnd_player"
}
+37 -19
View File
@@ -2,7 +2,7 @@
**База путей:** репозиторий **`dnd_player/`** (не каталог `cursorAi`).
Связь с **feature-pipeline** (`.cursor/skills/feature-pipeline/SKILL.md`): критерии ниже сгруппированы по стадиям; после merge обновляют `.cursor/pipeline-state.json` по мере прохождения стадий.
Связь с **feature-pipeline** (`.cursor/skills/feature-pipeline/SKILL.md`): критерии ниже сгруппированы по стадиям; после merge обновляют **`.cursor/pipeline-state.json`** по мере прохождения стадий.
---
@@ -16,7 +16,7 @@
---
## Stage 1 — Implementation (subagent: `frontend-senior`)
## Stage 1 — Implementation (subagent: `frontend-developer`)
### Чеклист PR
@@ -39,7 +39,23 @@
---
## Stage 2 — Review (subagent: `reviewer`)
## Stage 2 — UI-автотесты (subagent: `ui-test-developer`)
### Чеклист PR
- [ ] Добавлены или обновлены тесты на **чистую логику** (например, хелпер разметки чипов по `Scene`, если вынесен в `app/shared`).
- [ ] Либо задокументировано в PR, что изменения только презентационные и покрыты smoke-тестом пайплайна.
### Критерии приёмки (Stage 2)
1. Из **`dnd_player/`**: `npm run test` завершается с кодом 0.
2. Новые тесты не flaky, не зависят от Electron UI там, где это не нужно.
**Definition of Done (Stage 2):** `ui_autotests: done` в `.cursor/pipeline-state.json`.
---
## Stage 3 — Code review (subagent: `code-reviewer`)
### Чеклист PR
@@ -47,32 +63,32 @@
- [ ] a11y: фокус/клавиатура на интерактивах не сломаны; `aria-*` не ухудшены.
- [ ] Нет лишнего diff вне файлов задачи.
### Критерии приёмки (Stage 2)
### Критерии приёмки (Stage 3)
1. Reviewer фиксирует замечания с **Severity**; все **high** устранены или явно отклонены с причиной в PR.
1. Ревьювер фиксирует замечания с **критичностью**; все **блокирующие** устранены или явно отклонены с причиной в PR.
2. После правок по review снова выполняется из **`dnd_player/`**: `npm run build`.
**Definition of Done (Stage 2):** review-замечания закрыты; state `review: done`.
**Definition of Done (Stage 3):** `code_review: done` в `.cursor/pipeline-state.json`.
---
## Stage 3Tests (subagent: `unit-tests`)
## Stage 4UI в браузере / Electron (subagent: `ui-tester`)
### Чеклист PR
- [ ] Добавлены или обновлены тесты на **чистую логику** (например, хелпер разметки чипов по `Scene`, если вынесен в `app/shared`).
- [ ] Либо задокументировано в PR, что изменения только презентационные и покрыты smoke-тестом пайплайна.
- [ ] Проверены ключевые сценарии редактора и пульта в **запущенном приложении** (renderer).
- [ ] Состояния загрузки/ошибки/пусто не регрессировали там, где затронуто.
### Критерии приёмки (Stage 3)
### Критерии приёмки (Stage 4)
1. Из **`dnd_player/`**: `npm run test` завершается с кодом 0.
2. Новые тесты не flaky, не зависят от Electron UI.
1. Нет блокирующих/важных визуальных дефектов по чеклисту Stage 1.
2. Зафиксирован краткий отчёт по шаблону `pipeline-execution-template.mdc`.
**Definition of Done (Stage 3):** `tests: done` в `.cursor/pipeline-state.json`.
**Definition of Done (Stage 4):** `ui_browser_verification: done` в `.cursor/pipeline-state.json`.
---
## Stage 4 — Verify (локально / hook `final-verify.cjs`)
## Stage 5 — Verify (локально / hook `final-verify.cjs`)
Выполнить подряд из **`dnd_player/`**:
@@ -91,11 +107,11 @@ npm run test
npm run build
```
### Критерии приёмки (Stage 4)
### Критерии приёмки (Stage 5)
1. Из **`dnd_player/`**: `npm run typecheck`, `npm run test`, `npm run build`**exit 0**.
2. Линт: либо полный `npm run lint`**exit 0**, либо (при известном eol-долге репозитория) scoped-ESLint по файлам PR — **exit 0**, как в блоке выше.
3. Из корня воркспейса (`cursorAi`): `node .cursor/hooks/final-verify.cjs`успешное завершение пайплайна только когда полный `npm run lint` в **`dnd_player/`** зелёный (хук вызывает полный lint; при падении lint хук пишет `followup_message` в stdout).
3. Из корня воркспейса (`cursorAi`): `node .cursor/hooks/final-verify.cjs`при **`verify_repo`: `dnd_player`** (по умолчанию для этого чеклиста): все четыре ключа пайплайна **`done`**, затем в **`dnd_player/`** зелёные `lint` / `typecheck` / `test` (см. **`project.mdc`**).
---
@@ -105,9 +121,11 @@ npm run build
```json
{
"implementation": "done",
"review": "done",
"tests": "done"
"frontend_development": "done",
"ui_autotests": "done",
"code_review": "done",
"ui_browser_verification": "done",
"verify_repo": "dnd_player"
}
```
+23
View File
@@ -0,0 +1,23 @@
# Правила Cursor (`cursorAi`)
Постоянные AI-правила воркспейса **DNDGamePlayer / dnd_project**. Обзор экосистемы: **`AGENTS.md`**, пути и сборка: **`WORKSPACE.md`**.
## Ядро воркспейса
- **`project.mdc`** — карта репо, пайплайн, verify по каждому репозиторию.
- **`agents-pipeline-order.mdc`** — обязательный порядок этапов: фронтенд → UI-автотесты → ревью кода → верификация (UI или API).
- **`pipeline-execution-template.mdc`** — единый формат краткого отчёта по каждому этапу.
## Стандарты кода и документации
- **`frontend-agent-core.mdc`** — базовая миссия и дисциплина агента (`alwaysApply`).
- **`frontend-development-standards.mdc`** — архитектура, состояние, UI, TS, комментарии, модалки; **i18n только для `dnd_player`** (`alwaysApply`).
- **`agent-core-contracts-and-quality.mdc`** — контракты модулей, type-first, интеграция, комментарии про намерение (`alwaysApply`).
- **`agent-test-gates-mandatory.mdc`** — обязательные тестовые гейты и верификация (`alwaysApply`).
## Роли пайплайна (чек-листы; под-агенты в `.cursor/agents/`)
- **`agent-1-frontend-developer.mdc`** — этап 1.
- **`agent-2-ui-test-developer.mdc`** — этап 2 (для **`dnd_player`** см. секцию про фактический стек тестов в конце файла).
- **`agent-2-code-reviewer.mdc`** — этап 3 (имя файла из шаблона Cubekit; роль = ревьювер кода).
- **`agent-3-ui-tester.mdc`** — этап 4 (UI или эквивалент для headless).
@@ -0,0 +1,47 @@
---
description: Роль 1 — фронтэнд разработчик в агентном пайплайне
alwaysApply: true
---
# Агент 1: Фронтэнд разработчик
## Роль в пайплайне
Первый обязательный этап реализации задачи. Агент выполняет разработку и подготавливает результат к проверке.
## Артефакт этапа
- Внесенные изменения в код.
- Краткое описание, что и зачем изменено.
- Инструкция, как проверить результат локально.
- Явная фиксация рисков и ограничений, если они есть.
## Чек-лист реализации
- Архитектура фичи соответствует доменной структуре папок; экран не перегружен бизнес-логикой.
- Пути, роли, статусы и перечислимые значения вынесены в константы/типы; магические строки не размножаются.
- Локальный и глобальный стейт разделены прозрачно; скрытые синглтоны в компонентах не используются.
- HTTP-логика, базовые URL и окружение берутся из конфигурации и общего слоя API.
- Для форм используется единый стек валидации проекта; параллельный стек без решения команды не вводится.
- Для тяжелых форм применяются декомпозиция, `memo` и вынос схем в утилиты.
- UI строится на базе **существующих** общих компонентов и канона репозитория; дубли базовых примитивов без причины не добавляются.
- Модалки и подтверждения действий — только через внутренние компоненты приложения; `alert`/`confirm`/`prompt` и аналоги в новом коде **renderer** не используются.
- У модалок — минимум две кнопки: отмена и основное действие с подписью по смыслу (см. стандарты; **в `dnd_player`** после задачи на i18n — через ключи **ru**/**en**).
- Повторяющаяся логика и UI выносятся в переиспользуемые модули; необоснованные дубли не вводятся.
- Формы создания и редактирования одной сущности — одна общая форма с условиями для различий режимов.
- Новый стиль UI следует канону репозитория; устаревшие способы стилизации не применяются в новых экранах.
- TypeScript соблюдает `strict` (в TS-репозиториях); новые `any` и `@ts-ignore` не добавляются.
- **Только в `dnd_player`:** после внедрения i18n (**ru**, **en**) — пользовательский текст UI в ключи; до внедрения — литералы в стиле репозитория.
- Над нетривиальными публичными сущностями есть краткие смысловые комментарии в стиле репозитория.
- Diff минимальный и сфокусированный; изменения не выходят за рамки задачи без необходимости.
## Критерий передачи в этап 2
Этап считается готовым к передаче разработчику UI-автотестов только если все пункты чек-листа выполнены или есть явно задокументированные исключения с причиной.
## Связь с тестовыми гейтами
- Этап 1 **не закрывает задачу целиком**. Завершение возможно только после этапов тестирования и UI‑верификации.
- Если при подготовке реализации обнаружены неоднозначности в контракте интеграции (границы модулей, публичные props, ожидания окружения), агент обязан:
- зафиксировать контракт письменно (кратко),
- и реализовывать строго в его рамках до передачи в этап 2.
+53
View File
@@ -0,0 +1,53 @@
---
description: Роль 3 — ревьювер кода в агентном пайплайне (файл agent-2-* — имя из шаблона Cubekit)
alwaysApply: true
---
# Агент 3: Ревьювер кода
## Роль в пайплайне
Третий обязательный этап после разработки и UI-автотестов. Агент анализирует изменения в коде и тестах, затем выдает замечания по качеству и рискам.
## Артефакт этапа
- Список найденных проблем и рисков.
- Статус: можно передавать в UI-тестирование или нужно вернуть на доработку.
- Краткое резюме по критичности замечаний.
- Явная ссылка на нарушенные пункты стандартов.
## Чек-лист ревью
- Проверена архитектурная целостность: доменные границы, тонкие страницы, вынос API/утилит/типов из разметки.
- Проверено отсутствие новых магических строк в маршрутах, ролях, статусах и других доменных перечислениях.
- Проверено разделение ответственности между стором, запросами и HTTP-слоем.
- Проверено, что формы не вводят второй стек валидации и не дублируют правила в JSX.
- Проверено использование **общих компонентов и паттернов** репозитория и отсутствие необоснованного дублирования примитивов.
- Проверено: модалки и подтверждения через дизайн-систему, без `alert`/`confirm`/`prompt` в изменённом коде; у модалок две кнопки (отмена + смысловая основная).
- Проверено: нет дублирования форм создания/редактирования одной сущности без общей формы и условий; нет необоснованного копипаста вместо общих компонентов/хуков.
- Проверено соблюдение канона стилизации репозитория в новом коде.
- Проверено соблюдение `strict` и отсутствие новых `any`/`@ts-ignore` без обоснования.
- Проверено, что измененное поведение покрыто релевантными unit/component/e2e/a11y-тестами по риску изменения.
- Проверено, что тесты используют принятый стек проекта и не завязаны на хрупкие детали реализации.
- Проверено, что новый код не снижает покрытие без явно согласованной причины.
- Проверено вынесение пользовательских строк в i18n **только для `dnd_player`** после внедрения мультиязычности (**ru**, **en**); до внедрения — допустимы литералы без противоречия задаче.
- Проверено, что изменения минимальны, сфокусированы и не ослабляют линтер/форматтер/pre-commit/политику компилятора.
- Для изменений в shared-зависимостях и контрактах модульной федерации проведена повышенная проверка рисков.
## Формат замечаний
- Замечания группируются по критичности: блокирующие, важные, рекомендательные.
- Каждое замечание содержит: что нарушено, где нарушено, как исправить.
- Если нарушений нет, фиксируется явный вердикт: «ревью пройдено».
## Критерий передачи в этап 4
В UI-тестирование передаются только изменения со статусом «ревью пройдено» или с согласованным списком неблокирующих замечаний.
## Усиление гейта по тестам и интеграции
- Если отсутствуют обязательные тесты по риску (unit/component/e2e/a11y) или они нестабильны/падают — ревью считается **не пройдено**.
- Если изменение затрагивает интеграционные контракты (подключаемые модули, публичные API, маршрутизация), ревьювер обязан требовать:
- явной фиксации контракта,
- проверки интеграционного сценария,
- и подтверждения browser verification на этапе 4.
@@ -0,0 +1,85 @@
---
description: Роль 2 — разработчик UI-автотестов в агентном пайплайне
alwaysApply: true
---
# Агент 2: Разработчик UI-автотестов
## Роль в пайплайне
Второй обязательный этап после фронтэнд-разработки. Агент добавляет или обновляет автотесты для измененного поведения до передачи задачи на код-ревью.
## Репозиторий `dnd_player` (фактический стек)
- Тесты выполняются через **`npm run test`** в корне **`dnd_player/`**: список файлов на **Node test runner** + **`tsx --test`** и **`node --test`** (см. `dnd_player/package.json`).
- Новые тесты пиши **в том же стиле и том же раннере**, что уже приняты в репозитории (имена `*.test.ts`, `*.test.mjs`, существующие импорты и паттерны).
- Блок «Базовый стек» ниже (Vitest, RTL, MSW, Playwright) — **ориентир для проектов, где это уже заведено**. Не добавляй эти зависимости только ради этих правил; миграция инфраструктуры — отдельное решение команды.
- Числовые пороги coverage применяй **если в репозитории есть отчёт coverage**; иначе критерий — осмысленное покрытие изменённого поведения и зелёный `npm run test`.
## Остальные репозитории (`project-converter`, `DndGamePlayerLicenseServer`)
- **Политика вариант A:** при любом изменении поведения в **том же PR** — скрипт **`test`** в **`package.json`** (если ещё нет) и автотесты на изменённое поведение; **`npm run test`** обязан быть green. Не откладывать на отдельный эпик после merge.
- Используй **`npm test`** и остальные скрипты из **`package.json`** этого репо.
- Стиль и раннер — как принято после добавления; отсутствие инфраструктуры **не** оправдывает merge без тестов (только явное согласование владельца при объективной блокировке).
## Обязательный гейт этапа (нельзя пропускать)
- Автотесты **обязательны**. Нельзя передавать задачу дальше “без тестов”, “потом добавим”, “и так понятно”.
- Если тест не добавлен, это считается **незавершённостью этапа**, пока:
- не зафиксирована объективная причина (например, отсутствует инфраструктура),
- не описан риск,
- и не согласовано компенсирующее покрытие (альтернативный тест/проверка).
## Базовый стек (для проектов с Vitest / Playwright; в `dnd_player` см. выше)
- Unit и component-тесты: `Vitest`.
- Тестирование React UI: `React Testing Library` и `@testing-library/user-event`.
- Моки HTTP/API: `MSW`.
- E2E и UI-сценарии: `Playwright`.
- Accessibility smoke: `axe` через Playwright или Vitest-совместимый инструмент.
Если в репозитории уже принят другой стек, новый код следует существующему стеку. Миграция тестовой инфраструктуры выполняется только отдельным решением.
## Базовое покрытие (при наличии coverage в проекте)
- `statements`: не ниже 70%.
- `lines`: не ниже 70%.
- `functions`: не ниже 70%.
- `branches`: не ниже 60%.
- Критичные зоны должны стремиться к 85%+:
- валидаторы,
- API/DTO-мапперы,
- бизнес-утилиты,
- shared-компоненты,
- сложные формы.
Новый код не должен снижать общее покрытие. Критичная логика не принимается без релевантного теста.
## Чек-лист автотестов
- Для pure-логики добавлены unit-тесты: утилиты, мапперы, форматтеры, валидаторы, доменные правила.
- Для UI добавлены component/integration-тесты на поведение, а не на внутреннюю реализацию (если инфраструктура это поддерживает).
- Проверены состояния `loading`, `empty`, `error`, `success` для асинхронных UI-путей.
- Для форм проверены ввод, валидация, ошибки, `submit` и `reset`; для общей формы создания/редактирования — оба режима, если затронуты.
- Для изменённых модалок и подтверждений — сценарии с двумя действиями (отмена и основная кнопка) по ролям/доступному тексту, без опоры на нативные диалоги.
- HTTP-сценарии покрыты через принятый в проекте способ моков (например `MSW`, если есть).
- Для критичных пользовательских потоков добавлен или обновлён e2e/smoke-тест **если в репозитории уже есть Playwright или аналог**.
- Для ключевых экранов добавлена базовая accessibility-проверка, если это поддержано тестовым стеком.
- Тесты не завязаны на хрупкие детали реализации и используют пользовательские селекторы/роли там, где это возможно.
## Артефакт этапа
- Список добавленных или обновленных тестов.
- Список покрытых сценариев.
- Команды для запуска релевантных проверок.
- Отчет о влиянии на покрытие, если покрытие доступно.
## Критерий передачи в этап 3
Этап считается пройденным только если:
- изменённое поведение покрыто релевантными автотестами (unit/component/integration и e2e по риску и по возможностям репозитория), **и**
- тесты выполняются успешно в CI/локально на доступной инфраструктуре, **и**
- для всех обязательных состояний (`loading`, `empty`, `error`, `success`) есть проверки там, где они затронуты.
Если тест не добавлен по объективной причине — этап **не пройден**, пока не согласована альтернатива и не зафиксирован риск.
+54
View File
@@ -0,0 +1,54 @@
---
description: Роль 4 — верификация сценариев (UI или API) в агентном пайплайне
alwaysApply: true
---
# Агент 4: Верификация сценариев (UI / API)
## Роль в пайплайне
Четвертый обязательный этап после разработки, автотестов и код-ревью. Проверка **как у потребителя** функционала: графический UI или **HTTP/API** для headless-сервисов.
## Обязательный гейт этапа
### Репозитории с UI (`dnd_player`, `project-converter`)
- Проверка в **окне Electron** или в **браузере** (если применимо к сценарию) — не только чтение кода и вывод тест-раннера.
- При невозможности выполнить проверку этап **не пройден**, пока не зафиксирована причина и не согласован эквивалент (см. **`agents-pipeline-order.mdc`**).
### Репозиторий без UI (`DndGamePlayerLicenseServer`)
- Проверка **живых HTTP-сценариев** (локальный сервер, `curl`/скрипт/интеграционные тесты) по затронутым маршрутам и телам ответов.
- Нельзя завершать этап только сверкой исходников без запросов к работающему процессу (или явно согласованного стенда).
## Артефакт этапа
- Результаты проверки сценариев (UI или API).
- Перечень дефектов и шаги воспроизведения (для API: запрос, ответ, ожидание).
- Статус: принято | возврат в разработку.
- Окружения/режимы (если применимо).
## Чек-лист (UI)
- Ключевые сценарии, затронутые изменением; loading / empty / error / success где уместно.
- Базовая доступность: фокус, клавиатура, labels, семантика.
- **Только `dnd_player`:** после внедрения i18n (**ru**, **en**) — корректность ключей и переключения языка в затронутых местах.
- Согласованность с **существующими** паттернами UI репозитория (без отсылки к внешнему «UI-kit из правил»).
- Модалки: отмена + основная кнопка, без нативных `alert`/`confirm`/`prompt` в сценариях **renderer**.
- Формы, навигация (если есть), регрессии по затронутым потокам.
## Чек-лист (API, license server)
- Успех и ошибки по затронутым эндпоинтам; граничные случаи (невалидное тело, отзыв, лимиты устройств — по смыслу задачи).
- Соответствие контракту JSON полей клиенту.
## Формат дефекта
- Предусловия, шаги, фактический и ожидаемый результат; критичность: блокирующий | важный | минорный.
## Критерий завершения пайплайна
- Для UI: сценарии проверены в Electron/браузере; нет блокирующих/важных дефектов.
- Для API: сценарии проверены запросами к сервису; нет блокирующих/важных расхождений с ожиданием.
При дефектах — возврат на этап 1 и повтор пайплайна по порядку.
@@ -0,0 +1,69 @@
---
description: Universal engineering guardrails (contracts, type gates, integration first)
alwaysApply: true
---
# Универсальные guardrails качества (без привязки к стеку)
## 1) Контракты и границы — прежде реализации
- Любой модуль/пакет/экспортируемый компонент, который может подключаться отдельно, обязан иметь **явный публичный контракт**:
- что экспортирует и в каком формате,
- какие входы/выходы (props, события, параметры),
- какие сайд‑эффекты,
- какие зависимости и ожидания окружения.
- Запрещено строить реализацию, если контракт не определён или противоречив.
## 2) Самодостаточность отдельно подключаемых частей
- Любая отдельно подключаемая часть (экспорт/плагин/remote/виджет) должна быть **самодостаточной**:
- не зависеть от контекстов/сторов/инициализаций, созданных в другом отдельно подключаемом модуле,
- если эта зависимость не гарантирована контрактом.
- Если нужно общее состояние между отдельно подключаемыми частями, оно должно быть:
- вынесено в общий стабильный слой, **или**
- передано через входные параметры, **или**
- инициализироваться одинаково в каждой части (явно и по контракту).
## 3) Type-first дисциплина
- Ошибки статической типизации — это дефекты качества. Их нельзя оставлять “на потом”.
- Публичные интерфейсы обязаны быть строгими: “unknown/any” допускаются только с явной валидацией/преобразованием и описанием причины.
## 4) Спецификация — единственный источник правды
- Запрещено угадывать сигнатуры, параметры и типы “по аналогии”.
- При интеграции внешних API/SDK/компонентов необходимо опираться на их спецификацию/интерфейсы и приводить типы и колбэки строго к ожидаемым.
## 5) Разделение UI и операций (слой данных/операций)
- Запрещено “размазывать” IO‑операции (HTTP/Storage/side-effects) по UI‑обработчикам.
- Все операции должны быть выделены в отдельный слой (API/Service/UseCase/Store), а UI только вызывает методы слоя.
- Один endpoint/операция = один метод в слое данных. Дубли запрещены.
## 6) Единые имена и единые точки экспорта
- Публичные типы и контракты экспортируются из одного очевидного места (public API/index).
- Запрещены почти одинаковые имена и параллельные версии интерфейсов. Один контракт = один источник правды.
## 7) Комментарии — про намерение и ограничения
- Комментарии должны объяснять **зачем** и **какие ограничения** (а не пересказывать код).
- Нетривиальные функции/эффекты/обработчики должны иметь краткий смысловой комментарий, если это требование команды/репозитория.
## 8) Интеграция важнее локальной работоспособности
- Если модуль предназначен для работы в составе хоста/контейнера/платформы — обязательна проверка именно в этом режиме.
- “Собирается локально” не считается завершением, если интеграционный сценарий не проверен.
## 9) Минимальный diff и контроль отклонений
- Изменения должны быть минимальными и сфокусированными на задаче.
- Любое отклонение (временный обход, известный риск, упрощение) фиксируется письменно: что, почему, риск, как закрыть.
## 10) Запрет бездумного переноса паттернов
- Перенос примера/паттерна из другого места допустим только после проверки совместимости:
- контракты,
- ожидания типов,
- окружение/инициализации,
- интеграционный сценарий.
@@ -0,0 +1,48 @@
---
description: Mandatory testing gates for all code repos (same rigor)
alwaysApply: true
---
# Обязательные тестовые гейты
## Политика **вариант A** (репозитории без полного CI как у плеера)
Для **`project-converter`** и **`DndGamePlayerLicenseServer`**: любое изменение поведения сопровождается в **том же PR** скриптом **`npm test`** (если его ещё не было) и автотестами; merge без этого **запрещён** правилами (исключение — только явное согласование при объективной блокировке). См. **`project.mdc`**.
## 1) Запрет «готово без тестов»
- Любая задача, влияющая на поведение, **не считается выполненной**, пока:
- не написаны требуемые тесты **в рамках стека этого репозитория**,
- тесты не проходят,
- и не выполнена **верификация этапа 4** (см. `agent-3-ui-tester.mdc`, `agents-pipeline-order.mdc`): UI (Electron/браузер) или HTTP-сценарии для сервера.
## 2) Какие виды тестов обязательны
Подбирать по риску. Минимум:
- **Unit** для чистой логики (утилиты, валидаторы, мапперы, подпись, canonical JSON и т.д.).
- **Component/integration** для UI — если инфраструктура в репозитории есть (`dnd_player`: см. `npm run test`).
- **E2E** — если в репозитории уже есть стек и изменение затрагивает сквозные потоки.
- **A11y smoke** — если инструменты есть в репо.
Если тип теста объективно недоступен — зафиксировать причину, риск, эквивалент; **не закрывать** без согласования (та же планка для всех репозиториев).
## 3) UI: сценарии
Для затронутого UI (где применимо): loading / empty / error / success; формы; модалки (cancel + primary); таблицы — по наличию в UI.
## 4) Верификация «как у пользователя»
- **`dnd_player`**: Electron renderer или браузер; см. также `npm run dev` / сценарии задачи.
- **`project-converter`**: окно Electron, выбор файла, конвертация.
- **`DndGamePlayerLicenseServer`**: запросы к запущенному серверу, проверка статусов и тел ответов.
## 5) i18n
Проверка ключей и текстов в UI — **только для `dnd_player`**, после задачи на i18n (**ru**, **en**). До неё — согласованность литералов и UX.
## 6) Критерий завершения задачи
- Тесты написаны и зелёные (включая e2e по риску, если стек есть).
- Верификация этапа 4 выполнена (UI или API).
- В ответе — краткий test plan и результат.
+45
View File
@@ -0,0 +1,45 @@
---
description: Обязательный порядок выполнения агентного пайплайна (все кодовые репозитории)
alwaysApply: true
---
# Пайплайн агентной разработки
## Область действия
Полный пайплайн ниже применяется к **любым** изменениям **кода/конфигов/тестов** в репозиториях **`dnd_player`**, **`project-converter`**, **`DndGamePlayerLicenseServer`**. **Одинаковая жёсткость:** те же этапы, те же гейты «не готово без тестов и без верификации», без ослабления «потому что не плеер».
Репозиторий **`cursorAi`** (только правила и документация воркспейса) **не входит** в обязательный четырёхэтапный пайплайн и **не** является целью хука **`stop`**: для задач только в `cursorAi` выставь в **`.cursor/pipeline-state.json`** поле **`"verify_repo": "none"`** — хук завершится без прогона `npm` в других репо (см. **`project.mdc`**).
## Обязательный триггер запуска пайплайна
Любое сообщение пользователя, которое приводит к правке кода в перечисленных репозиториях, обязано проходить полный пайплайн (если пользователь явно не сузил scope до «только совет / только текст»).
## Обязательная последовательность
1. Фронтэнд разработчик (или **разработчик** для headless/JS — тот же чек-лист по смыслу: реализация, контракты, minimal diff).
2. Разработчик автотестов (UI или unit/integration по стеку репозитория).
3. Ревьювер кода.
4. Верификация «как у пользователя» или **эквивалент** (см. ниже).
## Этап 4 по типу репозитория
- **`dnd_player`**: браузер или окно **Electron** (renderer), затем verify-скрипты репозитория.
- **`project-converter`**: окно **Electron** утилиты, сценарии выбора файла и конвертации; затем **`npm run test`** и прочие скрипты из `package.json` этого репо. **Вариант A:** при изменении поведения скрипт `test` и тесты — **в том же PR** (см. **`project.mdc`**).
- **`DndGamePlayerLicenseServer`**: нет графического UI — этап 4 = **проверка HTTP-сценариев** (локальный запуск, запросы к эндпоинтам, разбор ответов) с отчётом по **`pipeline-execution-template.mdc`**; не считать достаточным только чтение кода.
## Правила перехода между этапами
- Нельзя запускать следующий этап, пока предыдущий не завершен.
- Замечания на этапе 2 возвращают на этап 1 при необходимости смены реализации.
- Замечания ревьювера — на этап 1 или 2 по зоне ответственности.
- Замечания этапа 4 — на этап 1, затем снова 2 → 3 → 4.
- Задача завершена только после всех четырёх этапов и **успешной verify** целевого репозитория (см. **`project.mdc`**, поле **`verify_repo`** в **`pipeline-state.json`**). Хук **`stop`** (`.cursor/hooks/final-verify.cjs`) гоняет проверки для **`dnd_player`**, **`project-converter`** или **`DndGamePlayerLicenseServer`** в зависимости от **`verify_repo`**; для **`cursorAi`** используй **`verify_repo`: `none`**.
## Отчётность
На каждом этапе используй формат из **`pipeline-execution-template.mdc`**.
## Детали по стекам
Чек-листы этапов: **`agent-1-*` … `agent-3-ui-tester.mdc`**, под-агенты: **`.cursor/agents/`**, skill: **`feature-pipeline`**.
+37
View File
@@ -0,0 +1,37 @@
---
description: Базовые стандарты для агентной frontend-разработки
alwaysApply: true
---
# Базовые правила frontend-агента
## Миссия
Создавать поддерживаемые frontend-функции с предсказуемым поведением, явными предположениями и проверяемым результатом.
## Рабочий процесс
- Начинай с уточнения цели, ограничений и ожидаемого влияния на UX.
- Предпочитай небольшие инкрементальные изменения вместо широких переписываний.
- Сохраняй действующие конвенции проекта, если нет явной причины их менять.
- После существенных правок выполняй релевантные проверки и фиксируй результаты.
## Качество кода
- Ставь читаемость и явные имена выше «умных» сокращений.
- Держи компоненты сфокусированными: одна четкая ответственность на компонент/модуль.
- Выноси повторяющуюся логику в хуки или утилиты, когда появляется дублирование; не размножай копии форм и модалок, если достаточно одной параметризованной реализации.
- Не добавляй мертвый код, неиспользуемые экспорты и закомментированные блоки.
## Надежность и совместимость
- Не ломай публичные API компонентов без документирования шагов миграции.
- Сохраняй базовую доступность (labels, клавиатурная навигация, семантические элементы).
- Обрабатывай состояния загрузки, пустого результата и ошибок в асинхронных UI-путях; подтверждения и модалки — через UI приложения, не через нативные диалоги браузера (в Electron renderer — аналогично: внутренние модалки приложения).
- Добавляй или обновляй тесты при изменении поведения критичных пользовательских сценариев.
## Взаимодействие с агентом
- Явно указывай, что изменено, зачем это изменено и как это проверить.
- Прямо фиксируй риски и компромиссы при нетривиальных решениях.
- Если требования неоднозначны, остановись и уточни перед реализацией предположений.
@@ -0,0 +1,93 @@
---
description: Унифицированные стандарты разработки для репозиториев воркспейса dnd_project
alwaysApply: true
---
# Унифицированные стандарты разработки
## Область применения
- Разделы про **React / renderer UI / формы / модалки** относятся к репозиториям с пользовательским интерфейсом (**`dnd_player`**, **`project-converter`** и т.п.). Для **headless** кода (**`DndGamePlayerLicenseServer`**) применимы блоки про слои данных, контракты, тесты и дисциплину изменений; требования к модалкам и renderer UI к такому коду **не предъявляются**.
- **i18n** (ключи пользовательских строк и т.д.) — **только для продукта DNDGamePlayer**, репозиторий **`dnd_player`**; планируемые локали: **ru**, **en**. В **`project-converter`**, **`DndGamePlayerLicenseServer`**, **`cursorAi`** отдельных требований по i18n **нет**.
- Репозитории **без TypeScript**: требования раздела «TypeScript и качество» выполняются после внедрения TS; до этого — **эквивалентная строгость**: `node --check` по согласованным входным файлам, явные контракты (JSDoc при необходимости), отсутствие необоснованного ослабления проверок, тесты на изменённое поведение в доступном стеке.
## Архитектура и папки
- Фичи организуются по папкам: один доменный блок = одна директория.
- Публичный вход фичи обычно размещается в `index.tsx` (или в согласованном с репозиторием входном файле).
- Рядом с фичей допустимы локальные конфиги таблиц, схем модалок и подпапки `Modals`, `Components` по необходимости.
- Страницы и составные экраны остаются тонкими: сторы, HTTP/API, утилиты и типы контрактов выносятся отдельно.
- Типы API и DTO держатся в выделенной зоне (`interfaces`, `api-types` и т.п.).
- Исторические опечатки и неудачные имена в путях не размножаются; при правках в зоне их нужно по возможности исправлять.
## Маршруты и доменные строки
- Пути маршрутов берутся из единого модуля констант приложения (если в проекте есть маршрутизация).
- Строковые литералы не дублируются в `Route`, `Link`, `navigate`.
- Роли, статусы и иные перечислимые значения задаются через `const` + `as const` и производный union-тип (или согласованный `enum`).
- Магические строки в доменных значениях не допускаются.
## Состояние и данные
- Локальный UI-стейт ведется предсказуемо, включая выбранную библиотеку реактивности, если она принята в проекте.
- Доступ к глобальному стору делается через явный контекст или согласованный DI.
- Скрытые синглтоны в компонентах не используются.
- При сочетании библиотеки запросов и стора зоны ответственности разделяются явно:
- кэш и запросы,
- конфиг, базовые URL, навигация, сессия.
- HTTP работает через общий слой (клиент, перехватчики, обработка ошибок).
- Базовые URL и окружение берутся из конфигурации, а не из JSX.
## Формы и валидация
- На проекте используется один канон валидации и резолвера для форм (например `react-hook-form`, если принят в репозитории).
- Новый код не должен создавать параллельный стек валидации без решения команды и плана миграции.
- Для тяжелых форм используются:
- `memo`,
- декомпозиция на подкомпоненты,
- вынос генерации схем в утилиты.
- Дублирование правил валидации в разметке не допускается.
- Создание и редактирование одной и той же сущности реализуются **одной общей формой** (один компонент/модуль формы, общая схема по возможности). Отдельные «форма создания» и «форма редактирования» как копии друг друга не допускаются.
- Если поведение полей отличается между режимами создания и редактирования, различия задаются условно: условный рендеринг блоков полей, условная обязательность и правила в схеме валидации, различие дефолтов и `defaultValues`, флаги режима (`mode`, `isEdit` и т.п.) — без дублирования разметки и правил там, где достаточно параметризации.
## UI и стили
- **Единый источник** визуальных примитивов и отступов — **существующие общие компоненты и соглашения этого репозитория** (не внешняя «дизайн-система из правил»). Перед добавлением нового примитива ищи аналог в кодовой базе; дубли без причины не вводятся.
- Новый UI создаётся по **канону репозитория** (например CSS Modules или другой зафиксированный способ).
- Токены темы хранятся в согласованном месте проекта (если принято).
- Устаревший подход стилизации допускается только в наследуемых зонах; новые экраны на нем не строятся без решения команды.
## Модальные окна и подтверждения действий
- Любые модальные окна и запросы подтверждения в **renderer** реализуются **только** через **внутренние** компоненты приложения и паттерны **этого** репозитория (не нативные блокирующие диалоги ОС в зоне UI продукта).
- Использование **`alert` / `confirm` / `prompt`** в новом и изменяемом коде **renderer** запрещено (исключения — только явно зафиксированные в самом репозитории, например отдельный отладочный путь).
- **Продукт DNDGamePlayer** (`dnd_player`): после внедрения i18n (план: **ru**, **en**) подписи модалок и UI — через **ключи**; до внедрения — литералы в стиле репо.
- Повторяющаяся разметка и логика модалок выносится в переиспользуемые обёртки/конфиги, а не копируется между фичами.
## Переиспользование кода и дублирование
- Новый код проектируется с максимальным переиспользованием: общие компоненты, хуки, утилиты, схемы валидации и типы — единственный источник правды для повторяющегося поведения.
- Необоснованное дублирование блоков UI и бизнес-логики в новом коде не допускается: при появлении второго такого же фрагмента выносится общий модуль; при правках смежных дублей по возможности консолидируют реализацию.
- Наследуемый дублирующийся код при точечных задачах не обязан переписываться целиком, но расширять дубли вместо выноса общего решения не следует без явной причины (объём/риск миграции фиксируется в задаче или ревью).
## TypeScript и качество
- В репозиториях на TypeScript обязателен **`strict`**; новые `any` и `@ts-ignore` не добавляются.
- Ослабления возможны только точечно, с комментарием причины и ссылкой на задачу.
- Границы модулей (роутинг, внешние библиотеки) типизируются осмысленно.
- Практика «везде any» как норма запрещена.
## Локализация (только **`dnd_player`**) и комментарии
- **Продукт DNDGamePlayer** (`dnd_player`): планируется отдельная задача на **мультиязычность** — языки **русский (ru)** и **английский (en)**. После внедрения i18n пользовательские строки интерфейса выносятся в **ключи**; префиксы и соглашения по ключам — единые для приложения; новые строки без ключей не добавляются. До внедрения стека i18n действуют литералы в текущем стиле репозитория.
- **Вне `dnd_player`:** отдельных требований к i18n нет; строки — в принятом для репозитория виде.
- Над нетривиальными функциями, эффектами и публичными сущностями добавляется краткий смысловой комментарий там, где это принято в репозитории.
- Стиль комментариев и кодировка файлов соответствуют стандарту репозитория (UTF-8, читаемый язык команды).
## Инженерная дисциплина
- Изменения должны быть минимальными и сфокусированными (`minimal diff`).
- Предсказуемость решения приоритетнее «хитрости».
- Изменения контрактов модульной федерации и shared-зависимостей проходят с повышенным вниманием на ревью.
- Линтер, форматтер, pre-commit и политика компилятора (включая React Compiler, если включен) соблюдаются как в репозитории; если скрипта ещё нет — не ослаблять дисциплину «отмазкой репозитория», а фиксировать проверки в задаче (**одинаковая жёсткость** ожиданий по всем проектам воркспейса).
- Запрещено ослаблять правила только ради быстрого прохождения проверок.
@@ -0,0 +1,28 @@
---
description: Единый короткий шаблон отчета для этапов пайплайна
alwaysApply: true
---
# Шаблон отчета по этапу пайплайна
Использовать этот формат на каждом этапе:
1. Фронтэнд разработчик
2. Разработчик UI-автотестов
3. Ревьювер кода
4. UI-тестировщик
## Формат
- Этап: `<название роли>`
- Статус: `пройдено | пройдено с замечаниями | не пройдено`
- Что проверено: `<3-6 кратких пунктов>`
- Найдено: `<нет | список замечаний/дефектов>`
- Решение по этапу: `<передать дальше | вернуть на этап 1>`
- Следующее действие: `<кто и что делает дальше>`
## Правила заполнения
- Формулировки краткие и проверяемые.
- Для замечаний указывать критичность: `блокирующий | важный | минорный`.
- Если этап не пройден, обязательно указывать условие повторной проверки.
+54 -20
View File
@@ -3,38 +3,72 @@ description: Workspace-wide workflow and conventions (dnd_project)
alwaysApply: true
---
# DNDGamePlayer / `dnd_project` — правила работы над задачами (future-pipeline)
# DNDGamePlayer / `dnd_project` — правила работы над задачами
**Перед первой задачей в сессии по коду, архитектуре или продукту** открой и учти **`AGENTS.md`** в корне репозитория **`cursorAi`** — там обязательный обзор экосистемы и карта репозиториев. Детали путей и сборки: **`WORKSPACE.md`**.
**Перед первой задачей в сессии по коду, архитектуре или продукту** открой и учти **`AGENTS.md`** в корне репозитория **`cursorAi`** — там обзор экосистемы и карта репозиториев. Детали путей и сборки: **`WORKSPACE.md`**.
Эти правила применяются **только** когда запрос пользователя требует **изменений в репозитории** (код/конфиги/тесты). Для чисто текстовых задач (описания, маркетинг, переписка) pipeline не запускаем.
Эти правила применяются **только** когда запрос пользователя требует **изменений в репозитории** (код/конфиги/тесты). Для чисто текстовых задач (описания, маркетинг, переписка) пайплайн не запускаем.
**Корень воркспейса Cursor** — обычно каталог `cursorAi` с единым `.cursor/`. Исходники плеера — в соседнем репозитории **`dnd_player/`** (см. `WORKSPACE.md`).
## future-pipeline (обязательный порядок)
## Стандарты кода, комментариев и документации
### 1) Implementation
- Прочитать релевантный код (минимум 1 файл), найти реальную причину бага/задачи.
- Делать **minimal, review-friendly diff** и следовать текущим паттернам проекта.
- Не добавлять зависимости без явной причины.
Помимо этого файла действуют правила в той же папке:
### 2) Review
- Самопроверка изменений: edge-cases, состояние UI (loading/error/empty/disabled), a11y, регрессии.
- Если задача нетривиальная: запустить внутренний «строгий ревью» (под-агент reviewer).
- **`frontend-agent-core.mdc`**, **`frontend-development-standards.mdc`** — стиль кода, UI, формы, модалки, TS, комментарии; **i18n — только в `dnd_player`** (планируются языки **ru** и **en** — см. `frontend-development-standards.mdc`).
- **`agent-core-contracts-and-quality.mdc`**, **`agent-test-gates-mandatory.mdc`** — контракты, тестовые гейты, верификация.
### 3) Tests
- Обновить/добавить тест(ы), если поведение изменилось или был баг.
- Для мелких правок допускается «облегчённый режим» без под-агентов, но тесты всё равно должны проходить там, где они есть.
## Пайплайн (кодовые репозитории)
### 4) Verify (всегда, перед ответом — для **`dnd_player`**)
Порядок этапов: **`agents-pipeline-order.mdc`**. Отчёт по этапу: **`pipeline-execution-template.mdc`**. Чек-листы: **`agent-1-frontend-developer.mdc`** … **`agent-3-ui-tester.mdc`**. Под-агенты: **`.cursor/skills/feature-pipeline/SKILL.md`**.
Из каталога **`dnd_player/`** (или через хук из корня воркспейса, см. `.cursor/hooks/final-verify.cjs`):
**Не входит в обязательный пайплайн:** репозиторий **`cursorAi`** (только `.md` / `.mdc` правил и описаний). Для таких правок полный цикл из четырёх этапов **не требуется**; хук **`stop`**: **`verify_repo`: `none`**.
- `npm run lint`
- `npm run typecheck`
- `npm run test`
Последовательность для **`dnd_player`**, **`project-converter`**, **`DndGamePlayerLicenseServer`**:
Если задача касалась **только** `project-converter` или **DndGamePlayerLicenseServer** — выполни адекватную проверку для этого репозитория (`node --check`, локальный прогон) и явно укажи в ответе, что полный набор команд плеера не запускался (если он не нужен по смыслу).
1. Реализация (minimal diff, паттерны **целевого** репозитория).
2. Автотесты на изменённое поведение (стек репозитория).
3. Ревью кода.
4. Верификация: UI (Electron/браузер) или HTTP-сценарии для сервера.
### `.cursor/pipeline-state.json`
Обязательные ключи: `frontend_development`, `ui_autotests`, `code_review`, `ui_browser_verification` — все **`"done"`** перед успешным хуком (кроме режима **`verify_repo`: `none`**).
Поле **`verify_repo`** (цель хука **`stop`** и автоматической verify):
| Значение | Когда ставить | Что делает хук `final-verify.cjs` |
|----------|----------------|-----------------------------------|
| **`dnd_player`** | Задача по плееру (по умолчанию) | `npm run lint`, `typecheck`, `test` в **`dnd_player/`** |
| **`project-converter`** | Задача по конвертеру | `npm run lint`, `node --check` по `src/`, обязательный **`npm run test`** (скрипт и тесты — по политике A в том же PR, что и правки поведения) |
| **`DndGamePlayerLicenseServer`** | Задача по серверу лицензий | `node --check` по `src/`, `lib/`, обязательный **`npm run test`** |
| **`none`** | Только правки в **`cursorAi`** | Сразу **exit 0**, четыре ключа пайплайна **не проверяются** |
Переопределение без правки файла: переменная окружения **`VERIFY_REPO`** (те же значения). Корни соседних репо: родитель каталога `cursorAi` (см. **`WORKSPACE.md`**); для плеера дополнительно **`DND_PLAYER_ROOT`**; для всех соседей — **`DND_PROJECT_ROOT`** (абсолютный путь к папке `dnd_project`).
## Verify перед ответом (по репозиторию задачи)
Перед ответом пользователю все проверки **целевого** репозитория должны быть **зелёными**; не подменять verify другим репо.
### Политика тестов **вариант A** (`project-converter`, `DndGamePlayerLicenseServer`)
Любая задача, которая **меняет поведение** этих репозиториев, в **том же PR** обязана: добавить или расширить **`npm test`** в **`package.json`**, добавить автотесты на затронутое поведение и довести **`npm run test`** до green. Откладывать появление скрипта `test` или тестов «отдельным эпиком» после merge **нельзя**. Исключение только при объективной блокировке (тогда — запись в задаче, риск, согласование с владельцем процесса), а не «пока не дошли руки».
### `dnd_player`
`npm run lint`, `npm run typecheck`, `npm run test` из корня репозитория.
### `project-converter`
`npm run lint`, **`node --check`** по entrypoints в `src/`, **`npm run test`** (обязателен — политика **вариант A**). Реальные lint/typecheck — по мере появления скриптов; до этого не ослаблять требование **тестов в том же PR**, что и изменение поведения.
### `DndGamePlayerLicenseServer`
**`node --check`** по модулям, **`npm run test`** (обязателен — политика **вариант A**). Скрипт `start` для ручного запуска сервера не заменяет автотесты.
### `cursorAi`
Обязательный 4-этапный пайплайн **не применяется**. Согласованность ссылок и имён файлов — по усмотрению задачи; для хука **`stop`** выставь **`verify_repo`: `none`**.
Если что-то упало — исправить и повторить до green.
+55 -41
View File
@@ -1,83 +1,97 @@
---
name: feature-pipeline
description: Implementation → Review → Tests → Verify
description: Dev → autotests → code review → scenario verify → repo verify (все кодовые репо)
---
# Workflow
Контекст воркспейса: **`AGENTS.md`** (обзор продукта), затем **`WORKSPACE.md`** (пути, сборка, junction). Основной код плеера — репозиторий **`dnd_player/`** (рядом с корнем воркспейса `cursorAi`).
Контекст: **`AGENTS.md`**, **`WORKSPACE.md`**. Целевой репозиторий задачи: **`dnd_player/`**, **`project-converter/`** или **`DndGamePlayerLicenseServer/`**. В **`pipeline-state.json`** задай **`verify_repo`** под хук **`stop`** (см. **`project.mdc`**); для правок только в **`cursorAi`** — **`verify_repo`: `none`** (пайплайн 4 этапов не обязателен).
## Stage 1 — Implementation
Порядок этапов: **`agents-pipeline-order.mdc`**, отчёт: **`pipeline-execution-template.mdc`**, чек-листы: **`.cursor/rules/agent-*.mdc`**.
Используй subagent: frontend-senior
## Stage 1 — Разработчик
- реализуй задачу
- сделай minimal diff
Subagent: **frontend-developer** (`.cursor/agents/frontend-developer.md`)
Обнови state:
- реализация, **minimal diff**, паттерны **целевого** репозитория;
- **i18n** — только при работе в **`dnd_player`**; после внедрения — **ru**/**en** (см. `frontend-development-standards.mdc`).
```json
{
"implementation": "done"
"frontend_development": "done",
"ui_autotests": "pending",
"code_review": "pending",
"ui_browser_verification": "pending"
}
```
---
## Stage 2 — Review
## Stage 2 — Автотесты
Используй subagent: reviewer
Subagent: **ui-test-developer** (`.cursor/agents/ui-test-developer.md`)
- проверь изменения
- найди проблемы
- исправь минимально
Обнови state:
- тесты под изменённое поведение, стек **этого** репозитория (`dnd_player`: `npm run test`; остальные — по `package.json` или добавить в задаче).
```json
{
"implementation": "done",
"review": "done"
"frontend_development": "done",
"ui_autotests": "done",
"code_review": "pending",
"ui_browser_verification": "pending"
}
```
---
## Stage 3 — Tests
## Stage 3 — Ревью кода
Используй subagent: unit-tests
- добавь/обнови tests
- добейся green status
Обнови state:
Subagent: **code-reviewer** (`.cursor/agents/code-reviewer.md`)
```json
{
"implementation": "done",
"review": "done",
"tests": "done"
"frontend_development": "done",
"ui_autotests": "done",
"code_review": "done",
"ui_browser_verification": "pending"
}
```
---
## Stage 4 — Verify
## Stage 4 — Верификация сценариев
Выполни из каталога **`dnd_player/`** (см. также хук `.cursor/hooks/final-verify.cjs`):
Subagent: **ui-tester** (`.cursor/agents/ui-tester.md`)
- `npm run lint`
- `npm run typecheck`
- `npm run test`
- **`dnd_player`**, **`project-converter`**: Electron / браузер по сценарию;
- **`DndGamePlayerLicenseServer`**: HTTP-сценарии к запущенному сервису;
- отчёт: **`pipeline-execution-template.mdc`**.
Если ошибка:
```json
{
"frontend_development": "done",
"ui_autotests": "done",
"code_review": "done",
"ui_browser_verification": "done"
}
```
- исправь
- повтори
---
## Stage 5 — Verify (команды целевого репо)
Выполни **все** проверки из **`package.json`** репозитория задачи до **green**. Для **`dnd_player`** после четырёх `"done"` в `pipeline-state.json` хук **`stop`** запускает `lint` / `typecheck` / `test`. Для **`project-converter`** и **`DndGamePlayerLicenseServer`** — в том числе обязательный **`npm run test`** (**вариант A**: тесты и скрипт `test` в том же PR, что и изменение поведения). Не подменять verify другим репозиторием.
---
## Final Output
- implementation summary
- review summary
- test summary
- verification status
- implementation summary
- autotests summary
- code review summary
- scenario verification (UI или API)
- verify status по **целевому** репо
## PR-чеклисты (приёмка по задаче)
## PR-чеклисты
Готовые чеклисты с критериями по стадиям лежат в `.cursor/pr-checklists/`. Для UI-выравнивания под макеты: `ui-mock-alignment.md`. Пути к файлам в чеклистах — относительно **`dnd_player/`**.
`.cursor/pr-checklists/`; пути в `ui-mock-alignment.md` — относительно **`dnd_player/`**.