spec: complete local frontend stack evolution
Specs security / security (pull_request) Successful in 7s
Specs verify / verify (pull_request) Successful in 11s
Conventional commits / commits (pull_request) Successful in 11s
Specs security / security (push) Successful in 7s
Specs verify / verify (push) Successful in 9s
Specs security / security (pull_request) Successful in 7s
Specs verify / verify (pull_request) Successful in 11s
Conventional commits / commits (pull_request) Successful in 11s
Specs security / security (push) Successful in 7s
Specs verify / verify (push) Successful in 9s
OpenSpec change: evolve-frontend-stack
This commit was merged in pull request #15.
This commit is contained in:
@@ -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