chore: codify frontend local verification
This commit is contained in:
@@ -1,37 +1,28 @@
|
||||
# Frontend
|
||||
|
||||
## Назначение
|
||||
## Назначение и authority
|
||||
|
||||
React/Vite-клиент WealthLedger. Функциональные изменения сначала планируются в `../specs/openspec`; контракт API задает backend OpenAPI, а не ручные DTO.
|
||||
React/Vite-клиент WealthLedger. Canonical OpenSpec store — `wealth-ledger-specs` в `../specs/openspec`; OpenSpec commands, читающие или изменяющие change, всегда выполняются с `--store wealth-ledger-specs`. Versioned planning artifacts вне canonical store запрещены, включая `superpowers/plans`; `../references/**` read-only.
|
||||
|
||||
## Проверка
|
||||
Перед изменением поставленного поведения прочитать [`../docs/architecture/system-overview.md`](../docs/architecture/system-overview.md), а для доменных терминов — [`../docs/architecture/domain-glossary.md`](../docs/architecture/domain-glossary.md). Testing, build-versus-buy и Delivery Map определены в [`../docs/development/engineering-governance.md`](../docs/development/engineering-governance.md). Audit-derived работа начинается с [`../docs/development/audit-remediation.md`](../docs/development/audit-remediation.md).
|
||||
|
||||
## Canonical gate
|
||||
|
||||
Node 22 обязателен. После lockfile install единственный completion gate:
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
npm run verify
|
||||
```
|
||||
|
||||
Node 22 обязателен (`.nvmrc`). `npm run openapi:sync` - единственная команда, обращающаяся к `${VITE_API_BASE_URL:-http://localhost:3000}/api/docs-json`; она атомарно обновляет snapshot и generated types. `openapi:generate` и `openapi:check` работают только с committed snapshot.
|
||||
Gate non-mutating и проверяет runtime, OpenAPI snapshot, hygiene, strict TypeScript, Biome, risk-based tests/coverage ratchet, Knip, dependency boundaries, build и bundle budget. `npm run openapi:sync` — отдельная записывающая команда для атомарного обновления snapshot/types; runtime contract обеих сторон сверяется из workspace через `bash specs/scripts/verify-runtime-openapi.sh`.
|
||||
|
||||
Для read-only сверки backend runtime OpenAPI с committed snapshot под Node 22
|
||||
запускать из workspace `bash specs/scripts/verify-runtime-openapi.sh`.
|
||||
## Enforceable boundaries
|
||||
|
||||
## Документация для агента
|
||||
- Code style и i18n: [`docs/CONVENTIONS.md`](docs/CONVENTIONS.md), исполняются Biome и TypeScript.
|
||||
- FSD и public API: [`docs/STRUCTURE.md`](docs/STRUCTURE.md), исполняются dependency-cruiser и Knip; направление `app → pages → features → entities → shared`.
|
||||
- HTTP и types: [`docs/API-LAYER.md`](docs/API-LAYER.md); только typed client и generated OpenAPI `paths[...]`, без ручных transport DTO и прямых T-Bank calls.
|
||||
- UI states: [`docs/UI-PATTERN.md`](docs/UI-PATTERN.md); route runtime failures обрабатывает единый route-keyed ErrorBoundary, expected API states остаются локальными.
|
||||
- Тесты: [`docs/TESTING.md`](docs/TESTING.md); новый тест обязателен по risk trigger, а не из-за появления файла или coverage процента.
|
||||
|
||||
- Перед изменением поставленного поведения или доменных терминов прочитать [`../docs/architecture/system-overview.md`](../docs/architecture/system-overview.md) и [`../docs/architecture/domain-glossary.md`](../docs/architecture/domain-glossary.md).
|
||||
- Перед изменением API или transport types прочитать [`docs/API-LAYER.md`](docs/API-LAYER.md).
|
||||
- Перед созданием формы, страницы или UI-состояний прочитать [`docs/UI-PATTERN.md`](docs/UI-PATTERN.md).
|
||||
- Перед изменением структуры слайса или импортов прочитать [`docs/STRUCTURE.md`](docs/STRUCTURE.md).
|
||||
- Перед кодом, тестами или quality checks прочитать [`docs/CONVENTIONS.md`](docs/CONVENTIONS.md) и [`docs/TESTING.md`](docs/TESTING.md).
|
||||
- Route-level runtime errors обрабатываются одним native route-keyed ErrorBoundary вокруг `AppRoutes`; expected API states остаются локальными.
|
||||
- Для задачи по Audit ID, продолжения remediation или выбора следующего улучшения сначала прочитать [`../docs/development/audit-remediation.md`](../docs/development/audit-remediation.md); единственный canonical OpenSpec store — `wealth-ledger-specs` в `../specs/openspec`, а OpenSpec commands, читающие или изменяющие change, выполнять с `--store wealth-ledger-specs`.
|
||||
|
||||
## Границы
|
||||
|
||||
- Текущий baseline использует FSD, React Router, i18n, Mantine, React Query и typed API scaffold.
|
||||
- Зависимости FSD идут `app -> pages -> features -> entities -> shared`; слайсы импортируются только через публичный `index.ts`.
|
||||
- HTTP идет только через типизированный клиент; request/response types выводятся из generated OpenAPI `paths[...]`, а не дублируются вручную. UI-строки - только через i18n. Каждый маршрут имеет loading, error и empty состояния.
|
||||
- Соблюдать strict TypeScript: `import type` для типов, без `enum` и `namespace`.
|
||||
- Не добавлять прямые вызовы T-Bank и не переносить Todo-код из `../references/`.
|
||||
- Не добавлять Storybook, Playwright, CI configuration, browser MSW worker или mock development mode.
|
||||
- Не создавать и не коммитить framework-specific planning/spec/task/design artifacts: versioned SDD-артефакты хранятся только в `../specs/openspec`; `../references/**` остаётся read-only исключением.
|
||||
Непроверяемые эстетические предпочтения считаются guidance. Не добавлять Storybook, Playwright, CI, browser MSW worker или mock development mode без утверждённого change.
|
||||
|
||||
@@ -22,10 +22,12 @@ npm run dev
|
||||
npm run verify
|
||||
```
|
||||
|
||||
Команда проверяет committed OpenAPI snapshot, strict TypeScript, Biome, unit
|
||||
tests и coverage, Knip, dependency rules и production build. Для обновления
|
||||
OpenAPI artifacts применяется только `npm run openapi:sync`; обычный
|
||||
`openapi:check` обращается лишь к committed snapshot.
|
||||
Команда сначала отклоняет runtime вне Node 22, затем проверяет committed
|
||||
OpenAPI snapshot, repository hygiene, strict TypeScript, Biome, один
|
||||
coverage-backed запуск Vitest, Knip, dependency rules, production build и
|
||||
bundle budget. Для обновления OpenAPI artifacts применяется только
|
||||
`npm run openapi:sync`; обычный `openapi:check` обращается лишь к committed
|
||||
snapshot.
|
||||
|
||||
## Документация
|
||||
|
||||
@@ -34,8 +36,12 @@ OpenAPI artifacts применяется только `npm run openapi:sync`; о
|
||||
- [UI-паттерны](docs/UI-PATTERN.md)
|
||||
- [Conventions](docs/CONVENTIONS.md) и [тестирование](docs/TESTING.md)
|
||||
- [Обзор поставленной системы](../docs/architecture/system-overview.md)
|
||||
- [Engineering governance и risk-based testing](../docs/development/engineering-governance.md)
|
||||
- [OpenSpec authority и lifecycle](../docs/development/openspec-authority-and-lifecycle.md)
|
||||
- [Frontend workflow](../docs/development/frontend-workflow.md)
|
||||
- [Remediation registry](../docs/development/audit-remediation.md)
|
||||
|
||||
Runtime OpenAPI backend сверяется с frontend snapshot отдельной read-only
|
||||
командой из workspace: `bash specs/scripts/verify-runtime-openapi.sh`.
|
||||
Полный multi-repository change проверяется из workspace командой
|
||||
`bash specs/scripts/verify-workspace-change.sh <change>`.
|
||||
|
||||
+5
-1
@@ -1,6 +1,10 @@
|
||||
# Frontend Documentation
|
||||
|
||||
Эти документы задают правила AI-разработки и дополняют `AGENTS.md`. Фактические версии зависимостей и scripts всегда определяются конфигурацией проекта.
|
||||
Эти документы задают frontend-local conventions и дополняют `AGENTS.md`.
|
||||
Общая engineering policy находится в
|
||||
[`../../docs/development/engineering-governance.md`](../../docs/development/engineering-governance.md),
|
||||
а фактические версии зависимостей и scripts всегда определяются конфигурацией
|
||||
проекта.
|
||||
|
||||
- `CONVENTIONS.md` - обязательные правила кода и i18n.
|
||||
- `API-LAYER.md` - OpenAPI, generated types и typed client.
|
||||
|
||||
+15
-1
@@ -1,9 +1,23 @@
|
||||
# Testing
|
||||
|
||||
Тесты запускаются `npm run test:run` через Vitest и Testing Library. `npm run test:coverage` создаёт локальный coverage report.
|
||||
Canonical completion gate — `npm run verify`; он запускает Vitest один раз
|
||||
через `npm run test:coverage`. `npm run test:run` остаётся короткой локальной
|
||||
командой без coverage report.
|
||||
|
||||
Выбор нового теста определяется риском поведения, а не фактом изменения файла.
|
||||
Автоматический тест обязателен для security/privacy, денежных расчётов,
|
||||
целостности данных, concurrency, публичного контракта, критического journey и
|
||||
регрессии. DTO без логики, декларативная конфигурация, тонкая orchestration и
|
||||
поведение зависимости отдельного unit test не требуют, пока у них нет
|
||||
собственного branching, transformation, invariant или regression. Полная
|
||||
policy находится в [engineering governance](../../docs/development/engineering-governance.md).
|
||||
|
||||
MSW запускается только Vitest setup в `src/test/`; handlers покрывают текущий API. Не добавлять service worker, browser mocking или mock development mode. Для transport проверять заголовки и retry через MSW, не через реальный backend.
|
||||
|
||||
Проверяйте наблюдаемое поведение, а не детали реализации. UI-тест строится как Arrange, Act, Assert; для интерактивных действий предпочитайте `userEvent`. Форма должна проверять валидацию и отсутствие запроса при невалидных данных; маршруты - редиректы и доступность экрана.
|
||||
|
||||
Colocated tests finance views фиксируют выбор loading/error/empty/loaded и доступные recovery actions. Route boundary tests используют test-only throwing route и проверяют безопасную ссылку и reset после navigation.
|
||||
|
||||
Coverage floors остаются anti-regression constraint. Нельзя добавлять тест,
|
||||
который только повторяет декларативную структуру или внутренности зависимости,
|
||||
ради повышения процента.
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@
|
||||
"node": "22.x"
|
||||
},
|
||||
"scripts": {
|
||||
"runtime:check": "node scripts/verify-node-version.mjs",
|
||||
"dev": "vite",
|
||||
"typecheck": "tsc -b --noEmit",
|
||||
"build": "tsc -b && vite build",
|
||||
@@ -22,7 +23,7 @@
|
||||
"deps": "node --test scripts/dependency-cruiser-config.test.mjs && depcruise src --config dependency-cruiser.cjs --output-type err-long",
|
||||
"bundle:check": "node --test scripts/bundle-budget.test.mjs && node scripts/bundle-budget.mjs",
|
||||
"bundle:baseline": "npm run build && node scripts/bundle-budget.mjs baseline",
|
||||
"verify": "npm run openapi:check && npm run hygiene:check && npm run typecheck && npm run lint && npm run test:run && npm run test:coverage && npm run knip && npm run deps && npm run build && npm run bundle:check",
|
||||
"verify": "npm run runtime:check && npm run openapi:check && npm run hygiene:check && npm run typecheck && npm run lint && npm run test:coverage && npm run knip && npm run deps && npm run build && npm run bundle:check",
|
||||
"prepare": "husky",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const packageJson = JSON.parse(
|
||||
readFileSync(resolve(root, "package.json"), "utf8"),
|
||||
);
|
||||
const nvmVersion = readFileSync(resolve(root, ".nvmrc"), "utf8").trim();
|
||||
const expectedMajor = nvmVersion.replace(/^v/, "").split(".")[0];
|
||||
const expectedEngine = `${expectedMajor}.x`;
|
||||
|
||||
if (packageJson.engines?.node !== expectedEngine) {
|
||||
throw new Error(
|
||||
`Node runtime contracts disagree: .nvmrc=${nvmVersion}, package.json engines.node=${packageJson.engines?.node ?? "missing"}`,
|
||||
);
|
||||
}
|
||||
|
||||
const actualVersion = process.versions.node;
|
||||
const actualMajor = actualVersion.split(".")[0];
|
||||
if (actualMajor !== expectedMajor) {
|
||||
console.error(
|
||||
`Unsupported Node.js runtime: expected ${expectedEngine}, actual ${actualVersion}. Activate .nvmrc before running repository checks.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Node.js runtime verified: ${actualVersion} (${expectedEngine})`);
|
||||
Reference in New Issue
Block a user