24 KiB
Tasks
Issue-координатор: WealthLedger/main#48. В каждом affected repo ветка feature/48-account-top-positions создаётся от актуального develop; PR открывается в develop. Тело PR: Summary, Linked Issue WealthLedger/main#48, Changes, Verification, ссылки на связанные PR других repo — по .ai/conventions/engineering-workflow.md («Analysis → Branch», «Validation → PR»). Обозначения PC, PVΔ: PC — portfolio-concentration, PVΔ — delta portfolio-view.
1. Backend: хранение, классификация, DTO, OpenAPI
-
1.1 [backend] Verification: ветка
feature/48-account-top-positionsот актуальногоdevelop- Covers: N/A — организационный шаг cross-repo delivery
- Source:
.ai/conventions/engineering-workflow.md«Analysis → Branch», «Branch → Implementation» - Verification:
git -C backend branch --show-currentвыводитfeature/48-account-top-positions;git log origin/develop..HEADпуст до первой задачи - Depends on: none
-
1.2 [backend] Migration: аддитивная модель
TbankInstrumentClassificationи миграцияCREATE TABLE- Covers:
portfolio-view—Свежесть и fallback полного Portfolio Snapshot - Source: design.md «Data / Storage Changes», B1; «Migration / Rollout / Rollback»
- Verification:
npx prisma validate;npx prisma generate;npm run typecheck:app; миграция применена к disposable копии БД с существующими Snapshot, прежние таблицы и строки не изменились;DROP TABLE "TbankInstrumentClassification"на копии возвращает её к исходной схеме - Depends on: 1.1
- Covers:
-
1.3 [backend] Implementation:
TbankClient.getEtf,getAssetBrandи opt-in NOT_FOUND для новых вызовов классификации- Covers:
portfolio-view—Результат получения сектора и эмитента - Source: design.md B4 «Новые методы», «NOT_FOUND»; analysis/data-mapping.md «Источники-кандидаты в T-Bank»
- Verification:
npm test -- src/integrations/tbank/tbank.client.spec.ts: NOT_FOUND даётNotFoundExceptionдляbondBy/etfBy/getAssetByтолько при opt-in; прежниеgetBond/getAssetDescriptionпо-прежнему дают Unavailable;PERMISSION_DENIEDдаётInvalidToken - Depends on: 1.1
- Covers:
-
1.4 [backend] Implementation:
PositionClassificationService— правило 24 ч, четыре исхода по каждому полю, UID→FIGI после NOT_FOUND, дедупликация по инструменту иasset_uid- Covers:
portfolio-view—Обновление сектора и эмитента;portfolio-view—Результат получения сектора и эмитента;portfolio-view—Нормализованный состав Portfolio - Source: design.md B3, B4, B5; analysis/failure-model.md «Классификация отказов по исходам PVΔ «Результат получения сектора и эмитента»», F02–F12
- Verification:
npm test -- src/modules/investments/portfolio: границы 23:59 и 24:00 отwalkStartedAt; при отсутствии значения получение идёт в каждом обходе; 4 исхода × {sector, brand}; mismatch не меняет поле; повтор по FIGI после NOT_FOUND по UID; одинGetAssetByна общийasset_uid; используется сохранённыйassetUid;InvalidTokenпробрасывается, остальные ошибки — нет; типы кроме STOCK/BOND/FUND не запрашиваются - Depends on: 1.2, 1.3
- Covers:
-
1.5 [backend] Implementation: шаг классификации в
PortfolioService.queueSnapshotдо publish;walkStartedAtизTbankHourlyScheduler; mapper пишетsector/issuer- Covers:
portfolio-view—Свежесть и fallback полного Portfolio Snapshot;portfolio-view—Нормализованный состав Portfolio - Source: design.md B2, B3; analysis/failure-model.md F01, F08
- Verification:
npm test -- src/modules/investments/portfolio/application/portfolio.service.spec.ts: отказ token в классификации → Snapshot не опубликован, вызванrejectMembershipToken; прочая ошибка → Snapshot опубликован,lastSuccessfulAtиisStaleне изменены, поля — прежние известные; ошибка GetPortfolio → публикации нет независимо от классификации - Depends on: 1.4
- Covers:
-
1.6 [backend] Implementation: DTO
sectorиPortfolioIssuerDto(nullable), нормализация старых Snapshot вsaved()- Covers:
portfolio-view—Нормализованный состав Portfolio - Source: design.md B6, B7; analysis/system-analysis.md «Семантическая delta
PortfolioPositionDto», «Совместимость и миграция» - Verification:
npm run test:e2e: GET/api/v1/brokerage-accounts/{accountId}/portfolioи/all/portfolioвозвращают у каждой позицииsectorиissuer; для payload без этих полей —null; после отказа token —400 INVALID_TBANK_TOKEN - Depends on: 1.5
- Covers:
-
1.7 [backend] Contract Parity: OpenAPI-artifact с новыми полями совпадает с target-delta
- Covers:
portfolio-view—Нормализованный состав Portfolio - Source: design.md «Contract Implementation»; analysis/system-analysis.md «Семантическая delta
PortfolioPositionDto» - Verification:
npm run openapi:generateиnpm run test:openapi-contractпроходят; в корневомopenapi.jsonуPortfolioPositionDtoполяsector(string, nullable, required) иissuer(nullable, required,id/nameобязательные строки); версия OpenAPI 3.0.x; запросы, маршруты и статусы не изменились (diff схемы сfrontend/src/shared/api/spec/openapi.jsonсодержит только эти добавления) - Depends on: 1.6
- Covers:
-
1.8 [backend] Verification: полный gate и PR в
developсо ссылкой на WealthLedger/main#48- Covers: N/A — финальный gate repo
- Source: backend
.ai/conventions/engineering.md«Проверки и завершение»;.ai/conventions/engineering-workflow.md«Validation → PR» - Verification:
npm run verifyзелёный на финальной ревизии; PR открыт, в телеWealthLedger/main#48и OpenAPI-artifact приложен как вход для frontend - Depends on: 1.7
2. Frontend: контракт, модель, UI
-
2.1 [frontend] Verification: ветка
feature/48-account-top-positionsот актуальногоdevelop- Covers: N/A — организационный шаг cross-repo delivery
- Source:
.ai/conventions/engineering-workflow.md«Analysis → Branch» - Verification:
git -C frontend branch --show-currentвыводитfeature/48-account-top-positions - Depends on: none
-
2.2 [frontend] Implementation: предоставленный backend snapshot в
src/shared/api/spec/openapi.jsonи generatedschema.d.ts- Covers:
portfolio-view—Нормализованный состав Portfolio - Source: design.md B6; frontend
.ai/conventions/data.md«Типы и contract» - Verification:
npm run openapi:generate;npm run openapi:checkбез diff;npm run typecheck; generatedpathsсодержитsectorиissuerу позиции - Depends on: 1.7, 2.1
- Covers:
-
2.3 [frontend] Implementation:
pages/account/model/concentration.ts— состав разрезов, учитываемые позиции, валюты, точные суммы и доли, топ-5, «Прочее», порядок равных, имя эмитента, группы «не указан»- Covers:
portfolio-concentration—Состав разрезов;portfolio-concentration—Названия элементов;portfolio-concentration—Название эмитента при разных названиях бренда;portfolio-concentration—Позиции, учитываемые в разрезе;portfolio-concentration—Сноска о не учтённых позициях;portfolio-concentration—Одна валюта за раз;portfolio-concentration—Доступные валюты вкладки;portfolio-concentration—Топ-5 и строка «Прочее»;portfolio-concentration—Порядок элементов с равной суммой;portfolio-concentration—Расчёт долей;portfolio-concentration—Показ долей;portfolio-concentration—Суммарная доля топ-5;portfolio-concentration—Группы «Сектор не указан» и «Эмитент не указан» - Source: design.md F1; analysis/data-mapping.md M3, I1–I8; analysis/test-cases/conc.md
- Verification:
npm run test:run -- src/pages/account/model/concentration.test.tsпо oracle TC-CONC-007, TC-CONC-008, TC-CONC-016, TC-CONC-020; сумма точных долей = 100 %; 6,25 → «6,3 %»; «< 0,1 %»; FUND исключён из «Эмитентов» - Depends on: 2.2
- Covers:
-
2.4 [frontend] Implementation: state
{accountId, tab, slice, currency}вAccountPage.vm.ts, управляемыеTabs, вкладка только для одного счёта- Covers:
portfolio-concentration—Вкладка «Концентрация» страницы счёта;portfolio-concentration—Вкладка в состояниях страницы;portfolio-concentration—Переключение разрезов;portfolio-concentration—Начальное состояние вкладки;portfolio-concentration—Независимый выбор валюты вкладки;portfolio-concentration—Состояния Portfolio на вкладке «Концентрация» - Source: design.md F2, F3; analysis/test-cases/conc.md TC-CONC-002, TC-CONC-005, TC-CONC-006, TC-CONC-015
- Verification:
npm run test:run -- src/pages/account/ui/AccountPage: вкладки нет дляall, при загрузке, ошибке и пустом Portfolio; по умолчанию открыта «Позиции»; разрез и валюта сохраняются при переключении вкладок и сбрасываются при смене счёта; при исчезновении валюты выбирается первая - Depends on: 2.3
- Covers:
-
2.5 [frontend] Implementation:
Concentration.view— список, раскрытие «Прочее», пустое состояние, сноска, выбор валюты, Alert «Данные неполные», подавление страничного Alert на вкладке- Covers:
portfolio-concentration—Раскрытие строки «Прочее»;portfolio-concentration—Строки без переходов;portfolio-concentration—Пустое состояние разреза;portfolio-concentration—Предупреждение о неполных данных - Source: design.md F2, F4, «UI Implementation»; analysis/ux-design.md «UI States», «Responsive Behavior»; visuals v2 (SHA-256 по ux-design «Materials» сверены до начала)
- Verification:
npm run test:run -- src/pages/account/ui/AccountPage: приpartialна «Концентрации» одно сообщение «Данные неполные», на других вкладках — прежний Alert; строки не являются ссылками; browser-тест 320 px по образцуposition-layout.browser.test.tsxбез горизонтального скролла страницы - Depends on: 2.4
- Covers:
-
2.6 [frontend] Implementation: DonutChart — центр-оверлей, обводка и штриховка через
cellProps, цифры ранга, текстовый эквивалент- Covers:
portfolio-concentration—Диаграмма распределения разреза;portfolio-concentration—Центр диаграммы;portfolio-concentration—Доступность диаграммы без цвета - Source: design.md F5; analysis/ux-design.md «Accessibility», D7; analysis/test-cases/conc.md TC-CONC-027
- Verification:
npm run test:run -- src/pages/account/ui/AccountPage: 7 элементов → 6 сегментов в порядке списка; центр «Топ-5 · 95 %» и «1 000 ₽»; при ≤ 5 элементах только сумма;role="img"иaria-describedbyс названиями, суммами и долями - Depends on: 2.5
- Covers:
-
2.7 [frontend] Implementation: подписи секторов через общий словарь
stock.sectors+ ключgovernment(«Государственный сектор»), видимый и в каталогах- Covers:
portfolio-concentration—Подписи секторов;portfolio-concentration—Русские подписи известных секторов - Source: design.md F6; решение владельца 3084; analysis/test-cases/conc.md TC-CONC-024
- Verification:
npm run test:run: 11 кодов из таблицы PC дают русские подписи;otherвыводится как есть; тестStockCompany(страница акции):sector: "government"отображается как «Сектор: Государственный сектор» — owner-approved изменение вне Specs (design.md F6, 3084) - Depends on: 2.3
- Covers:
-
2.8 [frontend] Automated Testing: регрессия вкладки «Позиции» и «Структуры портфеля»
- Covers:
portfolio-concentration—Вкладка «Концентрация» страницы счёта - Source: analysis/qa-analysis.md «Regression Impact»; analysis/test-cases/reg.md TC-REG-001
- Verification: существующие
AccountPage.test.tsx,position-groups.test.tsx, тестыwidgets/portfolio-structureпроходят без изменения ожиданий - Depends on: 2.6, 2.7
- Covers:
-
2.9 [frontend] Verification: полный gate и PR в
developсо ссылкой на WealthLedger/main#48 и backend PR- Covers: N/A — финальный gate repo
- Source: frontend
.ai/conventions/engineering.md;.ai/conventions/engineering-workflow.md«Validation → PR» - Verification:
npm run verifyзелёный на финальной ревизии; PR открыт со ссылками наWealthLedger/main#48и backend PR - Depends on: 2.8
3. Review и QA до G4
-
3.1
[specs] Independent Review: read-only review backend и frontend PR против Specs, design и analysis(descoped, см. process-record)- Covers:
portfolio-view—Результат получения сектора и эмитента;portfolio-concentration—Расчёт долей - Source: design.md целиком; analysis/system-analysis.md; analysis/failure-model.md
- Verification: отчёт review приложен к Gate Log G4 в process-record; blocker/major закрыты или возвращены в upstream-артефакт
- Depends on: 1.8, 2.9
- Covers:
-
3.2
[specs] QA Verification: прогон test-cases на локальном backend + frontend(descoped, см. process-record)- Covers:
portfolio-view—Обновление сектора и эмитента;portfolio-view—Свежесть и fallback полного Portfolio Snapshot;portfolio-concentration—Состояния Portfolio на вкладке «Концентрация» - Source: analysis/qa-analysis.md «Coverage Matrix», «Entry / Exit Criteria»; analysis/test-cases/conc.md, meta.md, reg.md
- Verification: результаты TC-CONC-002/005/006/007/008/015/016/020/024/027, TC-META-002/003/004/005, TC-REG-001/004 записаны pass/fail; F01–F16 покрыты; ручной блок (макеты v2, контраст, клавиатура, скринридер) зафиксирован
- Depends on: 1.8, 2.9
- Covers:
-
3.3
[specs] QA Verification: exploratory Q-D1/Q-D2/Q-F3 на реальном токене владельца(descoped, см. process-record)- Covers:
portfolio-view—Обновление сектора и эмитента;portfolio-concentration—Группы «Сектор не указан» и «Эмитент не указан» - Source: analysis/qa-analysis.md «Gaps / Blockers», «Test Data and Environment Needs»; решение владельца 3084
- Verification: записаны полнота сектора и бренда у позиций владельца (доля стоимости без значения, наличие
governmentи фондов без сектора), число RPC и длительность первого обхода, отсутствие RESOURCE_EXHAUSTED / queue full; шаг Portfolio укладывается вWORK_WAIT_BOUND_MS - Depends on: 3.2
- Covers:
-
3.4
[backend] Verification: откат backend-bundle на копии данных до G4(descoped, см. process-record)- Covers: N/A — проверка отката (design.md «Migration / Rollout / Rollback»)
- Source: design.md «Migration / Rollout / Rollback» (Backend);
deploy/README.md«Ручной откат и восстановление»;docs/architecture/deployment.md«Откат image» - Verification: на disposable копии БД с применённой миграцией
TbankInstrumentClassification: (1) предыдущий backend-image, запущенный как при ручном откате (up --no-deps backend, без сервисаmigration), проходит healthcheck, GET Portfolio отвечает200на Snapshot с полямиsector/issuer; (2) из предыдущего imagenode node_modules/prisma/build/index.js migrate statusиmigrate deploy— записаны exit code и вывод (ожидание: status сообщает о миграции, отсутствующей локально; deploy не падает). Результат записан в Gate Log G4; при падении deploy — finding в design - Depends on: 1.8
4. Docs (по analysis/docs-impact.md, после merge кода в develop)
-
4.1 [docs] Verification: ветка
feature/48-account-top-positionsот актуальногоdevelop- Covers: N/A — организационный шаг cross-repo delivery
- Source:
.ai/conventions/engineering-workflow.md«Analysis → Branch»; analysis/docs-impact.md «Summary» (правки AS-IS только после merge кода) - Verification: backend и frontend PR слиты в
develop;git -C docs branch --show-currentвыводитfeature/48-account-top-positions - Depends on: 1.8, 2.9, 3.3
-
4.2 [docs] Docs: домен Portfolio —
overview.md, при необходимостиconcentration.md,data-reference.md,flows/portfolio-loading.md, условная строка вall-accounts.md- Covers:
portfolio-concentration—Вкладка «Концентрация» страницы счёта;portfolio-view—Нормализованный состав Portfolio - Source: analysis/docs-impact.md «Documentation Changes» (строки домена и flow)
- Verification:
npm run verifyв docs; текст соответствует реализованному AS-IS - Depends on: 4.1
- Covers:
-
4.3 [docs] Docs: интеграция и архитектура —
integrations/tbank.md,architecture/cross-cutting/data-freshness.md,architecture/containers.md- Covers:
portfolio-view—Свежесть и fallback полного Portfolio Snapshot;portfolio-view—Обновление сектора и эмитента - Source: analysis/docs-impact.md «Documentation Changes» (Integration, Architecture); design.md B1, B4
- Verification:
npm run verifyв docs - Depends on: 4.1
- Covers:
-
4.4 [docs] Docs: ADR 022
stored-instrument-classification(Accepted, AS-IS), строка вadr/README.md, ссылка в Status ADR 019- Covers:
portfolio-view—Свежесть и fallback полного Portfolio Snapshot - Source: analysis/docs-impact.md «ADR Decision»; design.md «ADR Candidates», «Solution Assessment»; решение владельца 3083
- Verification:
npm run verifyв docs; текст ADR 019 кроме строки Status не изменён - Depends on: 4.1
- Covers:
-
4.5 [docs] Docs: глоссарий и навигация —
glossary.md,overview.md,README.md- Covers:
portfolio-concentration—Переключение разрезов - Source: analysis/docs-impact.md «Glossary / Navigation Impact»
- Verification:
npm run verifyв docs; ссылки из навигации ведут на домен Portfolio - Depends on: 4.2
- Covers:
-
4.6 [docs] Verification: PR в
developсо ссылкой на WealthLedger/main#48 и code PR- Covers: N/A — финальный gate repo
- Source:
.ai/conventions/engineering-workflow.md«Validation → PR» - Verification:
npm run verifyзелёный; PR открыт со ссылками наWealthLedger/main#48, backend и frontend PR - Depends on: 4.2, 4.3, 4.4, 4.5
5. Specs: G4 и завершение change
-
5.1
[specs] Verification: запись G4 в process-record с evidence задач 1–4(descoped, см. process-record)- Covers: N/A — gate протокол
- Source: instruction
process-record(Readiness Checklist, Gate Log) - Verification:
npx -y @fission-ai/openspec@1.13.1 validate account-top-positions --store wealth-ledger-specs --strictvalid;git diff --checkчист; строка G4 содержит ссылки на PR, отчёты 3.1–3.3 и решение владельца - Depends on: 3.1, 3.2, 3.3, 3.4, 4.6
-
5.2 [specs] Verification: native archive change после G4 и PR в
developсо ссылкой на WealthLedger/main#48- Covers: N/A — native sync/archive выполняет CLI, canonical specs вручную не правятся
- Source: schema
wealth-ledger-sdd-labapply/archive instruction;.ai/conventions/engineering-workflow.md«Merge → Issue Closed» - Verification:
npx -y @fission-ai/openspec@1.13.1 archive account-top-positions --store wealth-ledger-specsзавершён;openspec validate --all --strictvalid; PR specs открыт; Issue main#48 закрывается после merge всех PR - Depends on: 5.1