Files
ksv741 329d66e767
Specs security / security (push) Successful in 8s
Specs verify / verify (push) Successful in 11s
spec: finalize wealth-ledger SDD migration
2026-10-09 21:14:22 +03:00

43 KiB
Raw Permalink Blame History

Context

Локальная архитектура реализована; независимая публикация отложена. Baseline исследования — frontend 3c99deb, версия 0.3.0, 2026-09-20. Требования — в proposal и delta.

В приложении уже работают 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.

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, не конечная цель

Направление стрелки — «потребляет»; циклов нет:

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 уже есть переносимые значения и описания. Не менять формат 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 защищают именно преобразования и ссылки, не каждое значение 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.

Назначение Текущий источник Целевой источник Правило применения Этап
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.

Во время перехода 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 уже реализованы, независимые версии остаются отложенными.