docs(specs): archive frontend view model boundary change
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
schema: wealth-ledger-sdd
|
||||||
|
created: 2026-08-25
|
||||||
|
goal: Codify and restore the frontend ViewModel/View boundary without changing user-visible behavior.
|
||||||
|
skip_specs: true
|
||||||
|
affected_areas:
|
||||||
|
- frontend
|
||||||
|
- specs
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
# codify-frontend-view-model-boundary — Design
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Frontend уже использует FSD-направление импортов, typed API hooks и page pattern
|
||||||
|
`container + ViewModel + view` на части finance pages. Однако текущий
|
||||||
|
`AccountPage` показывает противоречивый пример: container вызывает
|
||||||
|
`useAccountPageViewModel`, но `AccountPage.view.tsx` дополнительно вызывает
|
||||||
|
server-state hooks для recent Account Ledger и Future Cash Events, группирует
|
||||||
|
Portfolio Positions по типам, считает display-only доли и содержит много
|
||||||
|
самостоятельных presentation sections в одном файле.
|
||||||
|
|
||||||
|
Reference template фиксирует другую семантику: `*.tsx` без суффикса — container
|
||||||
|
или public component, `*.vm.ts` — hook, который инкапсулирует данные, действия и
|
||||||
|
state mapping, а `*.view.tsx` — чистое представление. В текущем frontend docs
|
||||||
|
эта граница описана короче и не проговаривает отрицательные правила, поэтому
|
||||||
|
AI-agent может принять локальный god-view за допустимый pattern.
|
||||||
|
|
||||||
|
Ограничения frontend: React/Vite, TanStack Query, Mantine, React Router,
|
||||||
|
i18n через `useTranslation`, FSD public API checks, canonical gate
|
||||||
|
`npm ci && npm run verify` под Node 22. Change не вводит новый automatic
|
||||||
|
guardrail: enforcement остаётся docs/review guidance плюс исправленный локальный
|
||||||
|
пример и tests.
|
||||||
|
|
||||||
|
## Goals / Non-Goals
|
||||||
|
|
||||||
|
**Goals:**
|
||||||
|
|
||||||
|
- Восстановить `AccountPage` как корректный пример page container,
|
||||||
|
ViewModel и маленьких presentation views.
|
||||||
|
- Перенести recent data loading, state selection, Portfolio Position grouping,
|
||||||
|
derived display flags/numbers и callbacks из view layer в ViewModel/container
|
||||||
|
layer.
|
||||||
|
- Раздробить account page presentation на именованные соседние components,
|
||||||
|
когда section/state имеет самостоятельный смысл.
|
||||||
|
- Уточнить frontend-local docs и `frontend/AGENTS.md`, чтобы будущие AI agents
|
||||||
|
видели явную границу container/ViewModel/view.
|
||||||
|
- Покрыть VM-derived presentation data focused tests и сохранить existing
|
||||||
|
render tests как regression net пользовательского поведения.
|
||||||
|
|
||||||
|
**Non-Goals:**
|
||||||
|
|
||||||
|
- Automatic lint, dependency-cruiser или AST guardrail для VM/view boundary.
|
||||||
|
- Нормализация `account-operations`, `account-events`, login, register или
|
||||||
|
settings pages.
|
||||||
|
- Изменение API hooks signatures, auth-gating pattern или централизованного
|
||||||
|
access-token handling.
|
||||||
|
- Изменение backend, HTTP routes, OpenAPI snapshot, generated types, domain
|
||||||
|
docs или product behavior.
|
||||||
|
- Визуальный redesign account page.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
**D1. Сохранить template-семантику ролей файлов.** `AccountPage.tsx` остаётся
|
||||||
|
container: он вызывает `useAccountPageViewModel()` и выбирает top-level state
|
||||||
|
view. `AccountPage.vm.ts` становится owner данных и derived presentation model:
|
||||||
|
portfolio state, recent ledger/events state, refresh/retry callbacks, position
|
||||||
|
sections и display-only calculations. `*.view.tsx` и nested view components
|
||||||
|
получают props и рендерят JSX.
|
||||||
|
|
||||||
|
*Alternative:* сделать `AccountPage.view.tsx` единственным component, который
|
||||||
|
вызывает VM hook. Отклонено: это переворачивает роль `*.view.tsx` относительно
|
||||||
|
reference template и текущих conventions.
|
||||||
|
|
||||||
|
**D2. View modules остаются render-only, но не hook-free.** Presentation views
|
||||||
|
могут использовать `useTranslation`, form-context hooks для form views и
|
||||||
|
локальный UI-only state, например image fallback state. Они не вызывают
|
||||||
|
server-state/API hooks, auth hooks, route/navigation hooks или VM hooks, не
|
||||||
|
делают domain grouping и не считают derived presentation values из collection
|
||||||
|
data. Простое форматирование одного переданного значения через существующие
|
||||||
|
formatters остаётся presentation concern.
|
||||||
|
|
||||||
|
*Alternative:* запретить все hooks во view. Отклонено: это вынудит переносить
|
||||||
|
i18n labels и локальный UI fallback state в VM, делая VM слишком dependent от
|
||||||
|
деталей rendering.
|
||||||
|
|
||||||
|
**D3. VM отдаёт presentation model, а не только raw domain data.** ViewModel
|
||||||
|
возвращает данные, уже разделённые на account page sections, вместе с flags,
|
||||||
|
share denominator/result values и recent sections states. View остаётся
|
||||||
|
ответственной за layout, labels, Mantine components, links и final rendering.
|
||||||
|
Это оставляет вычисления тестируемыми без DOM, но не превращает VM в generator
|
||||||
|
готовой разметки или локализованных strings.
|
||||||
|
|
||||||
|
**D4. Дробить view по смысловым границам.** Account page presentation делится на
|
||||||
|
nearby components для heading/refresh state, totals/cash, position sections,
|
||||||
|
position card/logo и recent sections. Критерий split — самостоятельная
|
||||||
|
ответственность и имя, а не только число строк. Если section может быть названа
|
||||||
|
и протестирована/прочитана независимо, она не должна накапливаться внутри
|
||||||
|
одного большого view file.
|
||||||
|
|
||||||
|
**D5. Docs first, automated enforcement later.** Этот change уточняет
|
||||||
|
`frontend/docs/UI-PATTERN.md`, `frontend/docs/CONVENTIONS.md` и короткий routing
|
||||||
|
pointer в `frontend/AGENTS.md`. Hard checker не добавляется, потому что сейчас
|
||||||
|
нет утверждённого design для надёжного AST rule, исключений и maintenance cost.
|
||||||
|
Rule остаётся review guidance; corrected AccountPage и tests уменьшают риск
|
||||||
|
повтора.
|
||||||
|
|
||||||
|
**D6. Tests фиксируют новую поверхность ответственности.** Новые focused tests
|
||||||
|
проверяют ViewModel-derived presentation data: секции позиций, display-only
|
||||||
|
доли, recent ledger/events state и retry/loading/error propagation. Existing
|
||||||
|
render tests сохраняют observable account page behavior, включая stale snapshot,
|
||||||
|
nullable values, logo fallback, recent failure isolation и cached portfolio
|
||||||
|
visibility.
|
||||||
|
|
||||||
|
## Delivery Map
|
||||||
|
|
||||||
|
| Area | Status | Architectural outcome or N/A reason |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| frontend | `affected` | `AccountPage` возвращается к container/ViewModel/view boundary; account page views дробятся по смысловым presentation components; frontend-local docs и `AGENTS.md` фиксируют guidance; focused VM tests добавляются к existing render regressions. |
|
||||||
|
| backend | `N/A` | Backend behavior, routes, DTOs, T-Bank integration и OpenAPI runtime не меняются. |
|
||||||
|
| specs | `affected` | Этот SDD change хранит approved Proposal, skipped Delta Specs, Design и Tasks для behavior-preserving frontend architecture hardening. |
|
||||||
|
| docs | `N/A` | Отдельный as-built docs repository не меняется: product capability и documented system behavior не меняются; frontend-local conventions живут в frontend repo. |
|
||||||
|
|
||||||
|
### Contract Gate Decision
|
||||||
|
|
||||||
|
| Gate | Status | Reason |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| runtime-openapi | `N/A` | Change не затрагивает backend и не меняет frontend/backend API contract, generated client или OpenAPI snapshot. |
|
||||||
|
|
||||||
|
### Solution Assessment
|
||||||
|
|
||||||
|
Формальная build-versus-buy assessment не triggered. Change не вводит и не
|
||||||
|
заменяет auth, security, storage, external integration, observability, caching,
|
||||||
|
concurrency или infrastructure/tooling. Automatic checker явно оставлен
|
||||||
|
non-goal; docs/review guidance не требует выбора стороннего решения.
|
||||||
|
|
||||||
|
## Risks / Trade-offs
|
||||||
|
|
||||||
|
- **Regression при переносе вычислений.** Перемещение grouping/share/recent
|
||||||
|
state из view в VM может изменить детали отображения. Mitigation: focused VM
|
||||||
|
tests фиксируют derived data, existing render tests фиксируют пользовательски
|
||||||
|
видимые states.
|
||||||
|
- **VM становится слишком presentation-specific.** VM получает display flags и
|
||||||
|
grouped sections, но не локализует text и не собирает JSX. Это удерживает
|
||||||
|
границу между testable preparation и rendering.
|
||||||
|
- **Docs-only guardrail может быть пропущен.** Без automatic checker нарушение
|
||||||
|
возможно. Mitigation: `frontend/AGENTS.md` ведёт AI agents к явной boundary
|
||||||
|
guidance, а largest local account page перестаёт быть плохим примером.
|
||||||
|
- **Слишком мелкое дробление компонентов.** Split по каждому JSX fragment
|
||||||
|
ухудшит навигацию. Mitigation: дробление основано на semantic responsibility
|
||||||
|
и самостоятельном имени section/state, а не на механическом лимите строк.
|
||||||
|
|
||||||
|
## Migration Plan
|
||||||
|
|
||||||
|
1. Добавить focused tests для ViewModel-derived account page presentation data,
|
||||||
|
чтобы зафиксировать переносимую логику до refactor.
|
||||||
|
2. Расширить `AccountPage.vm.ts`: перенести recent queries, position grouping,
|
||||||
|
share calculations, refresh/retry data и recent section states в возвращаемую
|
||||||
|
presentation model.
|
||||||
|
3. Раздробить account page views на nearby presentation components и обновить
|
||||||
|
`AccountPage.view.tsx` так, чтобы view modules получали props и не вызывали
|
||||||
|
data/auth/router/navigation/VM hooks.
|
||||||
|
4. Обновить frontend-local docs и `frontend/AGENTS.md` с explicit
|
||||||
|
container/ViewModel/view boundary и split guidance.
|
||||||
|
5. Запустить targeted account page tests, затем frontend canonical gate
|
||||||
|
`npm ci && npm run verify`; после implementation выполнить semantic
|
||||||
|
verification против Proposal и Design и workspace dispatcher для change.
|
||||||
|
|
||||||
|
Rollback — обычный revert frontend/specs commits; schema, data migration,
|
||||||
|
runtime contract migration и feature flag не вводятся.
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
|
||||||
|
<!-- none -->
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
# codify-frontend-view-model-boundary — Implementation Summary
|
||||||
|
|
||||||
|
## Semantic Verification
|
||||||
|
|
||||||
|
Date: 2026-08-25
|
||||||
|
|
||||||
|
Checked areas:
|
||||||
|
|
||||||
|
- User-visible account page behavior: existing render regressions still pass for
|
||||||
|
loading, error, empty, loaded, stale Portfolio Snapshot, nullable values,
|
||||||
|
signed returns, logo fallback, recent failure isolation and cached portfolio
|
||||||
|
visibility.
|
||||||
|
- VM/View boundary: `AccountPage.vm.ts` now owns Portfolio Position grouping,
|
||||||
|
share/return/logo derived presentation data, recent Account Ledger and Future
|
||||||
|
Cash Events query state, retry props and route targets. `AccountPage.view.tsx`
|
||||||
|
and `components/*.view.tsx` render props only.
|
||||||
|
- Forbidden view dependencies: grep found no `useBrokerageOperations`,
|
||||||
|
`useBrokerageEvents`, `useAuth`, `useParams`, `useNavigate`,
|
||||||
|
`useAccountPageViewModel`, `denominators` or `positions.filter` occurrences
|
||||||
|
in account page view files or presentation components.
|
||||||
|
- Access token boundary: `accessToken` remains only in `AccountPage.vm.ts` and
|
||||||
|
test auth mocks under `src/pages/account/ui`.
|
||||||
|
- API/backend contract: backend files, OpenAPI snapshot, generated client and
|
||||||
|
entity API hook signatures were not changed.
|
||||||
|
- Frontend guidance: `frontend/docs/UI-PATTERN.md`,
|
||||||
|
`frontend/docs/CONVENTIONS.md` and `frontend/AGENTS.md` now describe the
|
||||||
|
container/ViewModel/view boundary and semantic split guidance.
|
||||||
|
- Bundle guardrail: the account lazy route baseline was updated from 21,872 to
|
||||||
|
22,366 bytes after the semantic presentation split. Initial JavaScript payload
|
||||||
|
remains 509,165 bytes and passed the existing budget.
|
||||||
|
|
||||||
|
Observed verification:
|
||||||
|
|
||||||
|
- Initial baseline before edits: `npm run test:run -- src/pages/account/ui/AccountPage.test.tsx` — passed, 1 file / 12 tests.
|
||||||
|
- RED VM tests before implementation: `npm run test:run -- src/pages/account/ui/AccountPage.vm.test.tsx` — failed on missing `positionSections`, `recentOperations` and `recentEvents` presentation state.
|
||||||
|
- Targeted account page verification after implementation: `npm run test:run -- src/pages/account/ui/AccountPage.test.tsx src/pages/account/ui/AccountPage.vm.test.tsx` — passed, 2 files / 15 tests.
|
||||||
|
- Focused frontend checks: `npm run typecheck`, `npm run lint`, `npm run knip` and `npm run deps` — passed.
|
||||||
|
- Frontend canonical gate under Node 22.21.0 with Node 22 first in `PATH`: `npm ci && npm run verify` — passed after bundle baseline update; 18 test files / 64 tests, coverage 83.84% statements / 78.41% branches / 78.36% functions / 84.5% lines, production build and bundle check passed.
|
||||||
|
- OpenSpec structural check: `openspec validate codify-frontend-view-model-boundary --type change --strict --store wealth-ledger-specs` — passed.
|
||||||
|
- Workspace dispatcher under Node 22.21.0 with Node 22 first in `PATH`: `bash specs/scripts/verify-workspace-change.sh codify-frontend-view-model-boundary` — passed; Delivery Map frontend/specs affected and backend/docs N/A verified, main specs 20/20 passed, frontend canonical verification passed.
|
||||||
|
|
||||||
|
Conclusion:
|
||||||
|
|
||||||
|
The implementation matches the approved Proposal and Design as a
|
||||||
|
behavior-preserving frontend architecture hardening change. The account page now
|
||||||
|
provides a corrected local example of the container/ViewModel/view boundary,
|
||||||
|
frontend-local guidance documents that boundary, and no user-visible capability,
|
||||||
|
backend behavior, route, API contract, durable data behavior or non-goal changed.
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
## Why
|
||||||
|
|
||||||
|
Frontend conventions уже называют разделение ViewModel/View, а project template
|
||||||
|
описывает эту границу подробнее. Однако поставленный finance UI сейчас содержит
|
||||||
|
page view, который смешивает рендеринг с server-state hooks, соседней загрузкой
|
||||||
|
данных, доменной группировкой и derived presentation calculations. В результате
|
||||||
|
получается misleading example для будущих AI-assisted changes: агент может
|
||||||
|
следовать крупнейшей локальной странице и всё равно нарушить intended boundary.
|
||||||
|
|
||||||
|
Это нужно исправить сейчас, потому что проблема не сводится к локальной
|
||||||
|
сложности одного файла. Текущий пример ослабляет guidance, которое должно
|
||||||
|
удерживать будущую frontend-работу маленькой, reviewable и testable. Если
|
||||||
|
граница остаётся implicit, та же ошибка может повториться на следующих finance
|
||||||
|
pages даже после ручной очистки текущего файла.
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- Восстановить frontend page architecture так, чтобы data fetching, state
|
||||||
|
selection, domain grouping, derived display flags и callbacks жили в
|
||||||
|
ViewModel или container layer, а view modules оставались сосредоточены на
|
||||||
|
rendering props.
|
||||||
|
- Уточнить frontend-local guidance для AI agents и maintainers, чтобы роли
|
||||||
|
container, ViewModel и view modules были explicit и согласованы с reference
|
||||||
|
template.
|
||||||
|
- Держать view modules маленькими по ответственности: когда section или state
|
||||||
|
имеет отдельный смысл и может быть самостоятельно назван, его нужно выносить
|
||||||
|
в соседний presentation component, а не накапливать внутри одного большого
|
||||||
|
view.
|
||||||
|
- Сохранить текущее user-visible поведение account page, routing, localized
|
||||||
|
text, loading/error/empty/loaded states, cached-snapshot behavior и API
|
||||||
|
contract.
|
||||||
|
- Добавить focused regression coverage для derived presentation data,
|
||||||
|
перенесённых во ViewModel, сохранив existing rendering coverage для видимых
|
||||||
|
состояний страницы.
|
||||||
|
- Non-goal: вводить automatic lint или dependency-cruiser rule для этой границы
|
||||||
|
в данном change.
|
||||||
|
- Non-goal: нормализовать другие account-related pages, которые сейчас
|
||||||
|
используют другие page architecture patterns.
|
||||||
|
- Non-goal: менять HTTP routes, generated OpenAPI types, backend behavior,
|
||||||
|
finance domain terminology, visual design или portfolio calculations за
|
||||||
|
пределами переноса existing display-only derivation в правильный frontend
|
||||||
|
layer.
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
### New Capabilities
|
||||||
|
|
||||||
|
_Нет._
|
||||||
|
|
||||||
|
### Modified Capabilities
|
||||||
|
|
||||||
|
_Нет._
|
||||||
|
|
||||||
|
Это behavior-preserving frontend architecture и documentation hardening change.
|
||||||
|
Он отказывается от Delta Specs через `skip_specs: true`, потому что не меняются
|
||||||
|
user-visible capability, API contract, durable data behavior или product
|
||||||
|
requirement. Любое обнаруженное observable behavior change должно вернуться к
|
||||||
|
Proposal и Delta Specs до Design.
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
Users должны видеть одно и то же поведение account page до и после этого
|
||||||
|
change. Frontend maintainers и AI agents получают более ясное local rule о том,
|
||||||
|
где должна жить page logic, и исправленный account page example, которому можно
|
||||||
|
следовать.
|
||||||
|
|
||||||
|
Affected implementation area — frontend page structure и frontend-local
|
||||||
|
architecture documentation. Specs отслеживает этот SDD lifecycle. Backend и
|
||||||
|
отдельный as-built docs repository не должны меняться.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# codify-frontend-view-model-boundary — Tasks
|
||||||
|
|
||||||
|
## 1. Frontend: зафиксировать VM-derived behavior тестами
|
||||||
|
|
||||||
|
- [x] 1.1 Добавить focused tests для `useAccountPageViewModel` в `frontend/src/pages/account/ui/AccountPage.vm.test.tsx` или расширить существующий colocated account page test, если текущая test setup уже надёжно покрывает hook под `QueryClientProvider`, `MantineProvider` и `MemoryRouter`. Tests должны зафиксировать, что ViewModel возвращает grouped position sections для stocks/bonds/other, display-only share values, refresh/retry props и loaded/empty/error state selection без обращения к DOM-rendering details. Verification: `npm run test:run -- src/pages/account/ui/AccountPage.vm.test.tsx` в `frontend` либо точный account page test file, если tests останутся в существующем файле.
|
||||||
|
- [x] 1.2 Добавить focused tests для recent Account Ledger и Future Cash Events presentation state в ViewModel: loading, error, empty, loaded first five items/events и isolated retry/open-link data должны приходить из VM как props/state для presentation views. Verification: `npm run test:run -- src/pages/account/ui/AccountPage.vm.test.tsx` в `frontend` либо точный account page test file, если tests останутся в существующем файле.
|
||||||
|
- [x] 1.3 Сохранить existing account page render regressions для stale Portfolio Snapshot, nullable values, logo fallback, signed returns, recent section failure isolation и cached portfolio visibility. Если после refactor меняются props state views, обновить tests только на новую presentation interface без изменения expected visible behavior. Verification: `npm run test:run -- src/pages/account/ui/AccountPage.test.tsx` в `frontend`.
|
||||||
|
|
||||||
|
## 2. Frontend: перенести account page logic во ViewModel
|
||||||
|
|
||||||
|
- [x] 2.1 Расширить `frontend/src/pages/account/ui/AccountPage.vm.ts`, чтобы он возвращал discriminated presentation model для top-level states и loaded/empty content: account heading data, portfolio refresh state, totals, cash balances, position sections и retry callbacks. Verification: focused VM tests из 1.1 проходят.
|
||||||
|
- [x] 2.2 Перенести `useBrokerageOperations` и `useBrokerageEvents` из view layer в `AccountPage.vm.ts`. ViewModel должен ограничивать recent operations/events до данных, необходимых presentation components, включая loading/error/empty/loaded flags, first five events, operation payment fallback data и route target для full ledger/events pages. Verification: focused VM tests из 1.2 проходят.
|
||||||
|
- [x] 2.3 Перенести из view layer grouping Portfolio Positions по `STOCK`, `BOND` и other, вычисление currency denominators/share display data, wide-section flags и signed/unlabeled return display flags. ViewModel не должен локализовать text или собирать JSX. Verification: focused VM tests из 1.1 проходят, `npm run typecheck` в `frontend`.
|
||||||
|
- [x] 2.4 Убрать `accessToken` из props state views account page, если после переноса recent hooks он больше нужен только ViewModel. Не менять signatures entity API hooks и не выполнять auth-gating refactor вне scope. Verification: `rg -n "accessToken" src/pages/account/ui` в `frontend` показывает token только там, где он остаётся responsibility VM/container.
|
||||||
|
|
||||||
|
## 3. Frontend: раздробить account page presentation
|
||||||
|
|
||||||
|
- [x] 3.1 Создать nearby presentation components под `frontend/src/pages/account/ui/components/` для самостоятельных sections account page: heading, portfolio refresh state, portfolio totals, cash balances, position section/card/logo, recent operations и recent events. Каждый component должен получать props и рендерить JSX без data/auth/router/navigation/VM hooks. Verification: `npm run typecheck` в `frontend`.
|
||||||
|
- [x] 3.2 Обновить `frontend/src/pages/account/ui/AccountPage.view.tsx`, чтобы exported Loading/Error/Empty/Loaded views только компоновали presentation props и nearby components. Файл не должен импортировать `useBrokerageOperations`, `useBrokerageEvents`, `useAuth`, `useParams`, `useNavigate` или `useAccountPageViewModel`, и не должен содержать collection grouping или share denominator calculations. Verification: `rg -n "useBrokerageOperations|useBrokerageEvents|useAuth|useParams|useNavigate|useAccountPageViewModel|denominators|positions\\.filter" src/pages/account/ui/*.view.tsx src/pages/account/ui/components` в `frontend` не находит запрещённые occurrences в view files, кроме false positives, явно проверенных вручную.
|
||||||
|
- [x] 3.3 Сохранить допустимые presentation hooks во view components: `useTranslation` для labels и локальный UI-only `useState` для image fallback. Не переносить локализованные strings или `Avatar` fallback state в ViewModel. Verification: account page render tests из 1.3 проходят.
|
||||||
|
- [x] 3.4 Убедиться, что split не создаёт cross-slice deep imports и не расширяет public API страницы сверх существующих exports `AccountPage*` из `AccountPage.tsx`. Verification: `npm run deps` и `npm run knip` в `frontend`.
|
||||||
|
|
||||||
|
## 4. Frontend: уточнить AI guidance и conventions
|
||||||
|
|
||||||
|
- [x] 4.1 Обновить `frontend/docs/UI-PATTERN.md`: явно описать роли `*.tsx` container, `*.vm.ts` ViewModel и `*.view.tsx` presentation views; перечислить запрет для view modules на data/auth/router/navigation/VM hooks, domain grouping и derived collection calculations; зафиксировать допустимые presentation hooks `useTranslation`, form-context hooks и локальный UI-only state. Verification: manual read-through против Design D1-D3.
|
||||||
|
- [x] 4.2 Обновить `frontend/docs/CONVENTIONS.md`: расширить `File roles` так, чтобы AI agent видел не только suffix names, но и boundary responsibilities, включая правило semantic split для маленьких files по ответственности. Verification: manual read-through против Design D4-D5.
|
||||||
|
- [x] 4.3 Обновить `frontend/AGENTS.md` коротким pointer на VM/view boundary в `docs/UI-PATTERN.md` и semantic split guidance. Не дублировать полный документ в AGENTS. Verification: `rg -n "ViewModel|view|UI-PATTERN|semantic|responsibility" AGENTS.md docs/UI-PATTERN.md docs/CONVENTIONS.md` в `frontend`.
|
||||||
|
|
||||||
|
## 5. Verification, semantic review и workspace gate
|
||||||
|
|
||||||
|
- [x] 5.1 Запустить targeted account page tests после refactor. Verification: `npm run test:run -- src/pages/account/ui/AccountPage.test.tsx src/pages/account/ui/AccountPage.vm.test.tsx` в `frontend`; если VM tests размещены в существующем файле, команда должна указывать фактические test files.
|
||||||
|
- [x] 5.2 Запустить frontend canonical gate под Node 22. Verification: `npm ci && npm run verify` в `frontend`.
|
||||||
|
- [x] 5.3 Проверить OpenSpec change структурно. Verification: `openspec validate codify-frontend-view-model-boundary --type change --strict --store wealth-ledger-specs` из `specs`.
|
||||||
|
- [x] 5.4 Выполнить semantic verification против Proposal и Design: подтвердить, что user-visible account page behavior, routes, localized text keys, loading/error/empty/loaded states, cached-snapshot behavior, API contract, backend behavior и non-goals не изменились. Verification: записать checked areas и conclusion в implementation summary перед archive.
|
||||||
|
- [x] 5.5 Запустить workspace change dispatcher под Node 22 после завершения affected tasks. Verification: `bash specs/scripts/verify-workspace-change.sh codify-frontend-view-model-boundary` из workspace root.
|
||||||
Reference in New Issue
Block a user