- Move canonical specs into domain folders (identity, tbank, brokerage, portfolio, instruments, banking, frontend-platform, backend-platform). - Remove process specs; keep still-valid unique rules in openspec/config.yaml. - Keep project-foundation behavior as app-shell and http-api-foundation. - Archive account-top-positions without G4 by owner decision (descoped review/QA recorded in process-record); sync portfolio-concentration and portfolio-view. - Group AI_INDEX by domain. Refs: WealthLedger/main#48
21 KiB
21 KiB
Process Record
Mode: lab Class: complex — межсистемно (backend + frontend + T-Bank), синхронизация внешних данных и финансовые расчёты долей Issue: WealthLedger/main#48
Change Profile
| Артефакт | Выбран | Причина |
|---|---|---|
| research | yes | Trigger: новый продуктовый функционал и вопрос владельца «какой ещё есть критерий?». Нужно сравнить критерии концентрации и формы визуализации в других продуктах. Итог — analysis/research.md. |
| ux-design | yes | Trigger: новый экран, вкладка «Концентрация» с четырьмя разрезами, выбором валюты, диаграммой и «Прочее». Отдельно нужно решить, как она соотносится с существующей «Структурой портфеля». |
| system-analysis | yes | Trigger: меняется контракт Portfolio, в позициях появляются сектор и эмитент. Новые данные берутся из внешней интеграции T-Bank (инструмент, актив и его бренд). |
| data-mapping | yes | Trigger: данные T-Bank (sector, asset → brand) нужно преобразовать в данные позиций Portfolio, а коды секторов — в русские подписи. Нужно правило для пустых и неизвестных значений. |
| failure-model | yes | Trigger: обогащение позиций идёт через внешнюю интеграцию в часовой синхронизации. Отказ или неполнота данных T-Bank не должны ломать Portfolio Snapshot и его свежесть (Open Decision 4 Proposal). |
| nfr | no | Число позиций одного счёта ограничено, вкладка считается по уже загруженному Portfolio. Нагрузку на T-Bank и лимиты запросов рассматривает failure-model; отдельных обязательств по задержке, объёму и хранению нет. |
| observability | no | Новых фоновых процессов нет: обогащение идёт внутри существующей синхронизации с её логированием. Недоступность данных видна пользователю как явные группы «не указан»; частичный успех обогащения (Snapshot сохранён, часть данных не получена) фиксируется в failure-model и существующих логах синхронизации без новых метрик и алертов. |
| security-analysis | no | Модель доступа и trust boundaries не меняются. Сектор и бренд — публичные справочные данные инструмента, к Portfolio того же User добавляются только они. Новые запросы к T-Bank идут под уже существующим токеном подключения того же User, новых секретов и прав нет. |
| test-cases | yes | Trigger: финансовые расчёты (суммы, доли, топ-5, «Прочее», сумма долей = 100 %) и много граничных случаев: одна валюта из нескольких, меньше пяти элементов, равные суммы, нет сектора или бренда, шорт, неоценённые позиции. Для проверки нужны конкретные данные и расчётный oracle. |
| docs-impact | yes | Trigger: несколько docs targets — домен Portfolio, страница интеграции T-Bank (новые используемые данные) и глоссарий (Концентрация, Сектор, Эмитент). |
Gate Log
| Gate | Дата | Scope | Validation | Findings | Decision |
|---|---|---|---|---|---|
| G1 | 2026-10-30 | proposal, change-profile | openspec validate — ожидаемая ошибка «no deltas» до specs; readiness: plan OK (proposal, process-record, research); HTML-комментариев нет; git diff --check OK |
G1 review independent-reviewer: 1 blocker, 4 major, 6 minor — закрыты решениями владельца (issuecomment-3077) и правками; повторный review: ready | approved "вроде все ок" |
| G1 | 2026-10-30 | proposal | — | G2 review B1: правило валют вкладки противоречит proposal | invalidated: решение владельца по B1 (issuecomment-3079) меняет правило валют в proposal |
| G1 | 2026-10-30 | proposal, change-profile | openspec validate --strict valid; readiness: plan OK; proposal обновлён по 3079 (свой список валют вкладки) |
G2 re-review independent-reviewer: B1 закрыт в proposal | approved "Да, G1 ок" (issuecomment-3080) |
| G2 | 2026-10-30 | specs | openspec validate --strict valid; git diff --check OK; readiness: plan OK; self-check по spec-writing.md |
G2 review qa-engineer + independent-reviewer: 1 blocker (B1, валюты), 4 major, ~12 minor — закрыты решениями владельца (3079, 3080) и правками; финальный re-review: ready | approved "да, идем дальше" |
| G2 | 2026-10-30 | specs | — | system-analysis/ux-design: эмитент у фондов, обновление metadata, имя эмитента при расхождении, поведение вкладки (сохранение выбора в пределах страницы, скрытый Select, метрика ≤5, partial) | invalidated: решения владельца (issuecomment-3081) меняют Specs |
| G2 | 2026-10-30 | specs, system-analysis, data-mapping, failure-model | openspec@1.13.1 validate --strict valid; validate --specs 33/33; git diff --check OK; readiness: plan OK; Coverage 32/32 |
G2 rev2/rev3 review independent-reviewer + qa-engineer: 1 blocker (B1 — противоречие canonical «Свежесть и fallback»), 3 major, ~8 minor — закрыты решениями владельца (3081, 3082) и правками; финальный re-review: ready | approved "ок, давай дальше" |
| G3 | 2026-10-31 | design, ux-design, qa-analysis, test-cases, docs-impact, tasks | openspec@1.13.1 validate --strict valid; git diff --check OK; readiness: apply OK; Visual Package v2 SHA-256 сверены reviewer; Coverage 32/32 |
G3 review independent-reviewer + frontend-engineer: 4 major, 4 minor, Q2 — закрыты; backend-engineer не выполнен (квота API), backend-утверждения design сверены основным агентом с кодом; повторный review: ready. Включает изменение вне Specs: подпись «Государственный сектор» на странице акции и в каталогах (3084) | approved "да, все окей, идем дальше" |
| G4 | 2026-11-02 | archive | Код и docs в develop: backend 17432df, frontend 70a2c33, docs 37430da; openspec@1.13.1 validate --strict valid |
Independent Review, QA и проверка отката не выполнялись | archived without verification: решение владельца в сессии specs#74 (descope 3.1–3.4, 5.1) |
Примечание к G2 (2026-10-30): GIVEN «сектор и бренд актива позиции ещё ни разу не получены» в Scenario «Недоступность сектора и эмитента не нарушает Snapshot» (finding N1) и замена строки design-обязательства в failure-model (N2) внесены основным агентом до записи approved G2 и входят в утверждённую версию.
Descoped Work
| Task | Причина | Gate |
|---|---|---|
| 3.1 Independent Review | Владелец решил архивировать без G4: код и docs уже в develop и релизах |
G4 |
| 3.2 QA test-cases | Владелец решил архивировать без G4: код и docs уже в develop и релизах |
G4 |
| 3.3 QA exploratory | Владелец решил архивировать без G4: код и docs уже в develop и релизах |
G4 |
| 3.4 Откат backend | Владелец решил архивировать без G4: код и docs уже в develop и релизах |
G4 |
| 5.1 Запись G4 с evidence | Владелец решил архивировать без G4: код и docs уже в develop и релизах |
G4 |
Lab Journal
| Стадия | Роль / сабагент | Уникальные находки | Решения | Риски найдены / исключены | Проблемы передачи | Skills | Стоимость | Переносимо |
|---|---|---|---|---|---|---|---|---|
| research | product-researcher | В Portfolio DTO нет сектора и эмитента, хотя T-Bank их отдаёт. Доля топ-5 понятнее HHI. Общий мультивалютный рейтинг без конвертации некорректен. «Структура» дублировала бы существующий виджет. | MVP: акции, облигации, секторы; позже: страна, maturity, riskLevel, P&L, HHI; не делать: кредитный рейтинг, конвертацию, treemap | Найден: полнота sector неизвестна. Исключено: смешение валют | Нет | — | 1 вызов | Шаблон «must / later / no» для выбора критериев |
| proposal | product-analyst + основной агент | Эмитент требует отдельной идентичности; основной агент нашёл в proto T-Bank AssetFull.brand {uid, name, company, sector} (краткий Asset бренда не содержит). 8 Open Decisions, 3 из них меняют scope |
Владелец: «Эмитенты» в MVP (отклонение от research: Later → MVP), эмитент = бренд T-Bank, фонды не входят, госбумаги — по сектору T-Bank, режим lab | Найден: «Эмитенты» зависят от полноты бренда. Исключено: группировка по названию | Валидация change ждёт delta specs (ожидаемо) | — | 1 вызов + 2 вопроса владельцу | Решать scope-вопросы до G1 через короткий опрос |
| G1 review | independent reviewer + product-analyst | Источник бренда указан неточно (Asset вместо AssetFull.brand); «Секторы» не задавали набор типов; раскрытие «Прочее» было Open Decision; не зафиксировано отклонение от research |
Владелец (Issue #48, комментарий): «Прочее» раскрывается; без бренда — fallback «Эмитент не указан» без нового G1; «Секторы» только STOCK/BOND/FUND; общий топ-5 вне scope | Найден: несоответствие источника и scope. Исключено: зависимость «Эмитентов» от полноты бренда | Proposal правился после review; Gate Log не заполнялся | — | 1 вызов | Сверять ссылки на proto с исходником до G1 |
| specs | product-analyst | Остальные нормы вкладки не требуют новых источников; в canonical нет перечня вкладок страницы счёта и правил выбора валюты «Структуры портфеля» (они только в коде и docs) — правила валюты, округления, равных сумм определены в Specs и вынесены на подтверждение G2. Эмитент и сектор — новые поля позиции Portfolio | 2 дельты: новая portfolio-concentration (23 Requirement), portfolio-view MODIFIED «Нормализованный состав Portfolio». Решения владельца (3078) внесены |
Найден: расхождение «Структуры портфеля» (деньги в знаменателе и в валютах) и вкладки (без денег) — различие зафиксировано явно | Нет | — | 1 вызов | Сверять правила «как в существующем виджете» с canonical до написания, а не с кодом |
| G2 review | qa-engineer + independent-reviewer + product-analyst | Валюты вкладки не были определены независимо от «Структуры»; «Прочее» при шести элементах скрывало одну строку; метод наибольшего остатка противоречил показу долей в карточках; подписи секторов без источника; не было граничных сценариев 5/6 элементов и противоречивый GIVEN | Владелец (3079): свой список валют вкладки; округление как в карточках, «< 0,1 %»; «Прочее» от семи элементов. Автор: список валют включает отрицательные и нулевые позиции STOCK/BOND/FUND; null считается в сноске при любой валюте |
Найден: расхождение формата долей между спеками и кодом. Исключено: инвариант «100,0 %» на показанных значениях | Gate Log ведёт основной агент (G1 инвалидирован) | — | 1 вызов | Сверять формат чисел с кодом существующего виджета до написания норм |
| specs rev2 | product-analyst | G2 инвалидирован решениями 3081: issuer у фондов в данных; обновление sector/brand раз в сутки с последним известным значением; отказ token — как существующая недействительность; trim пробелов; имя эмитента по наибольшей позиции; сохранение выбора в пределах страницы; метрика топ-5 при ≥6 элементах; центр кольца; «Данные неполные» | portfolio-concentration 28 Requirement (+5: вкладка в состояниях страницы, название эмитента при разных названиях, центр диаграммы, строки без переходов, предупреждение о неполных данных; «Суммарная доля топ-5» и «Начальное состояние» переписаны); portfolio-view MODIFIED + 3 ADDED (срок обновления, последнее известное, ошибки получения) |
Найден: «Данные неполные» привязано к meta по tbank-data-sync, не к неоценённым позициям. Исключено: конфликт metadata/invalid token (отсылка к существующему поведению) |
Gate Log ведёт основной агент | — | 1 вызов | Сверять производные analysis-артефакты с Delta Specs до G2 |
| specs rev3 | product-analyst | G2 re-review: хранение sector/brand противоречило «Свежесть и fallback» (только онлайн, без долговременного справочника) и «metadata не определяет успешность»; граница 24 ч была сформулирована как «24 ч + интервал»; «не найдено», пустой ответ и ответ о другом активе не были определены | 3082: исключение для sector/brand; «не найдено» = «значения нет»; равные наибольшие позиции эмитента — по алфавиту; предупреждение о неполных данных только на вкладке | portfolio-view: MODIFIED «Свежесть и fallback» (полная копия + 2 исключения и 2 сценария), ADDED «Обновление сектора и эмитента» и «Результат получения сектора и эмитента» (таблица исходов), без дублей; portfolio-concentration: название эмитента по алфавиту, предупреждение без дубля |
Найден: страничного сообщения о неполноте в canonical «Состояния и ошибки Portfolio на клиенте» нет (требует лишь не выдавать неполный итог за окончательный), поэтому MODIFIED для него не нужен. Исключено: дублирование норм об ошибках | Gate Log ведёт основной агент | — | 1 вызов |
| design ∥ qa-analysis | solution-architect, qa-engineer | Общий metadata-кэш не подходит под 24 ч и 4 исхода, нужна отдельная таблица классификации; шаг классификации должен идти до publish, иначе отказ token не инвалидирует подключение; DonutChart 9.7.3 хватает без прямого recharts | Таблица TbankInstrumentClassification, opt-in NOT_FOUND только для новых вызовов, состояние вкладки поднято в page VM; владелец: ~25 ч, квоты в QA до G4, «Государственный сектор» в общем словаре (3084) |
Найдено: изменение страницы акции вне Specs (одобрено 3084); откат образа без миграции | Субагенты не видели полный текст review, findings пересылались вручную | — | 2 вызова + 3 доработки | Сверять design-ссылки на код до G3 |
| test-cases + docs-impact + tasks | qa-engineer, documentation-engineer, solution-architect | 21 из 30 зарезервированных TC ничего не добавляли сверх Scenario и выброшены; «эмитент» конфликтует с термином docs | 15 TC + TC-CONC-020; глоссарий с оговоркой, ADR 022 (3083); 28 tasks по 4 repo | Найдено: 2 неверных oracle (TC-CONC-007, TC-META-003) | — | — | 3 вызова | Пересчитывать oracle независимым ревьюером |
| G3 review | independent-reviewer, frontend-engineer; backend-engineer — сбой по квоте API (3 попытки) | 4 major, 4 minor, Q2 (откат без миграции); frontend API DonutChart подтверждён | Все findings закрыты; backend-утверждения design (до publish, InvalidToken catch, NOT_FOUND в call(), WORK_WAIT_BOUND_MS) основной агент сверил с кодом вручную |
Остаётся: backend-ревью субагентом не выполнено | Квота API | — | 5 вызовов | Ревью backend повторить на G4 |