# Design System Foundation Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Создать внутренний пакет `@moex-vibe/design-system` с трёхуровневыми токенами, MUI light theme, согласованным UI-каталогом, Storybook и опубликованными правилами. **Architecture:** Platform-neutral токены хранятся как JSON-compatible TypeScript records и разрешаются собственным проверяемым resolver. MUI-адаптер переводит semantic/component tokens в CSS-variable theme; React-компоненты доступны только через public exports пакета. Storybook служит локальным/CI workbench, Docusaurus — единственной опубликованной документацией. **Tech Stack:** TypeScript 5, React 18, MUI 6.5, TanStack Table 8, Vitest 4 browser mode, Storybook 10.2 (`@storybook/react-vite`), Playwright Chromium, Docusaurus 3.7. --- ## Зафиксированные интерфейсы Пакет предоставляет subpath exports: ```json { ".": "./dist/index.js", "./tokens": "./dist/tokens/index.js", "./theme": "./dist/theme/index.js" } ``` Token source использует плоские DTCG-подобные записи: ```ts type TokenType = 'color' | 'dimension' | 'fontFamily' | 'fontWeight' | 'duration' | 'cubicBezier' | 'shadow'; type TokenValue = string | number | readonly number[] | readonly string[]; type TokenDefinition = { readonly $type: TokenType; readonly $value: TokenValue }; type TokenCollection = Readonly>; // Primitive содержит абсолютное значение. 'color.green.700': { $type: 'color', $value: '#176747' } // Semantic/component содержит alias и никогда не дублирует primitive. 'color.action.primary': { $type: 'color', $value: '{color.green.700}' } ``` Публичный React API: ```ts type Tone = 'default' | 'secondary' | 'positive' | 'negative' | 'muted'; type Density = 'balanced' | 'compact'; type ActionVariant = 'primary' | 'secondary' | 'tertiary' | 'danger'; type TextProps = { variant?: 'body' | 'caption' | 'label' | 'numeric'; tone?: Tone }; type HeadingProps = { level: 1 | 2 | 3 | 4 | 5 | 6; size?: 'display' | 'title' | 'section' | 'subsection' }; type ButtonProps = { variant?: ActionVariant; size?: 'small' | 'medium'; loading?: boolean }; type IconButtonProps = { label: string; size?: 'small' | 'medium' }; type SurfaceProps = { padding?: 'none' | 'sm' | 'md' | 'lg'; elevation?: 'none' | 'sm' | 'md' }; type DataTableProps = { table: Table; density?: Density; loading?: boolean; empty?: ReactNode; caption: string }; type MoneyProps = { value: number; currency?: string; locale?: string; signDisplay?: 'auto' | 'always' | 'never' }; type PriceChangeProps = { value: number; format?: 'percent' | 'money'; currency?: string; locale?: string }; type MetricProps = { label: string; value: ReactNode; supportingText?: ReactNode; trend?: ReactNode }; ``` Остальные контракты фиксированы так: - `Link`: MUI Link без `color`, `variant`, `sx`; добавляет `tone` и сохраняет polymorphic `component`. - `TextField`: MUI TextField без `color`, `variant`, `size`, `sx`; всегда `variant="outlined"` и `size="medium"`. - `Select`: `label`, `value`, `onChange(value: string)`, `options: { value; label; disabled? }[]`, `error?`, `helperText?`, `disabled?`. - `Checkbox`: `label`, `checked`, `onChange(checked: boolean)`, `disabled?`, `error?`. - `Card`: Surface props плюс `header?`, `actions?`, `children`; не знает маршруты и домен. - `Chip`: `label`, `tone: neutral|info|success|warning|error`, `onDelete?`. - `Badge`: `value`, `max?`, `label`; decorative badge запрещён без accessible label. - `Alert`: `severity: info|success|warning|error`, `title?`, `children`, `action?`. - `Dialog`: `open`, `onClose`, обязательные `title`, `children`, `actions?`. - `Skeleton`: `width?`, `height?`, `shape: text|rectangular|rounded|circular`. - `Progress`: `label`, `value?`; отсутствие value означает indeterminate. - `FormField`: `label`, `htmlFor`, `helperText?`, `error?`, `required?`, `children`. - `FilterBar`: `children`, `actions?`; отвечает только за responsive layout. - Page states: обязательный `title`, optional `description/action`; `LoadingState` дополнительно имеет `label` и `size: section|page`. Все wrappers запрещают произвольные `color`, `variant`, `size` и `sx`, где они обходят контракт. `Box`, `Stack`, `Grid` остаются полным и единственным прямым MUI allowlist во frontend. ## Карта файлов - `packages/design-system/src/tokens/` — schema, три token collections, resolver и guards. - `packages/design-system/src/theme/` — MUI augmentation, theme factory, provider, component overrides. - `packages/design-system/src/components/` — Core UI и product patterns; один каталог на компонент. - `packages/design-system/.storybook/` — единый provider, a11y и browser-test annotations. - `apps/frontend/src/app/providers/AppProviders.tsx` — подключение provider пакета без миграции страниц. - `apps/docs/docs/design-system/` — канонические правила; `apps/docs/docs/adr/ADR-016-design-system.md` — архитектурное решение. ### Task 1: Pre-flight и workspace shell **Files:** - Modify: `package.json` - Create: `packages/design-system/package.json` - Create: `packages/design-system/tsconfig.json` - Create: `packages/design-system/vitest.config.ts` - Create: `packages/design-system/.eslintrc.cjs` - Create: `packages/design-system/src/test/setup.ts` - Create: `packages/design-system/src/index.ts` - [ ] **Step 1: Проверить pre-flight до любых implementation edits** Run: ```bash git branch --show-current git status --short npm run test:backend npm run test:frontend npm run lint npm run build:backend npm run build:frontend ``` Expected: ветка `codex/design-system-foundation`, чистый worktree и все команды PASS. При сбое остановиться и классифицировать его до изменения кода. - [ ] **Step 2: Добавить workspace и root scripts** В `package.json` добавить `packages/design-system` в `workspaces` и scripts: ```json { "build:design-system": "npm run build -w packages/design-system", "test:design-system": "npm run test -w packages/design-system", "lint:design-system": "npm run lint -w packages/design-system", "storybook": "npm run storybook -w packages/design-system", "build:storybook": "npm run build-storybook -w packages/design-system", "test:storybook": "npm run test:storybook -w packages/design-system" } ``` - [ ] **Step 3: Создать package manifest и TypeScript build** `packages/design-system/package.json` должен быть private ESM package версии `0.1.0`, иметь `files: ["dist"]`, exports из раздела выше, peer dependencies на React 18, MUI 6 и TanStack Table 8, dev dependencies Storybook `^10.2.9`, `@vitest/browser-playwright`/Vitest `^4.1.8` и Playwright, scripts `build: tsc -p tsconfig.json`, `test: vitest run --project unit`, `storybook: storybook dev -p 6006 --no-open`, `build-storybook: storybook build`, `test:storybook: vitest run --project storybook`, `lint: eslint "src/**/*.{ts,tsx}"`. `tsconfig.json` компилирует `src` в `dist`, включает declarations, `jsx: react-jsx`, strict и `moduleResolution: bundler`. `vitest.config.ts` сначала содержит unit project с jsdom и `passWithNoTests: true`; флаг удаляется после Task 2. Test setup подключает jest-dom и matchMedia mock. Package ESLint config проверяет TypeScript/React hooks, но не включает frontend FSD zones. Root `lint` дополняется `lint:design-system`. - [ ] **Step 4: Установить зависимости и проверить пустой пакет** Run: ```bash npm install npm run build:design-system npm run test:design-system ``` Expected: package-lock обновлён, build PASS, Vitest PASS с `passWithNoTests: true`. - [ ] **Step 5: Commit** ```bash git add package.json package-lock.json packages/design-system git commit -m "build(design-system): add workspace package" ``` ### Task 2: Token schema и resolver (TDD) **Files:** - Create: `packages/design-system/src/tokens/types.ts` - Create: `packages/design-system/src/tokens/resolveToken.ts` - Test: `packages/design-system/src/tokens/resolveToken.test.ts` - [ ] **Step 1: Написать failing tests** ```ts it('resolves an alias chain and preserves the declared type', () => { const tokens = { base: { $type: 'color', $value: '#176747' }, semantic: { $type: 'color', $value: '{base}' }, component: { $type: 'color', $value: '{semantic}' }, } satisfies TokenCollection; expect(resolveToken(tokens, 'component')).toEqual({ type: 'color', value: '#176747' }); }); it.each([ ['missing alias', { a: { $type: 'color', $value: '{missing}' } }, /Unknown token/], ['cycle', { a: { $type: 'color', $value: '{b}' }, b: { $type: 'color', $value: '{a}' } }, /cycle/i], ['type mismatch', { a: { $type: 'color', $value: '#fff' }, b: { $type: 'dimension', $value: '{a}' } }, /type/i], ])('rejects %s', (_name, tokens, error) => expect(() => resolveToken(tokens, 'a')).toThrow(error)); ``` - [ ] **Step 2: Запустить тест и подтвердить RED** Run: `npm run test:design-system -- resolveToken.test.ts` Expected: FAIL, module/functions отсутствуют. - [ ] **Step 3: Реализовать schema и resolver** Resolver распознаёт только полную alias-строку `/^\{([^}]+)\}$/`, хранит visited path, проверяет существование target и равенство `$type`, возвращает `{ type, value }`. Смешанные строки вроде `calc({space.2} * 2)` запрещены. - [ ] **Step 4: Запустить тест и commit** Run: `npm run test:design-system -- resolveToken.test.ts` Expected: PASS. ```bash git add packages/design-system/src/tokens git commit -m "feat(design-system): add token contracts" ``` ### Task 3: Три уровня токенов **Files:** - Create: `packages/design-system/src/tokens/primitives.ts` - Create: `packages/design-system/src/tokens/semantic.light.ts` - Create: `packages/design-system/src/tokens/components.ts` - Create: `packages/design-system/src/tokens/index.ts` - Test: `packages/design-system/src/tokens/tokens.test.ts` - [ ] **Step 1: Написать token integrity tests** Тест объединяет три collections, резолвит каждый token, проверяет уникальные имена и инварианты: ```ts expect(Object.keys(primitiveTokens).every((name) => !isAlias(primitiveTokens[name].$value))).toBe(true); expect(Object.keys(semanticLightTokens).every((name) => isAlias(semanticLightTokens[name].$value))).toBe(true); expect(Object.keys(componentTokens).every((name) => isAlias(componentTokens[name].$value))).toBe(true); for (const name of Object.keys(allTokens)) expect(() => resolveToken(allTokens, name)).not.toThrow(); ``` - [ ] **Step 2: Запустить тест и подтвердить RED** Run: `npm run test:design-system -- tokens.test.ts` Expected: FAIL, collections отсутствуют. - [ ] **Step 3: Добавить минимальный полный набор foundations** Primitive groups: `color.neutral.{0,50,100,200,400,600,800,900}`, `color.green.{50,100,600,700,800}`, `color.red.{50,600,700}`, `color.amber.{50,600}`, `color.blue.{50,600}`, `space.{0,1,2,3,4,5,6,8,10,12}` на 4px grid, `radius.{none,sm,md,lg,pill}`, `font.family.{sans,mono}`, `font.size.{100..700}`, `font.weight.{regular,medium,semibold,bold}`, `lineHeight.{tight,normal,relaxed}`, `shadow.{none,sm,md}`, `duration.{instant,fast,normal}`, `easing.standard`, `size.control.{sm,md}`. `font.family.sans` использует Inter с system-ui fallback. Webfont weights 400/500/600/700 подключаются один раз во frontend shell в Task 10; Roboto не становится частью нового foundation. Semantic groups: `color.canvas`, `color.surface.{default,subtle,raised}`, `color.text.{primary,secondary, disabled,inverse}`, `color.border.{subtle,default,strong,focus}`, `color.action.{primary,primaryHover, secondary,danger}`, `color.feedback.{info,success,warning,error}`, `color.finance.{positive,negative, neutral}`, plus semantic typography, focus ring, spacing and control sizes. Component groups cover только API v1: button, iconButton, field, checkbox, surface, card, chip, badge, alert, dialog, skeleton, progress, table, metric и pageState. - [ ] **Step 4: Проверить GREEN и запрет hardcoded values вне primitives** Run: `npm run test:design-system -- tokens.test.ts` Expected: PASS. Дополнительный test scan подтверждает, что `semantic.light.ts` и `components.ts` не содержат hex/rgb/px literals. - [ ] **Step 5: Commit** ```bash git add packages/design-system/src/tokens git commit -m "feat(design-system): define three-level tokens" ``` ### Task 4: MUI adapter и provider (TDD) **Files:** - Create: `packages/design-system/src/theme/createMoexVibeTheme.ts` - Create: `packages/design-system/src/theme/MoexVibeThemeProvider.tsx` - Create: `packages/design-system/src/theme/mui.d.ts` - Create: `packages/design-system/src/theme/index.ts` - Test: `packages/design-system/src/theme/createMoexVibeTheme.test.ts` - [ ] **Step 1: Написать failing theme contract tests** ```ts const theme = createMoexVibeTheme(); expect(theme.cssVarPrefix).toBe('mv'); expect(theme.colorSchemes.light.palette.primary.main).toBe(resolveValue('color.action.primary')); expect(theme.typography.body1.fontFamily).toContain('Inter'); expect(theme.shape.borderRadius).toBe(resolveValue('radius.md')); expect(theme.components?.MuiButton?.defaultProps).toMatchObject({ disableElevation: true }); ``` - [ ] **Step 2: Подтвердить RED** Run: `npm run test:design-system -- createMoexVibeTheme.test.ts` Expected: FAIL, factory отсутствует. - [ ] **Step 3: Реализовать adapter** Использовать `createTheme({ cssVariables: { cssVarPrefix: 'mv' }, colorSchemes: { light: ... } })`. Theme получает palette, typography, spacing, shape, shadows, transitions и component overrides только через `resolveValue`. `mui.d.ts` включает `themeCssVarsAugmentation` и добавляет `finance` palette roles. - [ ] **Step 4: Реализовать provider** `MoexVibeThemeProvider` оборачивает MUI `ThemeProvider` и `CssBaseline`, принимает только `children`; mode API в v1 не экспортируется. - [ ] **Step 5: Проверить и commit** Run: `npm run test:design-system -- createMoexVibeTheme.test.ts && npm run build:design-system` Expected: PASS. ```bash git add packages/design-system/src/theme packages/design-system/src/tokens git commit -m "feat(design-system): add MUI theme adapter" ``` ### Task 5: Storybook и automated story checks **Files:** - Create: `packages/design-system/.storybook/main.ts` - Create: `packages/design-system/.storybook/preview.tsx` - Create: `packages/design-system/.storybook/vitest.setup.ts` - Modify: `packages/design-system/vitest.config.ts` - Modify: `packages/design-system/package.json` - [ ] **Step 1: Настроить Storybook 10.2** ```ts const config: StorybookConfig = { framework: '@storybook/react-vite', stories: ['../src/**/*.stories.@(ts|tsx)'], addons: ['@storybook/addon-a11y', '@storybook/addon-vitest'], }; ``` `preview.tsx` добавляет decorator `MoexVibeThemeProvider`, background `color.canvas` и параметры `a11y.test = 'error'`, layout `centered` по умолчанию. - [ ] **Step 2: Добавить Storybook Vitest browser project** Использовать `storybookTest`, `@vitest/browser-playwright` и headless Chromium; setup регистрирует `@storybook/addon-a11y/preview` и project annotations через `setProjectAnnotations`. - [ ] **Step 3: Проверить стенд** Run: ```bash npx playwright install chromium npm run build:storybook ``` Expected: static Storybook build PASS. Первый `test:storybook` запускается после появления stories в Task 6. - [ ] **Step 4: Commit** ```bash git add package.json package-lock.json packages/design-system git commit -m "build(design-system): configure Storybook workbench" ``` ### Task 6: Typography и actions (TDD) **Files:** - Create: `packages/design-system/src/components/{Text,Heading,Link,Button,IconButton}/` - Test: colocated `*.test.tsx` - Stories: colocated `*.stories.tsx` - [ ] **Step 1: Написать failing interaction/type tests** Проверить semantic heading level, tone mapping, external link rel, loading button disabled state и progress label, обязательный accessible label IconButton. Type tests отклоняют `color`, произвольный `variant` и `sx`. - [ ] **Step 2: Подтвердить RED** Run: `npm run test:design-system -- Text Heading Link Button IconButton` Expected: FAIL, exports отсутствуют. - [ ] **Step 3: Реализовать компоненты по public contracts** Каждый каталог содержит component, props и index. `Button loading` сохраняет ширину, блокирует повторный click и имеет `aria-busy`; `IconButton` всегда устанавливает `aria-label={label}`. - [ ] **Step 4: Добавить stories и проверить GREEN** Stories: все variants/sizes/tones, disabled, loading, long Russian label, keyboard focus reference. Run: `npm run test:design-system && npm run test:storybook && npm run build:storybook` Expected: PASS без a11y violations. - [ ] **Step 5: Commit** ```bash git add packages/design-system/src git commit -m "feat(design-system): add typography and actions" ``` ### Task 7: Inputs, surfaces и feedback (TDD) **Files:** - Create: `packages/design-system/src/components/{TextField,Select,Checkbox,Surface,Card,Chip,Badge,Alert,Dialog,Skeleton,Progress}/` - Test/Stories: colocated `*.test.tsx`, `*.stories.tsx` - [ ] **Step 1: Написать failing contract tests** Проверить label/helper/error association, Select options и keyboard opening, Checkbox label click, Surface padding/elevation mapping, Dialog focus/escape/label, Alert role, determinate/indeterminate Progress accessible name и Skeleton `aria-hidden`. - [ ] **Step 2: Подтвердить RED** Run: `npm run test:design-system -- TextField Select Checkbox Surface Card Chip Badge Alert Dialog Skeleton Progress` Expected: FAIL, components отсутствуют. - [ ] **Step 3: Реализовать ограниченные wrappers** `Select` принимает `{ value: string; label: string; disabled?: boolean }[]`; `Checkbox` требует `label`; `Dialog` требует `title` и управляется через `open/onClose`; Surface/Card не принимают raw elevation. - [ ] **Step 4: Stories, GREEN и commit** Stories покрывают default/focus/disabled/error/loading, длинный русский текст и narrow viewport. Run: `npm run test:design-system && npm run test:storybook && npm run build:storybook` Expected: PASS. ```bash git add packages/design-system/src git commit -m "feat(design-system): add controls and feedback" ``` ### Task 8: Финансовые data patterns (TDD) **Files:** - Create: `packages/design-system/src/components/{DataTable,Metric,Money,PriceChange}/` - Test/Stories: colocated `*.test.tsx`, `*.stories.tsx` - Test: `packages/design-system/src/visual/financial-patterns.visual.test.ts` - [ ] **Step 1: Написать failing tests** Проверить table caption, semantic headers, sortable button `aria-sort`, balanced/compact density, loading и empty states; `Money` через `Intl.NumberFormat`; `PriceChange` знак, текстовое направление и не только цвет; `Metric` composition. - [ ] **Step 2: Подтвердить RED** Run: `npm run test:design-system -- DataTable Metric Money PriceChange` Expected: FAIL. - [ ] **Step 3: Реализовать patterns** `DataTable` принимает готовый TanStack `Table` и не владеет server pagination/sorting. Defaults: `density="balanced"`, locale `ru-RU`, currency `RUB`. Negative/positive output включает видимый знак и screen-reader label. - [ ] **Step 4: Stories, visual baselines и commit** Canonical screenshot cases: balanced table, compact table, positive/negative metrics, empty/loading. Browser test запускает portable stories через `composeStories`, затем делает `expect(page.getByTestId('visual-root')).toMatchScreenshot('.png')`; baselines коммитятся рядом с visual test. Обновление baseline допустимо только вместе с объяснением визуального изменения. Run: `npm run test:design-system && npm run test:storybook` Expected: interaction, a11y и screenshot checks PASS. ```bash git add packages/design-system/src git commit -m "feat(design-system): add financial data patterns" ``` ### Task 9: Form и page-state patterns (TDD) **Files:** - Create: `packages/design-system/src/components/{FormField,FilterBar,EmptyState,ErrorState,LoadingState}/` - Test/Stories: colocated `*.test.tsx`, `*.stories.tsx` - [ ] **Step 1: Написать failing tests** Проверить `htmlFor`/description/error association FormField, wrapping and action placement FilterBar, semantic heading/action для Empty/Error, `aria-live="polite"` LoadingState и reduced-motion rendering. - [ ] **Step 2: RED, implementation, GREEN** Run before: `npm run test:design-system -- FormField FilterBar EmptyState ErrorState LoadingState` Expected before: FAIL. Реализовать только layout/semantics без API/domain knowledge. Run after: `npm run test:design-system && npm run test:storybook` Expected after: PASS. - [ ] **Step 3: Commit** ```bash git add packages/design-system/src git commit -m "feat(design-system): add form and page-state patterns" ``` ### Task 10: Frontend integration и MUI boundary **Files:** - Modify: `apps/frontend/package.json` - Modify: `apps/frontend/tsconfig.json` - Modify: `apps/frontend/vite.config.ts` - Modify: `apps/frontend/src/app/providers/AppProviders.tsx` - Modify: `apps/frontend/.eslintrc.cjs` - Delete: `apps/frontend/src/app/styles/theme.ts` - Test: `apps/frontend/src/app/providers/AppProviders.test.tsx` - [ ] **Step 1: Написать failing provider test** Render `AppProviders`, assert generated `--mv-palette-primary-main` exists and Query/Session providers по-прежнему доступны. Test не проверяет редизайн страниц. - [ ] **Step 2: Подключить workspace package** Добавить dependency, `@fontsource/inter` и aliases к source для dev/test; заменить MUI ThemeProvider/CssBaseline на `MoexVibeThemeProvider`. Удалить старый локальный theme и импортировать Inter 400/500/600/700 в provider entry ровно один раз. - [ ] **Step 3: Зафиксировать ESLint allowlist** Во frontend запретить root import `@mui/material` и subpaths через `no-restricted-imports`; исключить только `@mui/material/Box`, `Stack`, `Grid`. Сам пакет design-system использует отдельный lint config. - [ ] **Step 4: Проверить отсутствие визуальной миграции** Run: ```bash npm run test:frontend npm run lint -w apps/frontend npm run build:design-system npm run build:frontend ``` Expected: PASS; legacy `styles.css` и product component markup не изменены. - [ ] **Step 5: Commit** ```bash git add apps/frontend packages/design-system package.json package-lock.json git commit -m "feat(frontend): connect design system foundation" ``` ### Task 11: Docusaurus и ADR **Files:** - Create: `apps/docs/docs/design-system/{overview,foundations,tokens,components,patterns,accessibility,governance}.md` - Create: `apps/docs/docs/adr/ADR-016-design-system.md` - Create: `packages/design-system/CHANGELOG.md` - Modify: `apps/docs/sidebars.ts` - Modify: `apps/docs/docs/adr/index.md` - Modify: `apps/docs/docs/frontend/styling.md` - [ ] **Step 1: Написать канонические правила** Документы фиксируют light-only v1, balanced density, три token levels, MUI allowlist, каталог, component-card template, WCAG 2.2 AA и promotion/change process. Components page содержит матрицу «задача → компонент → не использовать» и полную карточку обязательного шаблона для каждого public export. `CHANGELOG.md` начинается с `0.1.0` и документирует public API foundation; governance описывает обязательную migration note для будущих breaking changes. - [ ] **Step 2: Добавить ADR-016** ADR содержит Context, варианты theme-only/hybrid/full-wrapper, решение hybrid, последствия, Storybook роль и будущие DTCG/Android adapters. - [ ] **Step 3: Обновить sidebar и проверить docs** Run: `npm run build:docs` Expected: PASS без broken links; новый раздел виден как отдельная категория «Дизайн-система». - [ ] **Step 4: Commit** ```bash git add apps/docs packages/design-system/CHANGELOG.md git commit -m "docs(design-system): publish usage guidelines" ``` ### Task 12: CI, visual checks и финальная верификация **Files:** - Modify: `.gitea/workflows/ci.yml` - Modify: `README.md` - Modify: `docs/features/design-system-foundation/tasks.md` - [ ] **Step 1: Добавить CI gates** После `npm ci` установить Chromium `npx playwright install --with-deps chromium`; добавить design-system unit/story tests, Storybook build, design-system build и docs build. Сохранять Storybook static build и visual diff через `actions/upload-artifact@v4` с `if: failure()`. - [ ] **Step 2: Обновить команды README** Добавить `npm run storybook`, `build:storybook`, `test:design-system`, `test:storybook`, `build:design-system` и пояснить, что Docusaurus — published docs, Storybook — engineering workbench. - [ ] **Step 3: Запустить полный DoD** ```bash npm run format:check npm run lint npm run test:backend npm run test:frontend npm run test:design-system npm run test:storybook npm run build:backend npm run build:design-system npm run build:storybook npm run build:frontend npm run build:docs git diff --check git status --short ``` Expected: все команды PASS; status содержит только намеренные изменения до финального commit. - [ ] **Step 4: Обновить SDD tasks и запросить code review** Отметить выполненные checkbox в `tasks.md`, применить `superpowers:requesting-code-review`, исправить только подтверждённые scope issues и повторить полный DoD. - [ ] **Step 5: Final commit** ```bash git add .gitea/workflows/ci.yml README.md docs/features/design-system-foundation git commit -m "ci(design-system): enforce foundation quality gates" ```