chore(release): 0.1.2 #17
@@ -0,0 +1,440 @@
|
||||
## Context
|
||||
|
||||
Локальная архитектура реализована; независимая публикация отложена. Baseline исследования — frontend `3c99deb`, версия `0.3.0`,
|
||||
2026-09-20. Требования — в
|
||||
[proposal](proposal.md) и [delta](specs/frontend-design-system/spec.md).
|
||||
|
||||
В приложении уже работают React, TypeScript, Vite, Mantine, TanStack Query,
|
||||
RHF/Zod, JSON-токены, общий адаптер темы, Storybook, Vitest/RTL/MSW,
|
||||
dependency-cruiser и Knip. Они сохраняются. Другие production-потребители
|
||||
общего UI или клиентского SDK в исследованном workspace не обнаружены.
|
||||
|
||||
На 2026-09-22 workspace-пакеты `@wealthledger/tokens`, `@wealthledger/ui` и
|
||||
`@wealthledger/icons` используются локально как private packages. Это принятая
|
||||
часть перехода. Описанные далее независимый release и Nexus остаются
|
||||
предложением, отложенным до оценки пилота. Фактическое выполнение и ограничения
|
||||
сохраняются в [tasks](tasks.md).
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:** три небольшие границы поставки общего фундамента; единый каталог
|
||||
источников; сохранение внешнего вида и предметных инвариантов; потребление
|
||||
собранного пакета; ограниченные задачи, исполнимые по одной сессии.
|
||||
|
||||
**Non-Goals:** другой UI framework, второй transport/store/form stack,
|
||||
универсальные CRUD/table/form engines, монорепозиторий всего WealthLedger,
|
||||
mobile adapter, тёмная тема, массовый rewrite CSS и тестирование внутренностей
|
||||
Mantine. Календарь платежей требует отдельного продуктового запроса.
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Репозиторий и направления зависимостей
|
||||
|
||||
Рекомендация: **npm workspaces внутри существующего frontend**. Корневое
|
||||
приложение сохраняет `src`, Vite entry, собственные providers и `private: true`.
|
||||
Новые пакеты располагаются в `packages/tokens`, `packages/icons`, `packages/ui`.
|
||||
Имена `@wealthledger/*` приняты для локальных packages; регистрация scope
|
||||
и внешняя registry-поставка не подтверждены.
|
||||
|
||||
| Вариант | Польза | Цена в этом проекте | Решение |
|
||||
| --- | --- | --- | --- |
|
||||
| Три workspace-пакета в frontend | Один lockfile, toolchain, Storybook и атомарный review источников с потребителем | Нужно явно расширить scopes проверок; локальный link может скрыть дефект поставки | Выбран; обязательна проверка packed consumer |
|
||||
| Один отдельный design-system repo с тремя пакетами | Отдельный owner, release cadence, независимые потребители | Новый CI/catalog/install, синхронизация PR и доступа к registry при одном приложении | Отложить до второго независимого production consumer либо отдельного владельца/release cadence |
|
||||
| Три отдельных Git repo | Полностью независимые права/жизненные циклы | Три workflow и совместимость без подтверждённой выгоды | Не выбирать |
|
||||
| Только существующий shared | Уже работает, нет стоимости публикации | Не даёт запрошенной границы версионируемой поставки | Сохраняется до готовности package foundations, не конечная цель |
|
||||
|
||||
Направление стрелки — «потребляет»; циклов нет:
|
||||
|
||||
```text
|
||||
frontend app / единственный Storybook
|
||||
├─ @wealthledger/ui ── @wealthledger/tokens
|
||||
│ └─ Mantine + React (peers у ui)
|
||||
├─ @wealthledger/icons ── React (peer)
|
||||
└─ entities/features/pages → shared/api, domain models, i18n
|
||||
|
||||
tokens → нет runtime dependencies
|
||||
ui → нет icons dependency до появления реального общего consumer
|
||||
icons → нет ui/tokens/Mantine/router/API dependencies
|
||||
```
|
||||
|
||||
Общие компоненты принимают уже подготовленные строки и slots. `EntryCard`
|
||||
принимает `ReactNode` и не знает, какой пакет рисует icon/action. Domain выбирает
|
||||
цвет по смыслу и форматирует деньги; UI только отображает переданное значение.
|
||||
|
||||
### 2. Публичная поверхность и сборка
|
||||
|
||||
Имена ниже в колонке «Цель» — принятые публичные exports локальных пакетов.
|
||||
Внутренние `src`, `dist/*` и application alias `@/` не являются package API.
|
||||
|
||||
| Пакет | Цель / entrypoints | Состав поставки | Зависимости |
|
||||
| --- | --- | --- | --- |
|
||||
| tokens | `@wealthledger/tokens/tokens.json` | Доверенный JSON v1; JS, CSS, React-адаптер и `.d.ts` на старте не нужны | Нет runtime dependencies |
|
||||
| icons | Именованные `AddIcon`, `EditIcon`, `DeleteIcon` из `@wealthledger/icons` | ESM JS + declarations; CSS только если переносится собственная анимация | React peer + external; React DOM не используется |
|
||||
| ui | `@wealthledger/ui`: `StateView`, `LoadingSkeleton`, `EntryCard` и их необходимые props types; `@wealthledger/ui/theme`: `theme`, `colorRoles`, `cssVariablesResolver`; `@wealthledger/ui/styles.css` | ESM JS + declarations + собранный CSS, включая CSS Modules | React/React DOM и используемые Mantine core/hooks — peers/external; tokens — точная dependency |
|
||||
|
||||
`designTokens` нужен foundations story: адаптер может сохранить существующий
|
||||
одноимённый export из `ui/theme`, который ссылается на JSON, а не копирует его.
|
||||
JSON остаётся отдельно доступным без Mantine. Не добавлять JS-обёртку в tokens
|
||||
только ради импорта JSON. Не выдавать non-web adapter за готовый.
|
||||
|
||||
Использовать установленный Vite для library build ui/icons и TypeScript для
|
||||
declarations. Один `tsc` недостаточен для CSS Modules `EntryCard`. Формат — ESM;
|
||||
CJS/SSR build не нужен текущему Vite SPA. Настройки library build ещё предстоит
|
||||
проверить на зафиксированной Vite 8.3.0; готовых конфигураций здесь нет.
|
||||
Публикуемые `files`/`exports` ограничивают поверхность. CSS явно включается в
|
||||
side effects; JS импорт сам не устанавливает provider и не читает приложение.
|
||||
Library build использует отдельную конфигурацию нужных plugins, не наследует
|
||||
app Vite config целиком: PWA/manifest/service worker и dev API proxy не должны
|
||||
попасть в поставку библиотеки.
|
||||
|
||||
Exports указывают на собранные artifacts, поэтому обычные local/CI entrypoints
|
||||
сначала собирают packages, затем выполняют consumer typecheck/tests/build.
|
||||
Сейчас `verify` начинает проверки до app build; этот порядок потребуется
|
||||
дополнить при 2.2. Acceptance начинается на чистом checkout после `npm ci`,
|
||||
без старого package dist/cache. Достаточно последовательности npm scripts,
|
||||
без собственного build orchestrator.
|
||||
|
||||
Docker — отдельный потребитель workspace: нынешний `Dockerfile` копирует только
|
||||
root manifests перед `npm ci`, а `.dockerignore` не допускает packages.
|
||||
В 2.1–2.2 нужны точечные manifests/source/build-config allowlists, установка
|
||||
с workspace manifests и package build перед consumer. Host node_modules,
|
||||
готовый локальный dist и реальные `.env` в контекст не попадают. Development
|
||||
и production targets проверяются отдельно. В текущем Compose монтируются
|
||||
только app src/public: изменения packages сначала требуют rebuild dev image.
|
||||
Отдельный package bind-mount/watch в Compose отложен до фактической потребности;
|
||||
host development может использовать package watch без изменения root repo.
|
||||
|
||||
Сначала peer ranges узкие, по проверенной комбинации React 19.3.0 и Mantine
|
||||
9.6.1; расширять их только после проверки потребителя. React/React DOM
|
||||
devDependencies для разработки не должны попадать в bundle. Проверять
|
||||
`npm ls react react-dom @mantine/core` и содержимое bundle/packed consumer;
|
||||
`dedupe` не заменяет корректную упаковку. Две несовместимые версии Mantine
|
||||
также нельзя скрыть локальным symlink.
|
||||
|
||||
### 3. Токены: использовать уже существующий JSON
|
||||
|
||||
В [tokens.json](../../../../frontend/packages/tokens/tokens.json) уже есть
|
||||
переносимые значения и описания. **Не менять формат v1 ради упаковки.**
|
||||
`primitive → semantic → component` — модель владения и ссылок, а не повод
|
||||
немедленно переименовать все ключи в новый стандарт.
|
||||
|
||||
| Уровень | Текущая основа и целевое правило |
|
||||
| --- | --- |
|
||||
| Primitive | `color.base`, `color.palettes`, `typography`, `spacing.values`, `radius.values`, `shadows.values`, `breakpoints.values`; исходные эффективные значения сохраняются |
|
||||
| Semantic | Существующие `color.roles.*` с `color` + `shade` ссылаются на primitive; `primary` с `shade: null` сохраняет разрешение через primaryShade |
|
||||
| Component | Пока новые не нужны. Добавлять только именованный совместно управляемый контракт реального общего компонента, если semantic role недостаточно; ссылаться на semantic, затем primitive при отсутствии смысловой роли |
|
||||
|
||||
Имена описывают роль (`surface`, `border`, `positive`), а не экран или случайный
|
||||
цвет. Ссылки однонаправленные и разрешимые; обратных ссылок из primitive на
|
||||
semantic/component нет. Новый color role включает назначение и ограничение
|
||||
применения. Семантический положительный цвет не вычисляет знак финансовой суммы.
|
||||
|
||||
Сохранить единицы: размеры/тени в px адаптируются существующими `rem`/`rgba`,
|
||||
breakpoints в em не масштабируются, line-height без единицы. Имеющиеся
|
||||
[theme tests](../../../../frontend/packages/ui/src/theme.test.ts) защищают
|
||||
именно преобразования и ссылки, не каждое значение JSON.
|
||||
|
||||
Общие CSS-роли `--wl-color-*` производит прежний `CSSVariablesResolver`.
|
||||
Spacing/radius/type scales продолжают поступать в Mantine theme и его CSS
|
||||
variables. Статическая генерация второго `tokens.css` не нужна: появился бы
|
||||
ещё один адаптер и риск расхождения scale. JSON экспортируется без сборочного
|
||||
token engine; Style Dictionary, DTCG-converter и runtime schema отложены до
|
||||
конкретного внешнего потребителя/формата. Источник остаётся доверенным файлом,
|
||||
не внешним пользовательским документом.
|
||||
|
||||
Светлая схема сохраняется. `primaryShade.dark` не означает готовую dark theme.
|
||||
Бизнес-коды, суммы/валюты, московские даты, pagination limits, brand gradients
|
||||
`BankCardFace` и случайная геометрия SVG не превращаются в глобальные токены.
|
||||
Первое применение semantic roles — точные эквиваленты gray-3/gray-0/green-6/
|
||||
red-6 в `EntryCard`; перенос и эта правка идут отдельно.
|
||||
|
||||
### 4. Mantine, тема и providers
|
||||
|
||||
`Stack`, `Group`, `Button`, `Paper`, `ActionIcon`, поля, Modal, Dates/Charts
|
||||
остаются прямыми импортами Mantine. Изменение defaults решается темой.
|
||||
Wrapper нужен только собственному контракту: busy region у `LoadingSkeleton`,
|
||||
empty/error composition у `StateView`, layout/image fallback/actions у `EntryCard`.
|
||||
|
||||
App владеет MantineProvider, DatesProvider, QueryClientProvider, AuthProvider,
|
||||
Router и i18n. Storybook имеет свой Mantine/Dates/i18n runtime с той же темой.
|
||||
UI не создаёт `WealthLedgerProvider`, не импортирует локализацию продукта и
|
||||
не включает app providers. `ui/styles.css` содержит существующую визуальную
|
||||
основу и стили общих компонентов; app/preview подключают его явно после
|
||||
Mantine CSS. Продуктовые route transitions и bank-card styles остаются в app.
|
||||
|
||||
Theme Modal transition и глобальная CSS animation сейчас сосуществуют.
|
||||
Их визуальный конфликт не доказан. После выделения выбрать один механизм
|
||||
открытия по browser comparison, предпочтительно уже настроенный Mantine
|
||||
transition; нельзя удалить второй механизм на основании одного сходства кода.
|
||||
|
||||
### 5. Иконки и движение
|
||||
|
||||
Начальный набор — реально повторяющиеся plus/pencil/trash из Card/Cards views.
|
||||
Имена `AddIcon`, `EditIcon`, `DeleteIcon` — предлагаемая поверхность, не найденные
|
||||
exports. Размер задаёт `size` (default 24), геометрия сохраняет `viewBox`, цвет
|
||||
получается через `currentColor`. Существующие размеры и strokeWidth 1.5/2
|
||||
сохраняются у callers; выравнивание рисунка не совмещается с переносом.
|
||||
|
||||
Канонический исходник SVG для небольшого набора — **SVG-разметка в именованных
|
||||
React-компонентах** `packages/icons/src/svg/<Name>.tsx`. Это один редактируемый
|
||||
источник, без параллельных ручных `.svg` и `.tsx`. Отдельные raw SVG-файлы в
|
||||
первой поставке не публикуются: non-React consumer пока отсутствует. Если
|
||||
потребуются исходные `.svg` как самостоятельный продуктовый артефакт, перенести
|
||||
канон в `src/svg/*.svg` и сравнить штатный SVGR CLI с ручным поддержанием;
|
||||
не писать собственный генератор. Сейчас ни dependency, ни pipeline для этого
|
||||
не нужны. JS/types несут SVG-компоненты, это явно отражено в составе поставки.
|
||||
|
||||
По умолчанию рисунок декоративный (`aria-hidden`, без фокуса). У standalone
|
||||
meaningful icon потребитель задаёт доступное имя и image semantics. У
|
||||
`ActionIcon` имя остаётся на действии; SVG не дублирует его. Общий пакет не
|
||||
выбирает подпись «редактировать операцию» и не получает DTO.
|
||||
|
||||
`BankOperationIcon` и `operation-appearance.ts` остаются в entity: mapping
|
||||
category/kind → рисунок/цвет/анимация — бизнес-логика. Собственная геометрия и
|
||||
движение рисунка могут перейти в icons позже при реальном reuse. Hover/focus
|
||||
trigger по сценарию, route transitions, bank/card state остаются приложению.
|
||||
Существующий `bind-icon-animation` переиспользуется, если переносится тот же
|
||||
animation contract; он не копируется в пакет ради трёх статичных иконок.
|
||||
Все переносимые движения обязаны сохранять reduced-motion поведение.
|
||||
|
||||
### 6. Каталог источников компонентов
|
||||
|
||||
Порядок поиска: **существующие компоненты приложения → собственная библиотека
|
||||
→ Mantine → уже разрешённые dependencies → обоснованное новое решение**.
|
||||
Новый компонент появляется у владельца реальной ответственности, а не потому,
|
||||
что текущий компонент отсутствует в Storybook. Таблица — компактный маршрут,
|
||||
не каталог каждого JSX-узла. Номера обозначают этапы в [tasks](tasks.md).
|
||||
|
||||
| Назначение | Текущий источник | Целевой источник | Правило применения | Этап |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Layout, buttons, inputs, dialogs | `@mantine/core`, `@mantine/dates` | Те же пакеты | Прямые imports; variant/default через theme, не WL-копия каждого primitive | 1, 2 |
|
||||
| Цветовые роли, шкалы | `shared/theme/tokens.json` | `tokens/tokens.json` + адаптер `ui/theme` | JSON — значения, адаптер — Mantine, бизнес-смысл — consumer | 2 |
|
||||
| Тема/общие стили | `shared/theme` | `ui/theme`, `ui/styles.css` | Одна тема App/Storybook; providers у runtimes | 2 |
|
||||
| Busy skeleton region | `shared/ui/LoadingSkeleton` | `ui` | Label и region общие, skeleton shapes принадлежат странице | 3.1 |
|
||||
| Empty/error | `shared/ui/StateView` | `ui` | Строки/action props; query/error classification вне UI | 3.1 |
|
||||
| Строка с изображением и значением | `shared/ui/EntryCard` | `ui` | Готовые strings/slots, fallback и responsive actions; без money parsing | 3.2–3.3 |
|
||||
| Plus/edit/delete | Inline SVG Card/Cards views | `icons` | Named imports; label и disabled у ActionIcon | 4 |
|
||||
| Навигация и active route | `shared/ui/AppShell` | `app/ui` | Product shell; не публичный компонент ui-пакета | 1.1 |
|
||||
| Карта и её операции | `entities/bank-card` | Там же | `BankCardFace`, `BankOperationIcon`, `BankSummaryView`, `BankCardFields`, `BankFeedback` — domain | Без переноса |
|
||||
| Период банковских данных | `entities/bank-card/BankPeriodPicker`, model/period | Там же | Draft/URL/query semantics сохраняются; не универсальный date service | 5, без extraction |
|
||||
| Период дохода | `pages/account-income/.../IncomePeriodForm.view` | Та же page; pure helpers в её model | Изолировать story от VM, сохранить validation/submit | 5.3 |
|
||||
| Позиции/структура портфеля | `pages/account/ui/components/PositionCard.view`, `PortfolioStructure.view` | Там же | Page-local композиция допустима; не переделывать под EntryCard | Без переноса |
|
||||
| Недавние события | `entities/brokerage-event` + Account page | Там же; общий EntryCard из ui | Первый продуктовый пилот, финансовое представление у entity | 3.2 |
|
||||
| Общие instrument details | `features/instrument-details` | Там же | Реальный reuse stocks/bonds; typed presentation contract отдельно от общего UI | Без переноса |
|
||||
|
||||
Последние непакетные источники выбираются через существующие `index.ts`.
|
||||
В таблице обозначения `shared/ui/...` описывают файлы до миграции; это не разрешение
|
||||
на deep import. Текущие владельцы указаны в колонке цели.
|
||||
|
||||
### 7. Предметный UI, API и конечные словари
|
||||
|
||||
Рекомендация: оставить domain UI в `entities/features/pages`. Второй
|
||||
производственный consumer, которому нужен тот же стабильный domain contract,
|
||||
и отдельный release owner — проверяемое условие рассмотрения business package.
|
||||
Storybook не считается таким потребителем. Повторная карточка может потребовать
|
||||
переноса page → entity внутри приложения, но не нового npm-пакета.
|
||||
|
||||
`shared/api` сохраняет snapshot, generated types, typed transport и auth-aware
|
||||
boundary. Генерируются **типы**, а не весь handwritten client. Query keys,
|
||||
normalization, freshness и invalidation остаются в entity/feature owner;
|
||||
не входят ни в generated artifact, ни в ui. Отдельный `api-client` сейчас
|
||||
потребовал бы отделить Vite environment, auth/retry lifecycle и query policy без
|
||||
второго потребителя. Вернуться к вопросу при втором независимом приложении.
|
||||
|
||||
Backend остаётся единственным editable HTTP source. Frontend получает
|
||||
предоставленный snapshot, локально генерирует и сравнивает declarations;
|
||||
соседний backend checkout не становится входом CI. DTO aliases из generated
|
||||
`paths` сохраняются. UI form models допустимы, когда отличаются от transport.
|
||||
|
||||
Для frontend собственных конечных словарей — принятый `as const` + union:
|
||||
`enum` несовместим с текущим `erasableSyntaxOnly`. Набор operation kinds можно
|
||||
свести у bank entity и проверить через generated `BankOperation['kind']`;
|
||||
не объявлять вторую DTO enum. Wire literals сохраняются. `ProblemDetailsDto.code`
|
||||
остаётся `string`, unknown code получает fallback; нельзя объявлять закрытый
|
||||
список ошибок. Общий `apiErrorCode` извлекает code, одинаковое recovery
|
||||
классифицируется ближайшим допустимым owner без обратных FSD imports.
|
||||
|
||||
### 8. Политика библиотек
|
||||
|
||||
Версии закреплены в frontend package manifests и lockfile. Решения ниже
|
||||
не означают новой установки или обновления.
|
||||
|
||||
| Область | Сейчас | Решение и причина | Этап |
|
||||
| --- | --- | --- | --- |
|
||||
| Build/React/Router | Vite, TS, React Compiler, React Router | Сохранить; расширить имеющийся build для library artifacts | 2 |
|
||||
| Server/local state | TanStack Query / React state / URL | Сохранить owners; Redux из transitive deps не делает его app store | Все |
|
||||
| Forms/validation | RHF, resolvers, Zod | Сохранить; vocabulary у entity, controller/view банковской формы отдельно | 5.2, 5.4 |
|
||||
| UI/charts | Mantine; Recharts/react-is обеспечивают peer graph charts | Сохранить, не удалять peer deps из-за отсутствия direct imports | Все |
|
||||
| Styles/условные классы | CSS Modules, template/ternary, data-* | Сохранить один этот подход; clsx/classnames не вводить без сложности, которой здесь нет | 3–5 |
|
||||
| Icons | Inline SVG | Унифицировать повторяющиеся общие рисунки в малом собственном наборе | 4 |
|
||||
| Motion | motion для routes, CSS/native для рисунков | Сохранить по разным владельцам; проверить дублирование Modal отдельно | 5.1 |
|
||||
| Dates | Day.js + Mantine Dates + native Date/Intl | Сохранить роль каждого; Moscow/ISO policy остаётся domain/page | 5.3 |
|
||||
| Money | String + BigInt cents, display formatters | Сохранить точность и unknown≠zero; decimal library не добавлять | Все |
|
||||
| API/errors | openapi-fetch/react-query/typescript | Сохранить; не добавлять axios, второй generator или schema registry | Все |
|
||||
| Tests | Vitest/RTL/MSW | Сохранить; `fireEvent` принят, user-event только transitively | 2–5 |
|
||||
| Catalog | Storybook 10.6.0 | Один runtime, расширить glob и границы на packages | 2–4 |
|
||||
| Quality | Biome, Knip, dependency-cruiser | Дополнить действующие scopes, не ставить Steiger/ещё один analyzer | 1–2 |
|
||||
| Browser/visual CI | Принятого E2E runner/visual diff нет | Ручной browser proof пилота; Playwright — при повторяемой browser-only регрессии и владельце CI | Отложено |
|
||||
| Release | release-it + native npm + Gitea | Использовать текущий подход, адаптировать workspace releases; Changesets/Lerna не нужны для трёх пакетов | 6 |
|
||||
|
||||
### 9. Предлагаемое уточнение conventions
|
||||
|
||||
Это предложения для будущих задач; действующие инструкции сейчас не меняются.
|
||||
AGENTS остаётся коротким router, постоянный каталог переносится в подходящий
|
||||
раздел existing UI convention/README после подтверждённого перехода.
|
||||
|
||||
| Владелец правила | Конкретное уточнение | Когда |
|
||||
| --- | --- | --- |
|
||||
| `.ai/architecture.md` | Package graph вне FSD; src public APIs; app shell; никакого package → app или same-layer обхода | 1–2 |
|
||||
| `.ai/conventions/ui.md` | Каталог источников и search order; тема против wrapper; props-only общие компоненты | 2–3 |
|
||||
| UI + Storybook | JSON/semantic roles, explicit CSS import, светлая схема, иконки/currentColor/reduced-motion | 2–4 |
|
||||
| `.ai/conventions/data.md`, TypeScript/React | Generated vocabulary vs local const unions; errors открыты; package не владеет query state | 5.2 |
|
||||
| Engineering/dependencies | Workspace direct deps, peers, exact lock, packed consumer, ограничения exports | 2, 6 |
|
||||
| Storybook | Один runtime, colocated package/product stories, новые reachability scopes | 2–3 |
|
||||
| Testing | Поведение → риск → минимальная boundary; package artifact contract; browser proof не равен build | 2–3, 6 |
|
||||
|
||||
### 10. Storybook и проверки
|
||||
|
||||
Один существующий frontend Storybook показывает `Design System` и `Product`.
|
||||
Общие stories переезжают вместе с ui/icons; foundations читают опубликованный
|
||||
JSON/адаптер. Product stories остаются рядом с entities/pages. Обновляются
|
||||
только globs/aliases/check scopes, не создаётся отдельное приложение каталога.
|
||||
Mantine/theme/Dates/i18n уже есть в preview; Query/Auth/API providers не нужны.
|
||||
Synthetic props и callbacks сохраняются; MSW остаётся в Vitest, не в worker.
|
||||
|
||||
| Наблюдаемый контракт | Минимальный способ доказать |
|
||||
| --- | --- |
|
||||
| JSON → размеры/тени/semantic CSS, unscaled breakpoints | Перенести существующие theme unit tests; не проверять каждый literal |
|
||||
| JS/types/CSS/JSON доступны вне workspace | Pack + чистый consumer с type/build/render и без source aliases |
|
||||
| EntryCard image fallback, actions при focus/touch | Один небольшой RTL case на собственный fallback/действие, synthetic story и browser review |
|
||||
| Деньги/version/idempotency/invalid input | Существующие targeted RTL/MSW tests формы; новые cases только если меняется соответствующая boundary |
|
||||
| Query/auth/recovery | Имеющиеся MSW tests; no real backend; не тестировать это через stories |
|
||||
| Keyboard/name/reduced motion/narrow layout | Выбранные собственные interactions в browser; примитивные гарантии Mantine не переписывать |
|
||||
|
||||
`build:catalog` не исполняет `play`; существующий `storybook.test.tsx` проверяет
|
||||
лишь выбранные группы. Не обещать screenshot regression по факту сборки.
|
||||
Snapshot всех компонентов и полный новый E2E stack не планируются.
|
||||
|
||||
Новые workspace-папки не охвачены автоматически: нынешние TS/Knip/deps/story
|
||||
настройки главным образом ориентированы на `src`. Package type/build/lint,
|
||||
dependencies и запрет app imports вводятся вместе с соответствующим пакетом.
|
||||
Нельзя временно исключить packages целиком и назвать gate полным. Same-layer
|
||||
rule сначала проверяется на текущем graph, затем включается для чистого scope;
|
||||
legacy exception имеет имя, причину и задачу удаления. Existing coverage floors
|
||||
не понижаются; перенос tests/coverage ownership не должен скрыть потерю сценария.
|
||||
|
||||
### 11. Локальная работа и потребление
|
||||
|
||||
Приняты приватные npm workspaces внутри frontend: один install/lockfile,
|
||||
сборка пакетов и потребление через exports. Проверки охватывают приложение,
|
||||
пакеты и Storybook. Собранные tarballs проверены вне workspace без source aliases;
|
||||
эта проверка выявляет отсутствующие exports, типы, CSS и несовместимые peers.
|
||||
|
||||
Публикация, независимый SemVer, package release automation и настройка Nexus
|
||||
не входят в текущий переход. Вернуться к ним можно при подтверждённой пользе
|
||||
для независимого потребителя; тогда отдельно определить registry, права,
|
||||
неизменность версий, совместимость и откат. Текущий app release не меняется.
|
||||
|
||||
## UI/UX Applicability and Package
|
||||
|
||||
**Applicability: N/A для нового визуального дизайна.** Цель — сохранение уже
|
||||
существующего приложения, без новых экранов и рисунков. Новый макет/visuals и
|
||||
hash registry не создаются. Для проверки переноса выбран следующий scope.
|
||||
|
||||
Пилот: `AccountPage → useAccountPageViewModel → useBrokerageEvents →
|
||||
BrokerageEventsPreview → BrokerageEventCard → EntryCard`. Это read-only
|
||||
preview выплат; `PositionCard` не использует EntryCard и не подходит для
|
||||
переноса без изменения представления. Generic icons в пилоте отсутствуют и
|
||||
мигрируют отдельно в Card/Cards.
|
||||
|
||||
Сохраняются loaded/loading/error/empty, missing amount как unknown, а не ноль,
|
||||
registry-date/account metadata, валюта, logo fallback, длинные строки,
|
||||
preview limit и ссылка полного списка. Сверяются desktop и viewport 375px,
|
||||
доступный focus и отсутствие горизонтального overflow. У generic EntryCard
|
||||
actions дополнительно проверяются fine/coarse pointer и reduced motion на
|
||||
synthetic story. Текущий RecentEvents error-priority не меняется молча.
|
||||
|
||||
## Delivery Map
|
||||
|
||||
| Area | Status | Architectural outcome or N/A reason |
|
||||
| --- | --- | --- |
|
||||
| frontend | affected | Workspaces tokens/icons/ui, ограниченная миграция, checks и package release integration |
|
||||
| backend | N/A | Пакеты не меняют HTTP/auth/storage; замечание об errors вынесено в отложенный scope |
|
||||
| specs | affected | Этот change и новые требования к поставке/иконкам; main specs обновятся только после принятой реализации |
|
||||
| docs | affected | После поставки уточняются design overview и описание frontend container/release boundary |
|
||||
|
||||
## Solution Assessment
|
||||
|
||||
| Решение | Fit / зрелость / ограничения / стоимость | Выбор |
|
||||
| --- | --- | --- |
|
||||
| Существующие npm workspaces + Vite/TS | Стандартная упаковка; не требует нового Git repo; CSS/peers и published surface нуждаются в проверке | Да |
|
||||
| Отдельный design-system repo | Ясная независимость ownership, но удваивает окружение каталога/CI при одном app | Позже по явному consumer/owner trigger |
|
||||
| Style Dictionary или собственный token compiler | Полезны нескольким форматам/платформам; сейчас JSON + Mantine adapter уже решают задачу | Нет; runtime trust boundary не меняется |
|
||||
| Ручные React SVG / SVGR pipeline | Несколько рисунков дешевле поддерживать в одном TSX source; SVGR нужен каноническим raw SVG exports | Ручные SVG-компоненты сейчас, без генератора |
|
||||
| release-it/native npm / Changesets | Первый стек уже принят; второй полезен большому потоку независимых release contributions | Сохранить существующий app release; независимый package release отложен |
|
||||
|
||||
Новые внешние runtime dependencies не требуются. Риск supply chain сохраняется
|
||||
под существующим security gate; peer/version checks и registry ACL нельзя
|
||||
заменить предположением о готовом Nexus.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- Workspace links скрывают отсутствующие exports/assets и конфликт React:
|
||||
независимый packed consumer обязателен.
|
||||
- Package graph расширяет проверяемую область: старый зелёный `deps src` не
|
||||
подтверждает новые packages. Scopes расширяются при появлении владельца.
|
||||
- CSS order/global reset влияют на всё приложение. Сначала перенос без
|
||||
изменения значений, затем отдельно semantic roles и Modal consolidation.
|
||||
- Общие исходники в frontend — осознанный выбор для одного потребителя;
|
||||
публикация не означает уже существующий независимый каталог/команду.
|
||||
- Изменение view/controller рядом с денежной формой рискованнее UI extraction:
|
||||
это отдельная поздняя задача с сохранением tests version/idempotency.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Границы owners → package foundations → общие компоненты и read-only пилот →
|
||||
иконки и точечное выравнивание → packed consumer → удаление совместимости.
|
||||
Единственный подробный backlog и зависимости находятся в [tasks](tasks.md).
|
||||
|
||||
Во время перехода `shared/theme` и три старых UI entrypoints могут быть тонкими
|
||||
re-exports package API. Они не содержат второй JSON, CSS или реализации.
|
||||
Новые consumers используют package paths; добавлять exports/логику в facade
|
||||
запрещено. Удаление — когда поиск оставшихся runtime/test/story imports даёт
|
||||
ноль и app/catalog/packed consumer прошли gates. Старые inline icons живут до
|
||||
своего consumer batch, но новые копии извлечённых рисунков не добавляются.
|
||||
|
||||
### Rollback Contract
|
||||
|
||||
| Field | Decision |
|
||||
| --- | --- |
|
||||
| Status | required: меняются локальные imports, сборка и владельцы компонентов |
|
||||
| Trigger | Нет exports/CSS/types, peer conflict, несовместимое представление либо failed pilot/recovery |
|
||||
| Actions | Вернуть согласованный diff приложения, packages, imports и lockfile; при выпуске приложения использовать прежний app image |
|
||||
| Data safety | API/storage/money wire format не меняются; не откатывать чужие продуктовые изменения и не сбрасывать пользовательские данные |
|
||||
| Verification | Повторить соответствующий consumer gate и пилот на прежней версии; проверить восстановление согласованного состояния приложения и packages |
|
||||
|
||||
### Осознанно отложенное
|
||||
|
||||
| Находка/возможность | Причина и условие возврата |
|
||||
| --- | --- |
|
||||
| F8: RecentEvents error приоритетнее cached data | Реальное отличие от общего recovery convention. Не менять при extraction; отдельная product recovery задача после согласования expected stale/error UX, с refetch-error regression test |
|
||||
| F9: ProblemDetails errors schema/example и validation mapping | Отдельная backend contract задача: metadata + HTTP behavior test, затем предоставленный snapshot; не основание вручную исправлять frontend DTO |
|
||||
| F12: Основная frontend-quality-guardrails spec требует initial 500 kB и baseline lazy chunks, а действующий verify не содержит такого gate | Отдельно согласовать актуальность сохранённого требования и способ enforcement. Не считать Vite warning блокирующим budget gate; package migration сравнивает фактический размер сборки, не заявляя выполнения отсутствующей проверки |
|
||||
| Единый recovery classifier всех investment errors | Одинаковые codes ещё не доказывают одинаковый UX; объединять только подтверждённый общий recovery без нарушения FSD |
|
||||
| Business/API packages, dark/mobile, raw SVG pipeline, Playwright/visual service | Нет принятого второго consumer или значимого browser-only regression scope |
|
||||
|
||||
## Решения для подтверждения перед зависимыми действиями
|
||||
|
||||
1. Публичные имена `@wealthledger/tokens`, `@wealthledger/icons`, `@wealthledger/ui`,
|
||||
scope ownership и видимость. Рекомендуется приватная поставка WealthLedger;
|
||||
другое решение меняет доступ и release setup, не текущие данные.
|
||||
2. Nexus npm endpoint, владелец publish/read credentials, политика неизменности
|
||||
и хранения прошлых версий. Эти решения нужны только при отдельном запросе внешней публикации.
|
||||
3. Расхождение F12 между сохранённой spec и текущими quality-командами:
|
||||
рекомендуемый default — сохранять требование до отдельного решения владельца,
|
||||
не ослаблять его и не объявлять выполненным. Автоматизация либо корректировка
|
||||
требования оформляются отдельным ограниченным scope после уточнения причины.
|
||||
|
||||
Остальное — аргументированные defaults данного предложения, а не список
|
||||
неразрешённых вопросов. Перед реализацией нужен отдельный запрос пользователя;
|
||||
workspaces внутри frontend уже реализованы, независимые версии остаются отложенными.
|
||||
@@ -0,0 +1,69 @@
|
||||
## Why
|
||||
|
||||
У WealthLedger уже есть общий визуальный фундамент, каталог компонентов и
|
||||
типизированное взаимодействие с сервером. Следующий шаг — сделать границы
|
||||
переиспользования и поставки этого фундамента явными: участник должен быстро
|
||||
находить подходящее решение, а приложение — получать проверенную совместимую
|
||||
версию без копирования реализаций.
|
||||
|
||||
Исследование текущего frontend выявило конкретные незавершённые границы:
|
||||
повторяющиеся рисунки иконок, обход существующих цветовых ролей, продуктовую
|
||||
навигацию в общем UI и неполную автоматизацию архитектурных ограничений.
|
||||
|
||||
## What Changes
|
||||
|
||||
**Статус: локальная реализация и итоговая проверка завершены.**
|
||||
Локальные границы приложения и private workspace-пакеты реализованы;
|
||||
проверенные пункты и оставшиеся ограничения перечислены в [tasks](tasks.md).
|
||||
Независимое версионирование и публикация через Nexus отложены до оценки пользы
|
||||
пилота и не входят в требования этого перехода.
|
||||
|
||||
Первоначальный комплект плановых Markdown-файлов был подготовлен по запросу
|
||||
пользователя в одной сессии. Последующие разрешения касались ограниченных
|
||||
этапов; они не разрешают публикацию, deployment или archive.
|
||||
|
||||
- Выделить используемый общий визуальный фундамент в приватные workspace-пакеты,
|
||||
сохранив внешний вид и работоспособность приложения между небольшими этапами.
|
||||
- Установить единый порядок выбора компонентов и понятную границу между
|
||||
общим представлением, предметным UI и сценариями приложения.
|
||||
- Сделать повторно используемые собственные иконки доступными с единым
|
||||
визуальным и доступным контрактом.
|
||||
- Подтвердить переход существующим небольшим продуктовым срезом и проверкой
|
||||
потребления собранных артефактов, а не только локальных исходников.
|
||||
- Уточнить применимые инженерные правила после соответствующих изменений,
|
||||
сохранить существующие проверки и поэтапно закрыть найденные пробелы.
|
||||
|
||||
Сохраняются денежная точность, обработка неизвестных значений, поведение
|
||||
авторизации, запросов, форм, восстановления после ошибок и существующих страниц.
|
||||
Предметные расчёты и серверные контракты не становятся частью общего UI.
|
||||
|
||||
Не входят редизайн, тёмная тема, мобильный адаптер, календарь обязательных
|
||||
платежей, смена работающего стека, переустройство всех репозиториев и массовое
|
||||
перемещение компонентов. Публикация, deployment, commit, push, PR и archive не разрешены.
|
||||
Локальная реализация ограничена отдельно согласованными этапами.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
Нет: новая capability на каждый пакет или каталог не требуется.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `specs/frontend-design-system/spec.md`: добавить требования к потреблению
|
||||
локальных пакетов общего фундамента и доступному контракту собственных
|
||||
общих иконок. Существующие требования к единой теме и предметной независимости
|
||||
сохраняются. [Delta](specs/frontend-design-system/spec.md).
|
||||
|
||||
## Impact
|
||||
|
||||
- Frontend: поставка общей основы, выбор источников компонентов, ограниченная
|
||||
миграция потребителей и развитие существующих проверок.
|
||||
- Backend: производственный контракт и поведение не меняются; отдельное
|
||||
замечание к описанию ошибок остаётся отложенным исследованием владельца API.
|
||||
- Specs: этот change и delta; основные as-built требования пока не изменяются.
|
||||
- Docs: описание текущего локального устройства обновлено в 7.2;
|
||||
независимая registry-поставка не заявляется.
|
||||
|
||||
Решения, альтернативы и каталог источников — в [design](design.md), единственная
|
||||
очередь работ и текущее состояние — в [tasks](tasks.md).
|
||||
@@ -0,0 +1,60 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Общий фундамент доступен через проверяемые локальные пакеты
|
||||
|
||||
Общий визуальный фундамент SHALL принадлежать приватным npm workspaces внутри
|
||||
frontend и иметь явную публичную поверхность. Приложение SHALL использовать
|
||||
пакеты через объявленные exports. Собранные артефакты MUST содержать модули,
|
||||
типы, стили и данные согласно контракту каждого пакета и быть пригодными для
|
||||
проверки вне рабочего дерева frontend. Общие пакеты MUST NOT требовать серверных
|
||||
данных, авторизации, маршрутов или состояния WealthLedger. Совместимость пакетов
|
||||
между собой и с приложением SHALL проверяться; workspace links MUST NOT быть
|
||||
единственным подтверждением пригодности артефактов. Независимые релизы и
|
||||
публикация в registry не входят в этот переход.
|
||||
|
||||
#### Scenario: Приложение потребляет собранную поставку
|
||||
|
||||
- **WHEN** потребитель устанавливает собранные артефакты в чистом окружении без
|
||||
ссылок на рабочее дерево поставщика
|
||||
- **THEN** публичные модули, типы, стили и данные доступны, общий компонент
|
||||
отображается на заявленной теме без зависимостей от приложения поставщика
|
||||
|
||||
#### Scenario: Локальная разработка скрыла отсутствующий артефакт
|
||||
|
||||
- **WHEN** локальная ссылка разрешает импорт, отсутствующий в собранной поставке
|
||||
- **THEN** поставка не признаётся готовой по результату одной локальной сборки;
|
||||
потребление именно собранных артефактов должно быть подтверждено отдельно
|
||||
|
||||
#### Scenario: Приложение использует локальные пакеты
|
||||
|
||||
- **WHEN** frontend устанавливает зависимости из своего lockfile и собирается
|
||||
- **THEN** приватные workspaces доступны через публичные exports без публикации
|
||||
в registry; предметные компоненты и API-клиент остаются в приложении
|
||||
|
||||
### Requirement: Собственные общие иконки имеют доступный контракт
|
||||
|
||||
Общие иконки SHALL иметь предсказуемые размеры и возможность получать цвет
|
||||
от потребителя, не определяя бизнес-смысл операции или состояние приложения.
|
||||
Декоративная иконка MUST NOT создавать отдельную точку фокуса или повторять
|
||||
доступное имя соседнего действия. Смысловая иконка без сопровождающего текста
|
||||
MUST иметь доступное имя. Собственное движение иконки SHALL учитывать
|
||||
предпочтение уменьшенного движения; выбор момента запуска по пользовательскому
|
||||
сценарию SHALL оставаться у потребителя.
|
||||
|
||||
#### Scenario: Иконка находится в именованном действии
|
||||
|
||||
- **WHEN** собственная иконка дополняет кнопку с доступным именем
|
||||
- **THEN** кнопка сохраняет имя и клавиатурное поведение, а рисунок декоративен
|
||||
и не создаёт дополнительную точку фокуса
|
||||
|
||||
#### Scenario: Рисунок самостоятельно передаёт смысл
|
||||
|
||||
- **WHEN** иконка используется без текста и без именованного родительского
|
||||
элемента как самостоятельное изображение
|
||||
- **THEN** потребитель задаёт доступное имя, передающее её назначение
|
||||
|
||||
#### Scenario: Пользователь уменьшил движение
|
||||
|
||||
- **WHEN** включено предпочтение уменьшенного движения
|
||||
- **THEN** необязательная анимация общей иконки не выполняется, а значение и
|
||||
доступность действия сохраняются
|
||||
@@ -0,0 +1,239 @@
|
||||
# План перехода frontend
|
||||
|
||||
**На 2026-09-22 выполнены и проверены 1.1–1.2, 2.1–2.2, 3.1–3.3, 4.1–4.2, 5.1–5.4 и 7.1–7.3** по отдельному
|
||||
разрешению пользователя. Остальные задачи — предложения, не разрешение
|
||||
на реализацию или публикацию. Результаты и ограничения приведены ниже.
|
||||
Прочитать [proposal](proposal.md), затем нужное решение [design](design.md).
|
||||
Здесь единственный backlog инициативы, отдельного roadmap нет.
|
||||
|
||||
## Дорожная карта и зависимости
|
||||
|
||||
```text
|
||||
1.1 AppShell owner ────────┐
|
||||
1.2 import enforcement ────┴─ 2.1 tokens/workspaces ─ 2.2 ui theme
|
||||
│
|
||||
3.1 common states
|
||||
│
|
||||
3.2 EntryCard + pilot ─ 3.3 roles
|
||||
2.1 ─ 4.1 icons ─ 4.2 Card/Cards consumers
|
||||
2.2 ─ 5.1 Modal review
|
||||
1.2 ─ 5.2 operation vocabulary ─ 5.4 form boundary
|
||||
1.2 ─ 5.3 income period helper boundary
|
||||
|
||||
3.3 + 4.2 + packed consumer proof ─ 7.1 retire facades
|
||||
Выполненные локальные 1–5 ─ 7.2 текущее as-built описание
|
||||
3.2–3.3 + 5.1–5.4 + 7.1–7.2 ─ 7.3 acceptance всей инициативы
|
||||
```
|
||||
|
||||
1.1 и 1.2 независимы по смыслу, но могут менять общие конфиги: параллельные PR
|
||||
согласуют diff. 5.1–5.4 не блокируют выпуск основы и не входят скрыто в пилот.
|
||||
Иконки не нужны read-only пилоту RecentEvents. Пункты внешней публикации удалены из текущего плана по решению пользователя:
|
||||
пакеты остаются приватными workspaces frontend. Остальные
|
||||
задачи используют предложенные defaults после отдельного запроса реализации.
|
||||
|
||||
### Общие условия каждой будущей сессии
|
||||
|
||||
- Работать в repo владельца, сначала его AGENTS и только triggered conventions;
|
||||
проверить Git status, текущий HEAD и чужие изменения. План привязан к
|
||||
исследованным ревизиям, не к обещанию актуального remote develop.
|
||||
- Перед Node-командой активировать местную `.nvmrc`: `nvm use --silent`.
|
||||
Для code/dependency PR frontend требует `npm ci` и итоговый `npm run verify`;
|
||||
targeted команды ниже дополняют этот gate, не заменяют его.
|
||||
- Scope PR — одна задача. Не смешивать перемещение с новым поведением,
|
||||
обновлением версий библиотек и исправлением соседнего продукта.
|
||||
- Значимый тест начинается с наблюдаемого результата/риска; сохранять имеющиеся
|
||||
regression tests. Не добавлять тест wrapper existence, Mantine internals
|
||||
или snapshots всех вариантов ради переноса.
|
||||
- По завершении повторить routing, проверить diff/новые файлы, Boy Scout review,
|
||||
`git diff --check`, записать реально выполненные команды и ограничения.
|
||||
Непройденная проверка не отмечается как выполненная задача.
|
||||
|
||||
### Реальные команды и будущие проверки
|
||||
|
||||
Сейчас доступны: `npm run deps`, `npm run deps:storybook`, `npm run knip`,
|
||||
`npm run lint`, `npm run typecheck`, `npm run openapi:check`,
|
||||
`npm run test:run -- <существующий path>`, `npm run test:coverage`,
|
||||
`npm run build`, `npm run build:catalog`, `npm run verify`,
|
||||
`npm run release:preview`. Их поведение исследовано, но они **не запускались**
|
||||
в текущей Markdown-сессии. `typecheck` может записать tsbuildinfo;
|
||||
tests/builds пишут cache/coverage/dist/catalog. `openapi:generate` меняет
|
||||
tracked declarations и не нужен этой миграции.
|
||||
|
||||
Package build/declarations/check scopes и packed consumer проверены.
|
||||
Независимый package release не входит в текущий план. Не
|
||||
считать вымышленный `test:packages` или `release:packages` действующей командой.
|
||||
Native `npm pack --dry-run`, `npm pack`, `npm ls` использованы для проверки пакетов. `release:prepare` приложения
|
||||
создаёт commit; не использовать для пробного package release.
|
||||
|
||||
## 1. Уточнить владельцев и существующие ограничения
|
||||
|
||||
- [x] 1.1 [frontend] Перенести route-aware AppShell к владельцу приложения.
|
||||
- **Covers:** `N/A` — техническое исправление F3; product shell не должен стать публичной частью ui, согласно design §1/4.
|
||||
- **Verification:** `npm run deps`, `npm run typecheck`, `npm run knip`, существующие route/navigation tests, итоговый `npm run verify`; browser navigation/focus и active route.
|
||||
- **Читать / область:** `.ai/architecture.md`, UI, `src/app/ui/AppShell.tsx` и CSS (до переноса — shared/ui), его callers в `app/routes`, связанные auth/route tests. Найти все imports до переноса.
|
||||
- **Изменить / готово:** AppShell и принадлежащие ему navigation styles находятся в `app/ui` с допустимым public import. Labels, links, Outlet, transitions, responsive shell прежние; shared/ui не знает product routes. Коротко уточнён legacy пункт architecture.
|
||||
- **Не входит / сохранить:** Новая навигация, новый wrapper shell, миграция всех SVG, auth policy. Никаких изменений URL и bootstrap states.
|
||||
- **Откат:** Вернуть перенос и imports одним PR; данных/внешних artifacts нет. Зависимость: нет.
|
||||
|
||||
- [x] 1.2 [frontend] Закрыть same-layer imports действующим dependency-cruiser.
|
||||
- **Covers:** `N/A` — enforcement уже принятого FSD profile, F4; не новая пользовательская возможность.
|
||||
- **Verification:** Зафиксировать вывод существующего `npm run deps` до правки; после неё тот же gate отклоняет временный контролируемый forbidden import между двумя slices, чистый graph проходит; удалить пробный import, затем `npm run verify`.
|
||||
- **Читать / область:** Architecture/imports, `dependency-cruiser.cjs`, реальные alias/relative imports в pages/features/entities; public API примеры account-operations и bank-card.
|
||||
- **Изменить / готово:** Точные запреты соседних slices pages/features/entities, без запрета imports внутри одного slice и без ошибочного применения к shared segments. Если baseline выявит legacy, правило включается для чистой области с адресным исключением и условием удаления, без broad ignore.
|
||||
- **Не входит / сохранить:** Новый analyzer, автоматический fixer, массовая раскладка FSD, запрет page-local composition. Не писать постоянный анализатор проверки анализатора.
|
||||
- **Откат:** Вернуть только rule change, обязательный semantic review остаётся. Зависимость: нет.
|
||||
|
||||
## 2. Подготовить пакеты без изменения представления
|
||||
|
||||
- [x] 2.1 [frontend] Ввести workspace tokens и охват его контрактов.
|
||||
- **Covers:** `frontend-design-system` — `Общий фундамент доступен через проверяемые локальные пакеты`
|
||||
- **Verification:** Будущая package-конфигурация: `npm pack --dry-run` показывает JSON; чистый временный consumer вне workspace читает JSON обычным parser; `npm ci`, расширенные существующие type/lint/Knip/deps scopes, `npm run verify`; чистые Docker builds development/production с новым workspace manifest и JSON.
|
||||
- **Читать / область:** Engineering/dependencies, package/lock, TS/Knip/deps configs, `Dockerfile`, `.dockerignore`, `packages/tokens/tokens.json`, `shared/theme/theme.ts`, `theme.test.ts`; design §1–3/10. После 1.1–1.2; имена остаются предлагаемыми до принятия design.
|
||||
- **Изменить / готово:** `packages/tokens` владеет тем же JSON v1; root app private; один npm workspace lock, прямые зависимости, ограниченные files/exports. Адаптер читает package JSON. Проверки явно видят packages и запрещают package → app. Docker получает workspace manifests перед npm ci и только нужные package inputs через узкую allowlist, без host node_modules/dist/.env.
|
||||
- **Не входит / сохранить:** Новая schema, Style Dictionary, mobile/dark, преобразование всех токенов и CSS. Не поддерживать две редактируемые копии JSON; app appearance и все units прежние.
|
||||
- **Откат:** Вернуть JSON/imports/manifest/lock как связанный diff; package ещё не опубликован.
|
||||
|
||||
- [x] 2.2 [frontend] Упаковать Mantine adapter и общие стили в ui.
|
||||
- **Covers:** `frontend-design-system` — `Общий фундамент доступен через проверяемые локальные пакеты`
|
||||
- **Verification:** Существующие theme tests на новом owner; будущие Vite library build + declaration emit и packed consumer type/build/render без app alias; на чистом checkout после `npm ci`, без прежнего package dist/cache, `npm run verify` сначала собирает packages, затем проверяет consumer. `npm ls react react-dom @mantine/core`; отдельные чистые Docker development/production builds и render темы.
|
||||
- **Читать / область:** `packages/ui/src/{theme.ts,styles.css,theme.test.ts}`, facade `shared/theme/index.ts`, `app/ui/App.tsx`, `.storybook/{main.ts,preview.tsx,dependency-cruiser.cjs}`, `vite.config.ts`, `vitest.config.ts`, package scripts, `Dockerfile`, `.dockerignore`, design §2–4. Зависимость: 2.1.
|
||||
- **Изменить / готово:** `ui/theme`/`ui/styles.css`, dependency tokens, peers/external React/Mantine, CSS side effects, JS/d.ts/CSS в package. App/preview явно подключают styles и прежние providers. Package build предшествует всем проверкам потребителя в local/CI/Docker; scope tests/coverage следует owner. `shared/theme` только re-export. Host dev допускает package watch; в Docker изменение packages требует документированного rebuild dev image, без нового root orchestration.
|
||||
- **Не входит / сохранить:** Новый global provider, новый Storybook app, component wrappers, Modal animation cleanup. Library build не наследует app PWA/service-worker/proxy plugins. Не менять light scheme, source values, CSS order и effective theme; сравнить фактический bundle size с baseline, не заявляя отсутствующий budget gate F12.
|
||||
- **Откат:** Вернуть adapter/styles/imports и manifest/lock единым PR. Временный facade удаляется в 7.1, новые consumers его не расширяют.
|
||||
|
||||
## 3. Общие компоненты и продуктовый пилот
|
||||
|
||||
- [x] 3.1 [frontend] Перенести StateView и LoadingSkeleton с их stories.
|
||||
- **Covers:** `frontend-design-system` — `Общий фундамент доступен через проверяемые локальные пакеты`
|
||||
- **Verification:** `npm run deps:storybook`, `npm run build:catalog`, существующие проверки StateView/LoadingSkeleton/composeStories в новом scope, будущий packed component render, `npm run verify`.
|
||||
- **Читать / область:** Три UI-conventions темы, два `src/shared/ui` компонента/stories и callers, `src/test/storybook.test.tsx`, package ui. Зависимость: 2.2.
|
||||
- **Изменить / готово:** Реализации и CSF stories у ui, один catalog glob включает package stories. Props без query/i18n/router; busy label/status и error alert/action сохраняются. Проверка Storybook reachability включает новый каталог. Если нужен facade, он только переэкспортирует.
|
||||
- **Не входит / сохранить:** Перемещение page skeleton shapes, новый loading framework, полный набор stories для Mantine. No backend и реальные финансовые данные.
|
||||
- **Откат:** Вернуть перенос; содержимое/поведение исходных components не менялось. Удаление facade — 7.1.
|
||||
|
||||
- [x] 3.2 [frontend] Перенести EntryCard и подтвердить пилот RecentEvents.
|
||||
- **Статус 2026-09-22:** Реализация, 278 tests/full verify, Docker, packed consumer и browser desktop/375px прошли. Пользователь подтвердил успешную ручную проверку coarse pointer/reduced motion по предложенному чек-листу; browser-ограничение закрыто. CSS перенесён побайтово.
|
||||
- **Covers:** `frontend-design-system` — `Общий фундамент доступен через проверяемые локальные пакеты`
|
||||
- **Verification:** `npm run test:run -- src/pages/account/ui/AccountPage.test.tsx`, существующие ledger/CardPage cases использующих EntryCard; минимальный UI-test собственного image fallback при необходимости; `npm run deps:storybook`, `npm run build:catalog`, packed consumer render, `npm run verify`; browser сравнение 375px/desktop.
|
||||
- **Читать / область:** `EntryCard.tsx`/CSS и все callers; `AccountPage.vm.ts::toRecentEvents`, `useBrokerageEvents`, `BrokerageEventsPreview`, `BrokerageEventCard` и их stories, design UI/UX scope. Зависимость: 3.1.
|
||||
- **Изменить / готово:** Один EntryCard в ui с тем же CSS/props; entity пилота импортирует публичный ui package. В Storybook — существующие RecentEvents states и малая generic story длинного контента/image fallback/actions. Пилот реально проходит через API owner до прежнего presentation, без смены data flow. Остальные callers могут пока использовать re-export.
|
||||
- **Не входит / сохранить:** Generic icons, PositionCard rewrite, исправление F8. Сохраняются unknown≠zero, currency/date/account, logo fallback, preview limit/full-list link; у других callers — sign и disabled placeholder/archive guards.
|
||||
- **Откат:** Вернуть consumer import и extraction PR. Не вводить вторую реализацию EntryCard для пилота. Facade removal — 7.1.
|
||||
|
||||
- [x] 3.3 [frontend] Подключить существующие semantic roles внутри EntryCard.
|
||||
- **Статус 2026-09-22:** Реализованы border/subtle/surface. Positive/negative уже были semantic (shade 9); neutral gray-7 оставлен без неточного сопоставления. npm ci/full verify (278 tests) и browser computed colors/narrow/focus прошли. Пользователь подтвердил ручную проверку coarse pointer/reduced motion по чек-листу; пункт закрыт.
|
||||
- **Covers:** `N/A` — F1: применение уже существующей темы после структурного переноса, без нового UI behavior.
|
||||
- **Verification:** Сравнить computed colors и выбранные EntryCard/RecentEvents states до/после; gray-3→border, gray-0→subtle эквивалентны; текущие positive/negative (shade 9) сохранены; background tint/white→surface проверен; `npm run verify` и browser narrow/focus/coarse-pointer/reduced-motion.
|
||||
- **Читать / область:** ui EntryCard/CSS, tokens color.roles, ui/theme resolver, generic и product stories. Зависимость: 3.2.
|
||||
- **Изменить / готово:** Прямые эквиваленты заменены semantic CSS variables; текущий вид и actions не меняются. Если эквивалентность конкретной пары не доказана, оставить её локальной и пояснить, не создавать токен автоматически.
|
||||
- **Не входит / сохранить:** Новые palettes, card brand gradients, компонентный токен на каждое свойство, массовый CSS sweep.
|
||||
- **Откат:** Вернуть только CSS/inline-role diff; package ownership остаётся.
|
||||
|
||||
## 4. Собственные общие иконки
|
||||
|
||||
- [x] 4.1 [frontend] Подготовить минимальный icons package.
|
||||
- **Covers:** `frontend-design-system` — `Собственные общие иконки имеют доступный контракт`; `frontend-design-system` — `Общий фундамент доступен через проверяемые локальные пакеты`
|
||||
- **Verification:** Будущие package build/declarations/pack consumer checks; synthetic decorative и meaningful icon examples с именем/размером/currentColor; `npm ls react`, `npm run deps:storybook`, `npm run verify`.
|
||||
- **Читать / область:** Card/Cards inline plus/pencil/trash, `BankOperationIcon` как пример accessibility, `bind-icon-animation` только для границ ответственности, design §5. Зависимость: 2.1; после 2.2 можно переиспользовать package build pattern без общего самописного генератора.
|
||||
- **Изменить / готово:** Именованные Add/Edit/Delete SVG-компоненты, один TSX source на рисунок, React peer/external, public types, ограниченные exports. Static package не тянет motion/UI/domain; декоративность по умолчанию и доступное meaningful использование документированы.
|
||||
- **Не входит / сохранить:** SVG registry по строке, raw SVG+TSX дубли, SVGR/dependency, перенос категорий/навигационных анимаций. Сохранить geometry/stroke/size существующих рисунков, без редизайна.
|
||||
- **Откат:** Удалить ещё не используемый package diff; до публикации внешнего контракта нет. Если 4.2 уже интегрирован, откатывать согласованно.
|
||||
|
||||
- [x] 4.2 [frontend] Перевести только повторяющиеся Card/Cards actions на icons.
|
||||
- **Covers:** `frontend-design-system` — `Собственные общие иконки имеют доступный контракт`
|
||||
- **Verification:** `npm run test:run -- src/pages/card/ui/CardPage.test.tsx`, `npm run test:run -- src/pages/cards/ui/CardsPage.test.tsx`, `npm run verify`; browser accessible names/keyboard и appearance выбранных Add/Edit/Delete actions.
|
||||
- **Читать / область:** `pages/card/ui/CardPage.view.tsx`, `pages/cards/ui/CardsPage.view.tsx`, ActionIcon consumers и imports. Зависимость: 4.1.
|
||||
- **Изменить / готово:** Повторяющиеся SVG заменены named imports; размеры/strokeWidth задаются явно, если раньше различались. Имя и disabled остаются на action; внутри SVG нет дополнительного focus. В изменённом scope больше нет старых копий этих рисунков.
|
||||
- **Не входит / сохранить:** BankOperationIcon mappings, формы/mutations, поведение edit/delete и confirm dialogs, иной визуальный стиль.
|
||||
- **Откат:** Вернуть caller diff; пакет может оставаться неиспользуемым до отдельного решения, опубликованную версию не удалять.
|
||||
|
||||
## 5. Адресные улучшения после основы
|
||||
|
||||
Эти задачи самостоятельны. Их незавершённость не оправдывает расширение
|
||||
пакетного PR или утверждение, что изменено поведение формы в пилоте.
|
||||
|
||||
- [x] 5.1 [frontend] Проверить и при необходимости свести Modal animation к одному владельцу.
|
||||
- **Статус 2026-09-22:** BankCardForm browser A/B показал различный lifecycle: CSS даёт mount entrance, Mantine — exit/callback. Production-код сохранён; причины документированы в UI convention. Пользователь подтвердил ручную проверку reduced motion, Escape/Отмена и возврата фокуса; пункт закрыт.
|
||||
- **Covers:** `N/A` — F5, устранение подтверждённого дублирования механизмов без нового продукта.
|
||||
- **Verification:** Browser comparison открытия/закрытия существующей банковской Modal: overlay, motion, focus return, reduced motion; relevant Modal/form tests и `npm run verify` только при code diff.
|
||||
- **Читать / область:** ui theme Modal defaults, ui global styles, BankCardForm/OperationForm consumers. Зависимость: 2.2.
|
||||
- **Изменить / готово:** Выбран один механизм либо документирован конкретный различный смысл обоих. При эквивалентности предпочтён Mantine transition и убран только лишний CSS. Наблюдение «видимых проблем нет» само по себе не требует нового кода.
|
||||
- **Не входит / сохранить:** Новые timings, анимационная система, замена motion маршрутов. Keyboard/focus/closing rules неизменны.
|
||||
- **Откат:** Вернуть animation-only diff; component API/data не меняются.
|
||||
|
||||
- [x] 5.2 [frontend] Свести runtime vocabulary банковских operation kinds у entity.
|
||||
- **Covers:** `N/A` — часть F6, одна типизированная коллекция для существующих schema/choices без изменения wire contract.
|
||||
- **Verification:** `npm run typecheck`, `npm run test:run -- src/pages/card/ui/OperationForm.test.tsx`, `npm run deps`, `npm run verify`; все четыре прежних вида и defaults сохранены.
|
||||
- **Читать / область:** `entities/bank-card/api/queries.ts` и index, `OperationForm.tsx`/`.view.tsx`/`.types.ts`, TypeScript/data conventions. Зависимость: 1.2.
|
||||
- **Изменить / готово:** Schema и choices используют один `as const` набор, проверенный относительно generated `BankOperation['kind']`. Не добавлен enum, DTO copy или cast неизвестного code; строки UI остаются i18n.
|
||||
- **Не входит / сохранить:** Generic errors registry, backend enum generation, механическое именование каждого literal, controller refactor.
|
||||
- **Откат:** Вернуть маленький vocabulary/import diff; значения wire прежние.
|
||||
|
||||
- [x] 5.3 [frontend] Отделить pure period helpers от AccountIncomePage VM.
|
||||
- **Covers:** `N/A` — F7, устранение транзитивной зависимости presentation story от VM по design §6/10.
|
||||
- **Verification:** Existing account-income targeted tests, `npm run deps:storybook`, `npm run build:catalog`, `npm run verify`; synthetic form submit/reset/error states без API/query providers.
|
||||
- **Читать / область:** `AccountIncomePage.vm.ts`, `components/IncomePeriodForm.view.tsx`, их imports/tests, соседний page model и Storybook convention. Зависимость: 1.2.
|
||||
- **Изменить / готово:** Только реально используемые pure date helpers у page model и оба callers используют их; полезная isolated presentation story проходит reachability. Нового global date helper/service нет.
|
||||
- **Не входит / сохранить:** Общий DateRangePicker, изменение диапазонов/часового пояса и перенос логики в UI package. Moscow dates, validation и submit/reset прежние.
|
||||
- **Откат:** Вернуть helper move/story diff; URL/API поведение не менялось.
|
||||
|
||||
- [x] 5.4 [frontend] Отделить controller банковской OperationForm от presentation.
|
||||
- **Covers:** `N/A` — часть F6, применение существующей container/VM/view границы без изменения денежных сценариев.
|
||||
- **Verification:** До и после `npm run test:run -- src/pages/card/ui/OperationForm.test.tsx`; особенно conflict/draft/explicit version adoption, retained UUID, full refund и max money; `npm run deps:storybook`, затем `npm run verify`.
|
||||
- **Читать / область:** Полные OperationForm/OperationForm.view/types/tests, entity form-validation/mutations и UI/data/testing conventions. Зависимость: 5.2.
|
||||
- **Изменить / готово:** Query/mutation/recovery orchestration принадлежит page VM/controller; существующий fields view расширен только нужными presentation props/callbacks/slots. Runtime helpers сейчас приходят из banking barrel, который переэкспортирует API/hooks: эту транзитивную связь убрать через props/callbacks, type-only DTO imports допустимы. Не вводить deep-import exception и не ослаблять story gate. RHF context в fields остаётся; `CardPage` целиком не переписывается.
|
||||
- **Не входит / сохранить:** Generic form engine, extraction в feature/package без второго consumer, новые requests/optimistic updates. Не менять amount string/BigInt, intent lifecycle, version adoption, source constraints, pending close guards и вложенное создание категории.
|
||||
- **Откат:** Вернуть этот behavior-preserving PR. Любое необходимое изменение поведения остановить и согласовать отдельно, не прятать в refactor.
|
||||
|
||||
## 7. Закончить переход и описать поставленное состояние
|
||||
|
||||
- [x] 7.1 [frontend] Удалить только исчерпанные compatibility facades.
|
||||
- **Уточнение scope:** Пользователь разрешил удалить локальные facades с проверкой packed consumer вместо registry consumer. Nexus и независимый release остаются отложенными.
|
||||
- **Covers:** `N/A` — прекращение временного двойного import path после подтверждённого потребления, design Migration Plan.
|
||||
- **Verification:** `rg` по runtime/test/story imports старых theme/UI paths даёт ноль; `npm run knip`, `npm run deps`, `npm run deps:storybook`, app/catalog/packed consumer checks и `npm run verify`.
|
||||
- **Читать / область:** Facades `shared/theme` и EntryCard/StateView/LoadingSkeleton, все оставшиеся callers, component source catalog, frontend README и conventions. Зависимости: 3.3, 4.2 и подтверждённый packed consumer без workspace/source aliases.
|
||||
- **Изменить / готово:** Оставшиеся consumers используют package API, ненужные re-exports удалены, нет дубля JSON/CSS/implementation. В existing conventions закреплены каталог и import rules, AGENTS только маршрутизирует темы.
|
||||
- **Не входит / сохранить:** Массовая чистка unrelated shared/lib, запрет прямого Mantine, перенос domain UI. Старые подходы вне migrated scope не блокируются новым широким правилом.
|
||||
- **Откат:** Вернуть thin facades/imports; они не восстанавливают копии реализаций. Условия удаления снова проверяются перед повтором.
|
||||
|
||||
- [x] 7.2 [docs] Обновить только подтверждённое as-built описание.
|
||||
- **Уточнение scope 2026-09-22:** По запросу следующего пункта без browser verification описано текущее локальное состояние после 5.4. Завершение 7.1 не требуется для этого описания: переходное состояние и отсутствие registry-поставки указаны явно; после 7.1 описание facades актуализировано. После будущей поставки документация обновляется вместе с ней.
|
||||
- **Covers:** `N/A` — описание фактически принятой реализации и поставки; не новый behavior contract.
|
||||
- **Verification:** Docs `npm run verify` по местному CONTRIBUTING, проверка локальных ссылок/диаграмм и semantic review по поставленному frontend; `git diff --check`.
|
||||
- **Читать / область:** Docs AGENTS/README/CONTRIBUTING, `design/overview.md`, `architecture/containers.md`, при необходимости release boundary в `architecture/deployment.md`; frontend принятый package contract. Основание текущего описания: выполненные 1–5; удаление facades по 7.1 отражено в документации.
|
||||
- **Изменить / готово:** Тематические страницы говорят о реально используемой теме/пакетах/границах frontend и каталога. Указывается, что raw SVG/mobile/dark/API package не поставлены. При неполной 5.x не обещать завершение этих пунктов.
|
||||
- **Не входит / сохранить:** Анализ/план в permanent docs, новый roadmap, переописание backend, ADR на каждый маленький выбор. Один устойчивый ADR возможен лишь если принято значимое repository/release решение и нужен его rationale.
|
||||
- **Откат:** Вернуть описание вместе с отменённой поставкой; не менять исторические archives.
|
||||
|
||||
- [x] 7.3 [specs] Сверить реализацию с delta и закрыть плановые расхождения.
|
||||
- **Статус 2026-09-22:** Semantic сверка завершена для согласованного локального объёма: proposal/design/delta согласованы с private workspaces и packed consumer; внешняя публикация исключена. Код и ручные browser checks проверены ранее. Specs verify, локальные ссылки и whitespace проверены после правок. После установки OpenSpec выполнена команда `openspec validate evolve-frontend-stack --type change --strict --store wealth-ledger-specs`: change valid. Пункт завершён.
|
||||
- **Covers:** `frontend-design-system` — `Общий фундамент доступен через проверяемые локальные пакеты`; `frontend-design-system` — `Собственные общие иконки имеют доступный контракт`
|
||||
- **Verification:** Semantic проверка всех delta scenarios, `npm run verify` specs, при доступном CLI `openspec validate evolve-frontend-stack --type change --strict --store wealth-ledger-specs`; локальные ссылки и `git diff --check`.
|
||||
- **Читать / область:** Specs AGENTS/README, proposal/delta/design/tasks и фактические результаты consumer/rollback/accessibility checks. Зависимости полного acceptance: 3.2–3.3, 5.1–5.4 и 7.1–7.2; требования delta должны соответствовать согласованному локальному объёму.
|
||||
- **Изменить / готово:** Tasks отражают только фактически проверенные результаты; согласованные изменения scope возвращены в planning artifacts, не скрыты. Main specs обновляются только в отдельно разрешённом штатном завершении после реального внедрения; untouched deferred findings остаются явно отложенными.
|
||||
- **Не входит / сохранить:** Автоматический archive/approval, Evidence/state/hash registry, декларация успеха на основании одного build. Промежуточная сверка не означает завершения change.
|
||||
- **Откат:** Исправить несоответствующее предложение/отметку; main specs не описывают ещё не реализованный переход.
|
||||
|
||||
## Переходный период и отложенные вопросы
|
||||
|
||||
Точный перечень отложенного — в design: F8 recovery RecentEvents, F9 backend
|
||||
errors contract, F12 расхождение bundle-budget spec/gate, общий investment recovery classifier и новые потребители.
|
||||
Они не входят скрыто в tasks выше. Если требуется менять HTTP/observable
|
||||
recovery, нужен отдельный согласованный scope и соответствующий spec contract.
|
||||
|
||||
Facades допустимы только от 2.2/3.x до 7.1; новых возможностей они не получают.
|
||||
Новые components/imports следуют целевому каталогу. Старые inline рисунки
|
||||
допустимы лишь до миграции своего caller batch, а новые дубли уже вынесенных
|
||||
рисунков не создаются. Совместимость снимается по нулю imports и успешному
|
||||
consumer proof, а не по истечении произвольного срока.
|
||||
|
||||
Проверены задачи **1.1–1.2, 2.1–2.2, 3.1–3.3, 4.1–4.2, 5.1–5.4 и 7.1–7.3**.
|
||||
Недостающие browser checks 3.2/3.3/5.1 выполнены вручную пользователем:
|
||||
он подтвердил корректность всех пунктов переданного чек-листа.
|
||||
Независимые версии и Nexus отложены до оценки пользы после пилота;
|
||||
checkbox не разрешает дальнейшую реализацию или публикацию.
|
||||
|
||||
Последний полный frontend `npm run verify`: 49 test files / 282 tests,
|
||||
проверки зависимостей, типов, lint, Knip, OpenAPI и сборки app/catalog прошли.
|
||||
Свежий UI tarball проверен вне workspace: install, typecheck, build и browser render.
|
||||
Docs `npm run verify`: 45 Markdown-файлов, 0 issues.
|
||||
Reference in New Issue
Block a user