Выполнены implementation-owned задачи 1.1–7.5 (27/27). Archive не выполнялся. Текущее evidence — в checkpoint ниже. Входы: [Design revision 1](design.md), включая полностью inline UI/UX package, и [delta specs](specs/tbank-data-sync/spec.md). Перед работой в каждом repo прочитать его AGENTS и применимый routing; перед Node — местный `nvm use --silent`. Ни одна задача не требует изменения root или чтения соседнего checkout в CI. ## 1. Основание и сохраняемая модель - [x] 1.1 [backend] Применить Solution Assessment: использовать текущие Prisma/SQLite/TbankClient, зафиксировать baseline HTTP/RPC и подготовить изолированные исходные данные профиля Design без новой очереди или scheduler. - **Covers:** `N/A` — техническое основание storage/concurrency решения и сопоставимых измерений из Design; самостоятельного пользовательского поведения не добавляет. - **Verification:** сохранить версии runtime, hardware, объём/распределение fixture и числа RPC/latency исходного navigation trace; проверить, что тесты не используют рабочую SQLite и реальные token; проверить существующие owners и отсутствие добавленной инфраструктуры. - [x] 1.2 [backend] После 1.1 добавить additive Prisma migration для connection revision, membership, private datasets и последних полных прогнозов, общих инструментальных источников, coverage/work/staging с описанными unique keys и индексами. - **Covers:** `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Общие данные инструментов отделены от личных`. - **Verification:** `npx prisma validate`, generate/typecheck и migration на пустой и заполненной временной SQLite; автоматическая проверка integrity/FK, сохранности User/Session/TbankConnection/manual cards и исходных зашифрованных token; decimal round-trip без float; подтверждение ключей/индексов и невозможности дублирующей операции. - [x] 1.3 [backend] После 1.2 реализовать локальный membership owner и атомарную границу PUT/DELETE подключения, включая использование списка успешной проверки token и publication fence по revision/attempt. - **Covers:** `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`; `brokerage-accounts` — `Состояния недоступности списка счетов`. - **Verification:** реальные SQLite/HTTP проверки двух пользователей, unknown/empty/stale membership, closed/unsupported/removed account, invalid token, failed replacement и late completion после replace/delete; на warm access path spy фиксирует 0 GetAccounts до HTTP-ответа; данные/coverage/errors старой revision не публикуются. ## 2. Интервалы и выполнение запрошенной работы - [x] 2.1 [backend] После 1.2–1.3 реализовать операции staging → atomic reconciliation → coverage/dataRevision с обязательным исходным ID и локальной фильтрацией границ. - **Covers:** `tbank-data-sync` — `Сверка операций сохраняет идентичность и прежний результат`; `tbank-data-sync` — `Полнота подтверждается успешным покрытием интервалов`; `brokerage-account-ledger` — `Ledger entries preserve broker operation meaning`. - **Verification:** SQLite integration на нескольких страницах: одинаковый ID, изменённые amount/date/state, исчезнувшая операция, identical duplicate, conflicting duplicate, missing ID/cursor и сбой средней страницы; полная старая выборка/сумма/время не меняются до commit, удаление ограничено account/interval/predicate, частичный income-filter не подтверждает весь счёт. Refresh полного квартала/all с ошибкой второго месяца сохраняет весь прежний результат до атомарного commit publication group. - [x] 2.2 [backend] После 2.1 реализовать durable intent и in-process выполнение с coalescing, priority, ограниченной подачей RPC и request-only recovery по processRunId/attemptId. - **Covers:** `tbank-data-sync` — `Прогресс переживает перезапуск и одновременные запросы`; `tbank-data-sync` — `Обновление запускается только запросом с учётом свежести`. - **Verification:** автоматические гонки 20 одинаковых запросов, пересечения диапазонов и stale attempt; kill/restart между страницами и между stage/publish; без нового запроса 0 запусков, следующий запрос начинает незавершённое окно с первой страницы без дублей; после terminal failure нет retry loop; existing limiter/retry bounds сохраняются. - [x] 2.3 [backend] После 2.2 реализовать planner экранных зависимостей, TTL и первичной догрузки истории с учётом календарей и unknown lower bound. - **Covers:** `tbank-data-sync` — `Первая загрузка приоритизирует экран и продолжает историю`; `tbank-data-sync` — `Полнота подтверждается успешным покрытием интервалов`; `tbank-data-sync` — `Ручное обновление ограничено текущим экраном`. - **Verification:** controlled-clock сценарии 59/60, 299/300 и 86399/86400 секунд; повтор current `to=now` через секунду не создаёт RPC и сохраняет asOf; selected/previous/yearAgo выполняются до старой истории; новый видимый пропуск обгоняет pending backfill; Moscow/UTC boundary, конец месяца/года/февраля и незагруженный хвост; openedOn отсутствует — coverage явно ограничена, вся история не объявлена полной. Зафиксировать проверенные source boundary semantics без выдуманного default `from`. ## 3. Локальные владельцы данных и производные результаты - [x] 3.1 [backend] После раздела 2 перевести accounts, portfolio и все consumers личных позиций на общий persistent portfolio/membership owner. - **Covers:** `brokerage-accounts` — `Список активных брокерских счетов`; `portfolio-view` — `Получение Portfolio выбранного Brokerage Account`; `portfolio-view` — `Свежесть и fallback полного Portfolio Snapshot`; `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`. - **Verification:** configured HTTP/SQLite сценарии warm/cold/empty/stale portfolio, independent summary failure, all-account membership revision, отсутствующий metadata fallback и known access error; прежние Money/order/unsupported account правила сохранены; portfolio старше пяти минут остаётся доступен при допустимом доступе без блокирующих RPC. - [x] 3.2 [backend] После 2.1–2.3 перевести ledger и instrument personal history на локальные фильтры, детерминированную пагинацию и revision-bound cursor; убрать обязательный RAM-page TTL read path. - **Covers:** `brokerage-account-ledger` — `User can retrieve an account ledger`; `brokerage-account-ledger` — `User can browse a filtered ledger`; `brokerage-account-ledger` — `Кэш страниц журнала ограничивает локальные ресурсы`. - **Verification:** HTTP/DB cursor tests на равных timestamps, нескольких счетах, эквивалентных filters, connection/membership/rowset change, invalid cursor и `hasNext=false` при неполном coverage; categories/UID/page limit не создают полноту; повторная старая страница не вызывает RPC; personal instrument force удаляет только записи своего predicate. - [x] 3.3 [backend] После 3.2 перевести income/summary на сохранённые операции и раздельную готовность selected/previous/yearAgo, сохранив точные денежные правила. - **Covers:** `brokerage-account-income-analytics` — `Realized income analytics is account-scoped and period-bound`; `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries`. - **Verification:** денежные integration tests с несколькими валютами, отрицательной корректировкой, одинаковыми ID одного/разных счетов, empty complete и missing periods; selected complete/previous loading не даёт нулевую базу; all aggregation требует каждого счёта; обновлённая запись пересчитывается один раз; новый period не возвращает старый под новой подписью. - [x] 3.4 [backend] После 2.2–2.3 разделить shared catalog/metadata/company/quotes и личные projections; сохранить existing UID/FIGI/ticker lookup и источники bond metrics. - **Covers:** `tbank-data-sync` — `Общие данные инструментов отделены от личных`; `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Обновление запускается только запросом с учётом свежести`. - **Verification:** два пользователя используют сохранённый общий источник без повторного RPC и без передачи private fields/errors; каталог без enrichment не выдаёт ложный пустой поиск; свежий query SBER не подтверждает unknown GAZP, повтор того же query использует сохранённый discovery; company/fundamentals included; minute/day TTL независимы; stale initiating connection не публикует даже общий результат; bond quote percent/nominal/ACI и optional MOEX failures сохраняют прежний смысл. - [x] 3.5 [backend] После 3.4 реализовать durable candle coverage, mutable tail и portfolio-instrument prefetch через тот же planner. - **Covers:** `tbank-data-sync` — `Завершённость свечей подтверждается источником`; `tbank-data-sync` — `Первая загрузка приоритизирует экран и продолжает историю`. - **Verification:** автоматические window tests: 365-day seams/dedupe, complete candle без RPC после restart, old incomplete candle после полуночи, утреннее пустое окно → новая свеча, закрытое пустое окно, missing historyFrom, ошибка ручной перечитки; prefetch только бумаг текущего portfolio, открытие другого инструмента запускает его историю. - [x] 3.6 [backend] После 3.1 и 3.4 перевести instrument payouts и account upcoming events на общие сохранённые календари и локальные personal estimates, устранив отдельный synchronous portfolio fetch. - **Covers:** `brokerage-account-upcoming-events` — `User can retrieve upcoming events for an account`; `brokerage-account-upcoming-events` — `Forecasts preserve event meaning and uncertainty`; `brokerage-account-upcoming-events` — `Upcoming events use complete source results`; `tbank-data-sync` — `Общие данные инструментов отделены от личных`. - **Verification:** полные/неполные/пустые календари, cancelled dividends, offer без суммы, MOEX missing block, stock/bond source identity, holdings-dependent estimate и отсутствие private values в shared tables; новый portfolio с новой бумагой + ошибка её календаря + restart возвращает прежний полный прогноз/estimate того же scope с исходным временем; новый period/membership не получает чужой snapshot. Events refresh сохраняет применённые from/to. ## 4. Публичный API и передача контракта - [x] 4.1 [backend] После раздела 3 оформить envelope/meta/dependency coverage всех существующих data GET, observe mode, screen-scoped POST sync и авторизованный GET status в DTO/controllers/Swagger. - **Covers:** `tbank-data-sync` — `Ручное обновление ограничено текущим экраном`; `tbank-data-sync` — `Интерфейс различает свежесть полноту и состояние работы`; `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`. - **Verification:** configured HTTP contract tests для каждого route family, включая accounts/search arrays, stock company, quotes/candles/payouts и all scope; `202` не означает завершение, malformed descriptor отклонён, чужой job 404; `sync=observe`/status не создают RPC при stale/missing/failed; generation отсутствует в API/errors/logs и декодируемых cursors; Problem Details и nullable previous/yearComparison/summary dependency states соответствуют Design. Empty coverage completion меняет stateVersion без изменения pagination revision. - [x] 4.2 [backend] После 4.1 опубликовать сгенерированный OpenAPI artifact для frontend и проверить runtime parity, не превращая specs в editable HTTP-контракт. - **Covers:** `N/A` — передача изменённого публичного контракта из Contract Gate Decision, без самостоятельной бизнес-возможности. - **Verification:** `npm run test:openapi-contract` и сформированный backend-owned artifact; новые DTO/status/errors представлены, secret examples отсутствуют; artifact передаваем явно, backend CI не читает соседний frontend. - [x] 4.3 [frontend] После 4.2 принять предоставленный snapshot, выполнить локальную генерацию и адаптировать entity query owners, включая observe reads и connection/session fences. - **Covers:** `frontend-data-resilience` — `Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio`; `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`. - **Verification:** `npm run openapi:generate`, `npm run openapi:check`; typecheck всех consumers, включая breadcrumbs, document title и scope switch; MSW/RTL доказывает одну canonical cache identity для ordinary/observe, поздние data/status ответы старой connection/session игнорируются, all financial caches очищаются успешной mutation и сохраняются после неуспешной. ## 5. Экранные состояния и ручное обновление - [x] 5.1 [frontend] После 4.3 добавить page-owned screen descriptor и observer запрошенной работы по inline UI/UX package revision 1; разделить transport и source lifecycle. - **Covers:** `tbank-data-sync` — `Интерфейс различает свежесть полноту и состояние работы`; `tbank-data-sync` — `Ручное обновление ограничено текущим экраном`; `frontend-data-resilience` — `Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio`. - **Verification:** MSW/RTL controlled-clock checks: manual refresh обходит TTL только текущего scope; status poll + observe не создаёт новую работу даже после истечения минуты; observer прекращается при terminal/уходе/logout, active duplicate button недоступна; empty coverage completion отображается до завершения дальней истории; reverse-order observe ответы не откатывают данные/доступ; old data/timestamp остаются при transient failure, failed force до TTL сохраняет fresh, known access error очищает personal view. - [x] 5.2 [frontend] После 5.1 адаптировать accounts/account/all screens и независимые overview sections к server completeness/freshness и scoped refresh. - **Covers:** `brokerage-accounts` — `Экран списка брокерских счетов`; `brokerage-accounts` — `Клиентские состояния ошибки списка счетов`; `portfolio-view` — `Состояния и ошибки Portfolio на клиенте`; `brokerage-account-ledger` — `Account overview includes recent ledger events`; `brokerage-account-income-analytics` — `Account overview has an independent current-month income summary`; `brokerage-account-upcoming-events` — `Account overview includes upcoming events`. - **Verification:** RTL scenarios unknown/complete-empty accounts, independent summary staleness, portfolio + recent ops + income + events partial states, сохранённые суммы при failed refresh, 404/invalid token, новая membership в all; кнопка обновляет dependencies overview, не только portfolio. - [x] 5.3 [frontend] После 5.1 адаптировать operations/income/events pages: отдельная полнота периодов и comparisons, cursor recovery и сохранение applied filters. - **Covers:** `brokerage-account-ledger` — `User can browse a filtered ledger`; `brokerage-account-income-analytics` — `Realized analytics never presents an incomplete result as complete`; `brokerage-account-income-analytics` — `Period comparisons preserve calendar and currency meaning`; `brokerage-account-income-analytics` — `Income payments remain traceable to exact Ledger Entries`; `brokerage-account-upcoming-events` — `Account page presents an upcoming events list`. - **Verification:** RTL/MSW: partial empty не показывает «операций/доходов нет», selected готов до comparison без нулевой базы, отрицательная корректировка/одна карточка на identity, INVALID_OPERATIONS_CURSOR возвращает первую страницу с сохранением фильтров, смена периода не переименовывает старые суммы; полный старый events result виден с ошибкой обновления. - [x] 5.4 [frontend] После 5.1 адаптировать stock/bond search и detail sections: quote, company/metrics, candles, position, payouts и personal history к общим статусам и текущему screen scope. - **Covers:** `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Завершённость свечей подтверждается источником`; `frontend-data-resilience` — `Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio`. - **Verification:** section-adapter и page integration tests различают missing/partial/complete-empty/stale/failed, неполные свечи и личные estimates; refresh сохраняет выбранный график/UID и обновляет показанную personal history, не весь каталог; metadata completion не меняет личную cache boundary. ## 6. Доказательства корректности и быстродействия - [x] 6.1 [backend] После раздела 4 выполнить интегрированный crash/durability/rollback прогон на заполненной изолированной SQLite, расширив существующий подход сохранности данными T-Bank. - **Covers:** `tbank-data-sync` — `Прогресс переживает перезапуск и одновременные запросы`; `tbank-data-sync` — `Сверка операций сохраняет идентичность и прежний результат`; `tbank-data-sync` — `Локальная проверка доступа сохраняет границу подключения`. - **Verification:** сохранить runnable DB/HTTP tests для kill-before/after-publish, concurrent readers, membership change, replace/delete и shared result fence; подтвердить Rollback Contract без потери ручных карт и новых данных; unit mocks не заменяют реальные транзакции и reopen DB. - [x] 6.2 [backend] После 6.1 измерить HTTP budget и RPC reduction на профиле Design с задержанным/отказывающим upstream и одинаковым baseline trace из 1.1. - **Covers:** `tbank-data-sync` — `Быстродействие и сокращение запросов проверяются измерениями`; `tbank-data-sync` — `Все экраны читают сохранённые данные без ожидания T-Bank`; `tbank-data-sync` — `Обновление запускается только запросом с учётом свежести`. - **Verification:** ≥100 запросов каждой указанной группы, 10 concurrent clients, p50/p95/p99/max/размеры ответов/hardware; цель p95 ≤500 мс, отдельно первый read после restart; fresh RPC=0, старые полные intervals RPC=0, 20 одинаковых stale requests=1 логический проход/dependency, завершённая работа без нового запроса RPC=0. Показать old/new counts и снижение; провал бюджета не объявлять успехом и не менять порог без явного решения. - [x] 6.3 [frontend] После раздела 5 проверить inline UI/UX package revision 1 в браузере и сохранить уместные состояния в существующих stories на вымышленных данных. - **Covers:** `tbank-data-sync` — `Интерфейс различает свежесть полноту и состояние работы`; `brokerage-accounts` — `Экран списка брокерских счетов`; `portfolio-view` — `Состояния и ошибки Portfolio на клиенте`; `brokerage-account-upcoming-events` — `Account page presents an upcoming events list`. - **Verification:** journey accounts → account/all → ledger → income/comparison → events → stock/bond: cold, complete, partial, stale, failure, force refresh, leave/reopen, connection replacement; 320/375 px и широкий экран, длинные суммы, keyboard/focus, polite announcements, busy/skeleton/reduced motion. Browser evidence дополняет tests; Storybook build не доказывает состояния. ## 7. Документация и итоговые gates - [x] 7.1 [docs] После подтверждённой реализации обновить as-built storage/access/freshness, инвестиционные flows, public API handoff и термин полноты, сохранив ADR как историю принятого решения. - **Covers:** `N/A` — delivery объяснений поставленной архитектуры из Design, без параллельного источника требований. - **Verification:** сверить architecture/containers, cross-cutting data-freshness/ui-resilience, http-api, integrations/tbank, domains accounts/operations/portfolio/income/instruments и glossary со всеми delivered flows; обновить отметку отсутствующей реализации ADR 017 только по факту поставки, сохранить исторические решения и чужие изменения. Пути README → тема → термин/API существуют. - [x] 7.2 [backend] После 6.1–6.2 выполнить canonical gate для итогового backend и передать финальный OpenAPI artifact при отличиях от 4.2. - **Covers:** `N/A` — canonical backend verification из Delivery Map и Contract Gate Decision; не отдельное поведение. - **Verification:** `npm ci`, `npm run verify`, `npm run test:openapi-contract`; результаты обязательных DB/HTTP/latency checks относятся к тому же итоговому состоянию. Type/lint/build не объявляются доказательством migration/concurrency или latency. - [x] 7.3 [frontend] После 6.3 и финального artifact backend выполнить canonical frontend gate для итоговых types/queries/UI/stories. - **Covers:** `N/A` — canonical frontend verification изменённого API/UI package из Delivery Map, без самостоятельной бизнес-возможности. - **Verification:** `npm ci`, `npm run verify`, включая локальный OpenAPI drift; браузерные и boundary checks должны относиться к итоговому коду. Frontend CI использует свой snapshot, а не checkout backend. - [x] 7.4 [docs] После 7.1 выполнить canonical docs gate и смысловую проверку изменённых маршрутов чтения. - **Covers:** `N/A` — проверка связности as-built documentation из Delivery Map, без новых требований. - **Verification:** `npm run verify`, проверка новых/изменённых ссылок и терминов; если изменена диаграмма, проверить её renderer либо явно назвать ограничение. Не выдавать Markdown lint за семантическое подтверждение. - [x] 7.5 [specs] После implementation-owned задач сверить выполненный результат с каждой delta requirement и обновить этот Tasks по наблюдённым результатам без преждевременного archive/main-spec sync. - **Covers:** `N/A` — поддержание существующего SDD change и traceability реализации из Delivery Map; новых behaviors или отдельного журнала доказательств не создаёт. - **Verification:** все 35 delta requirement headings, включая REMOVED, имеют выполненные задачи и подходящее evidence; `npm run verify`, `openspec schema validate wealth-ledger-sdd --verbose`, `openspec validate persist-tbank-data --type change --strict --store wealth-ledger-specs`, `openspec validate --specs --strict --store wealth-ledger-specs`; проверить новые файлы, ссылки и diff. Structural success не означает реализации или approval. Независимое review и последующее завершение lifecycle не маскируются задачами, которые implementation agent может закрыть самостоятельно. Эта подготовка не разрешает менять приложение, применять миграцию к рабочей БД или архивировать change; текущий результат — комплект для начала реализации. ## Implementation checkpoint — 2026-09-24 Пользователь разрешил Apply утверждённых артефактов, включая изменения приложения, публичного API и документации. Архивирование не входит в текущую работу. - Completed: 0/27. Задача 1.1 выполнена частично; checkbox не установлен. - Backend: ветка `codex/persist-tbank-data` от полученного `origin/develop` `0862d56c4e4d9dd554556c3992cc073193020ff1`. Production source/schema не изменены. Добавлены `test/tbank-read-baseline.e2e-spec.ts` и `test/fixtures/tbank-read-baseline.json` с исходным HTTP trace и результатами. - Наблюдённый baseline: временная SQLite со штатными migrations, синтетическое подключение, 3 счёта × 100 000 доступных upstream операций, 200 инструментов; 7 групп × 100 чтений, 10 клиентов. Node v24.21.0, Apple M1 Pro, 10 CPU, 32 GiB. Счётчики считают вызовы TbankClient, а не реальные transport RPC. p95 client end-to-end: accounts 33.05 мс, portfolio 15.21 мс, all portfolio 30.39 мс, ledger 13.17 мс, all ledger 16.20 мс, income 2345.84 мс, all income 7128.47 мс. Полные percentile/size/counters сохранены в JSON; это исходная реализация и не доказательство новой модели. - Наблюдённые проверки: backend `npm run build`, `npm run typecheck:test`, targeted ESLint, `npm run verify` (35 suites, 257 tests) — success; `node test/sqlite.cjs tbank-read-baseline.e2e-spec.ts` — success (1 test). HTTP runner потребовал разрешённый loopback listener вне sandbox. Рабочая пользовательская БД и реальные credentials не использовались. - Specs: `npm run verify`, native schema validation, strict change validation с `--store wealth-ledger-specs` и strict validation всех 25 main specs — success. Повтор `npm ci` с сетевым доступом завершился HTTP 502 настроенного Nexus для `undici-types-8.9.0.tgz`; dependencies/lockfile не менялись. - Backend `npm ci` после проверок также завершился HTTP 502 Nexus для `zeptomatch-2.1.0.tgz`. Установка могла оставить неполный node_modules; успешный verify выше относится к прежнему установленному окружению. Воспроизводимая установка и canonical gate текущей поставки не закрыты. - Remaining: задачи 1.1–7.5. Baseline пока не включает market/candles/payouts, delayed/failing transport, профиль 4 CPU / 8 GiB или заполненные новые таблицы. Миграция, новая модель чтения, frontend/API handoff и as-built docs не реализованы. - Next implementation outcome: закончить 1.1 полным воспроизводимым trace профиля Design и подготовкой fixtures, затем переходить к additive migration 1.2. ### Продолжение установки Повторные установки через Nexus снова получили HTTP 502. Выполнен успешный `npm ci --registry=https://registry.npmjs.org --replace-registry-host=never` в backend (1065 packages) и specs (239 packages), с прежними lockfile/integrity. Manifest, lockfile и постоянная registry configuration не менялись. Это восстанавливает локальное окружение, но не исправляет доступность Nexus. ### Checkpoint после продолжения Apply - Completed: 1.1, 1.2 (2/27); remaining: 1.3–7.5. Предыдущий checkpoint описывает предыдущий прогон, а не текущее состояние реализации. - 1.1: расширенный baseline успешно измерил 23 группы × 100 чтений, 10 concurrent clients, включая stock/bond detail, quote, company/metrics, year/all candles, payouts/search и account/all events. Fixture предоставляет 3 × 100 000 операций и 200 × 5000 свечей; все внешние providers синтетические. Полный trace/percentiles/bytes/счётчики вызовов внешних clients сохранены в backend `test/fixtures/tbank-read-baseline.json`. Это измерение исходной модели на фактическом host, не доказательство budget новой модели 6.2; transport limiter/retries исключены из этих счётчиков. - 1.2: добавлены Prisma models и migration `20260924170000_persist_tbank_data`. Revision присваивается существующим подключениям без изменения ciphertext; SQLite rebuild подключения и новые таблицы выполняются одной транзакцией. Private membership/portfolio/operations/coverage/forecasts/work/staging связаны FK с revision; shared metadata/lookups/catalog/sources/candles/coverage хранятся отдельно. Decimal payload и candle close остаются строками. - Наблюдённые проверки 1.2: Prisma validate/generate, app/test typechecks, `node test/sqlite.cjs tbank-migration.e2e-spec.ts` (2 passed). Проверены пустая/заполненная SQLite, reopen, integrity/FK, сохранность старых User/Session/connection/manual-card records, unique operation identity, одинаковые ID разных счетов, decimal round-trip, индекс чтения, отказ позднего staging attempt, cascade private rows и сохранение shared candle. - 1.3 частично: PUT повторно использует accounts из validateToken, атомарно заменяет connection/private rows и публикует membership. Local access method не расшифровывает token и не делает RPC; различает unknown/empty/stale и известный invalid token. `node test/sqlite.cjs tbank-connection.e2e-spec.ts` (3 passed) проверяет HTTP auth, two users, failed replacement, DB rollback, revision rotation и поздние private writes после replace/delete. Известный invalid token блокирует и существующий HTTP accounts read до RPC; финальный повтор HTTP suite (постоянный loopback listener) и verify прошёл. Data GET ещё используют прежние owners; общий publication fence и discovery через coordinator ещё не реализованы. Checkbox 1.3 не установлен. - Итоговый backend `npm run verify`: 34 suites / 253 tests passed. `npm run test:durability -- /tmp/wealthledger-tbank-rollback.PuzfjF` passed на отдельной предыдущей сборке из `0862d56` и временной SQLite: manual data, restart, rollback/return и backup/restore сохранены. Этот прогон не закрывает задачу 6.1 о новых datasets и worker crash; результатов для неё пока нет. - Frontend, docs, публичный envelope и OpenAPI handoff не изменены. Рабочая пользовательская БД не использовалась. Change не архивирован. - Next implementation outcome: завершить 1.3 — membership discovery/publication с transaction fence текущей revision/attempt, затем staging/reconciliation 2.1. ### Checkpoint — membership publication и операции staging - Completed остаётся 2/27. В 1.3 добавлена транзакционная публикация membership через существующий access owner: revision/attempt fence, сохранение datasets неизменных accounts, cascade удалённых accounts, отказ устаревшему invalid-token результату. Отдельный coordinator ещё не подключён; checkbox не изменён. - Начата persistence boundary 2.1: concrete operations repository сохраняет страницы и continuation progress в SQLite staging, требует исходный ID, проверяет pagination и противоречащие payload, локально фильтрует `[from,to)`. Publication group обновляет операции/coverage всех accounts и intervals одной транзакцией; instrument predicate ограничивает удаления и coverage. operationsRevision изменяется только вместе с rowset, один раз на account. - Наблюдённые проверки: `node test/sqlite.cjs tbank-connection.e2e-spec.ts` — 4 passed; `node test/sqlite.cjs tbank-operations-persistence.e2e-spec.ts` — 4 passed. Проверены rollback неполной группы, отрицательная корректировка, одинаковый ID разных accounts, repeated/missing cursor, отсутствие ID, exact upper boundary, конфликт версий между intervals, predicate isolation, прежняя attempt, concurrent read отдельным SQLite connection и reopen. Использованы только изолированные временные SQLite. - Backend `npm run verify` прошёл (34 suites / 253 tests, lint, typechecks, build). Это проверка текущего промежуточного состояния, не финальный gate задачи 7.2. - Оставшиеся ограничения: HTTP owners ещё не читают новые datasets; worker/coalescing/recovery и interval planner не реализованы. Repository publication пока использует построчные Prisma operations; производительность на 300 000 строк и budget 500 мс не подтверждены. Проверка kill процесса, shared publication fence и полный Rollback Contract остаются в 6.1–6.2. Frontend/docs и публичный API не изменены, OpenAPI handoff не выполнялся. ### Checkpoint — request-driven operations worker - Реализован следующий backend этап 2.1–2.2: operations worker получает token только для действующей revision/attempt, сохраняет intent и staging progress, загружает EXECUTED pages через прежний TbankClient и публикует coverage вместе с завершением работы. Уже полное покрытие автоматически требует атомарной повторной сверки всей группы, даже при запросе инкрементального режима. - Нормализуются пересекающиеся targets одного account/predicate; RPC windows ограничены UTC-месяцем, с защитной секундой по краям и точным storage filter. Двадцать одинаковых запросов присоединяются к одной попытке. Частичное пересечение расширяет pending target только непокрытым остатком. Запрос, соединяющий несколько активных групп, fenced supersedes их producers и перезапускает объединённый staging новой попыткой; старые handles наблюдают successor без запуска работы. Этот случай может повторно загрузить ранее staged страницы и должен учитываться в итоговых измерениях. - Coordinator подаёт одну страницу за turn и выбирает screen перед history; сетевой RPC не удерживает reservation/publication lock. Retry policy остаётся в TbankClient. После terminal failure нет автоматического повторения. При новой runId следующий request очищает unfinished staging/cursor; ранее опубликованные интервалы первичной загрузки сохраняются. Observation и создание нового service не запускают импорт. - Evidence: `node test/sqlite.cjs tbank-operations-sync.e2e-spec.ts tbank-operations-persistence.e2e-spec.ts` — 12 + 4 passed. Sync suite включает настоящий дочерний process и SIGKILL между страницами, перед publish и сразу после publish; child использует текущую сборку из `npm run build` и только SQLite штатного isolated runner. После kill наблюдение не вызывает RPC, запрос запускает unfinished window с первой страницы; committed result и terminal state переживают kill-after-publish. - Проверены полный квартал двух accounts, failure второго месяца и сохранность всех прежних rows/coverage/timestamps, последующий atomic commit, 20-way coalescing, overlap remainder, bridge handles, page priority, known invalid token и отказ чужому account до RPC. Backend `npm run verify` — 35 suites / 255 tests, lint, app/test typechecks и build passed. - Completed остаётся 2/27: 1.3 пока не подтверждена на новом локальном HTTP read path; 2.1–2.2 имеют проверенное operations execution ядро, но ещё не подключены к экранным owners/public sync API. Общий discovery/shared-source scheduling, source TTL/coverage planner 2.3, HTTP envelopes и frontend остаются впереди. Это не итоговое доказательство 6.1, 6.2 или gate 7.2. Бюджет 500 мс и полный RPC navigation trace пока не измерялись. ### Checkpoint — operations coverage/freshness planner, 2026-09-25 - Продолжена 2.3: pure planner разделяет availability, freshness и asOf; полнота вычисляется по union интервалов, независимо от pagination. Account coverage обслуживает instrument subset, обратное не допускается. Current moving end сохраняет наблюдённый asOf и не создаёт RPC на новый хвост внутри TTL; в 300 секунд назначается сверка текущего UTC-месяца. Исторические полные интервалы автоматически не перечитываются, реальные holes не скрываются, после смены месяца незавершённый хвост прошлого месяца остаётся missing. - Operations sync service получил `readPlan`: читает durable coverage, проверяет account membership, возвращает plan и при необходимости запускает existing request-driven worker. Observe всегда read-only; force перечитывает показанные targets. Автоматическая сверка не добавляет RPC для уже полных прошлых месяцев. Верхняя граница новой попытки ограничена временем запроса: будущее не публикуется как подтверждённое coverage. - Verification: backend `npm run verify` — 35 suites / 261 tests passed. Pure calendar/planner suite — 8 tests: 299/300 секунд, current moving end, explicit end, реальные gaps, instrument predicate, rollover и force. `node test/sqlite.cjs tbank-operations-sync.e2e-spec.ts tbank-operations-persistence.e2e-spec.ts` — 14 + 4 passed на итоговой сборке; сохранены SIGKILL/race/atomic-quarter проверки. Новые SQLite сценарии подтверждают 0 RPC свежего readPlan и stale observe, RPC обычного stale request/force и отсутствие будущего coverage. - Completed по-прежнему 2/27: это operations-часть planner, а не весь 2.3. Source TTL 60/86400, discovery и shared sources, screen dependency plans, comparisons/backfill/unknown lower bound, локальные HTTP owners и API envelope ещё не поставлены. Новые функции пока не вызываются существующими HTTP GET. Frontend/docs не изменялись; OpenAPI artifact не изменён. Budget 500 мс и полный navigation RPC trace пока не измерены; change не архивирован. ### Checkpoint — local accounts/portfolio HTTP, 2026-09-25 - Закрыта 1.3: локальный membership/access owner, атомарная замена и удаление подключения, discovery только по запросу, coalescing и revision/attempt fence. SQLite/HTTP evidence: `tbank-connection.e2e-spec.ts` (4 tests) и `tbank-local-reads.e2e-spec.ts` (6 tests). Проверены unknown/empty/stale, два пользователя, unsupported/removed membership (закрытый счёт отсутствует в GetAccounts с ACCOUNT_STATUS_OPEN), failed replacement, invalid token, late publication после replace/delete и сохранение retained account data. - Accounts и portfolio HTTP теперь читают локальные snapshots и возвращают envelope; missing snapshot даёт null, observe не запускает работу. Полный portfolio сохраняется без временного предела при неудачном обновлении. Warm GET не вызывает GetAccounts, decrypt или metadata RPC. Exact total `21.100000002` сохраняется. Двадцать одновременных reads объединяют discovery; abandoned attempt восстанавливается только следующим обычным запросом. - Исправлена freshness составного metadata: худшее обязательное состояние и самый ранний успешный timestamp источников. Пустой aggregate использует TTL membership (300 секунд); непустой portfolio — TTL snapshot (60 секунд). Unit regression проверяет разные TTL и неизменность source timestamps. - Verification: `npm run verify` — 36 suites / 255 tests passed; `npm run openapi:generate` выполнен; runtime OpenAPI parity — 1 passed; SQLite operations persistence/sync — 4 + 14 passed на актуальной сборке, включая SIGKILL/recovery и атомарный refresh полного квартала/all. - Completed 3/27. 3.1 не закрыта: legacy consumers личных позиций ещё используют прежний путь. 2.3 и остальные source owners/API endpoints остаются в работе. Backend OpenAPI сгенерирован; передача frontend snapshot и адаптация consumer остаются задачами 4.2–4.3. Frontend/docs на этом этапе не изменялись. Финальный gate 7.2, полный durability/rollback и профиль 500 мс/RPC reduction не подтверждены. Change не архивирован. ### Checkpoint — batch 2.1–2.3, 3.1–3.2, 2026-09-25 - Закрыты **2.1, 2.2, 2.3, 3.1, 3.2**; completed **8/27**, remaining **19**. - **2.1:** staging проверяет исходные ID, курсоры и конфликтующие версии, включая смену state. Reconciliation обновляет дату/сумму, удаляет исчезнувшие и отменённые операции только в перечитанном account/interval/predicate. Полный квартал/all публикуется атомарно; ошибка средней страницы/месяца сохраняет прежние строки, суммы, coverage и время. SQLite persistence — **5 passed**, включая отдельного читателя, reopen и instrument predicate. - **2.2:** coalescing пересечений включает whole-account/instrument scope; новый экранный интервал обгоняет pending history, после публикации экранной части остаток получает background priority. Force показанного периода не ждёт несвязанный backfill: внутри durable intent хранится отдельная atomic publication group. Её результат сохраняется при последующей ошибке истории. SQLite sync — **17 passed**: 20 одинаковых requests, overlaps/bridge, stale attempt, priority, failure без retry loop и реальные SIGKILL между страницами, до/после publish; recovery запускается только новым запросом. TbankClient остаётся единственным владельцем RPC limiter/retries. - **2.3:** screen dependency planner описывает membership/portfolio, applied operations, selected/previous/yearAgo через существующий income planner, shared metadata/catalog/quote/company/metrics/calendars/candles. Force исключает архив; ordinary ledger request после экранных интервалов ставит недостающее account history с низким приоритетом. Оконные RPC идут последовательно, без предварительной массовой подачи в limiter. Unknown opening использует явный requested floor 1970, сохраняет unknown boundary и не объявляет полную историю. TTL policy проверена на 59/60, 299/300, 86399/86400 секундах; calendar tests покрывают Moscow/UTC, февраль, смену месяца/года, moving end и missing tail. Proto не обещает default-from/inclusivity: используются явные bounds, защитная секунда и точный локальный [from,to), без нового допущения о нижней границе источника. План shared зависимостей готов; их persistent owners/execution и candle prefetch поставляются задачами 3.4–3.6, public screen dispatch — 4.1. - **3.1:** старые RAM portfolio snapshots удалены; accounts, stock/bond personal positions и upcoming-events используют общий persistent owner. Отдельный upstream portfolio fetch событий удалён. Missing member скрывает aggregate/position, не превращается в ноль; summary другого счёта остаётся доступной. Проверены metadata fallback, source timestamp, indefinitely stale portfolio, known access failure и reopen. Local reads — **7 passed**; portfolio structure HTTP теперь использует настоящую SQLite — **4 passed** (точные валюты, отрицательные остатки и неизвестные valuations). - **3.2:** ledger/person-instrument history читают SQLite transaction со стабильным порядком occurredAt/accountId/brokerOperationId. HMAC cursor связан с user/connection, all membership, нормализованным filter/limit и account row revisions, без connection identifier в payload. Изменение coverage/time не ломает cursor; изменение rows/owner/connection — ломает. Read-only observe не ставит work; partial coverage не становится complete из-за hasNext=false, category/UID или размера страницы. HTTP SQLite — **5 passed**, включая reopen, равные даты/ID, equivalent categories и отсутствие RPC старых полных страниц. RAM page TTL read path удалён. Legacy RPC collector сохранён только для ещё не переведённого income (3.3). - **Gates:** `npm run verify` — **38 suites / 235 tests passed**, lint, app/test typecheck и build успешны. `npm run openapi:generate` выполнен; `openapi-contract.e2e-spec.ts` — **1 passed**. Дополнительно сохранены connection SQLite/HTTP — **4 passed**. Всего relevant SQLite/HTTP — **43 passed** (1 + 4 + 5 + 17 + 7 + 5 + 4), рабочая БД не использовалась. `git diff --check` успешен; native validation и specs gate выполнены. - Frontend/docs в этом batch не изменялись. Generated backend `openapi.json` содержит новые envelopes; явная передача consumer snapshot остаётся 4.2. Профиль 500 мс/RPC reduction, итоговый durability/rollback и gates 7.2–7.5 не закрыты; change не архивирован и не объявляется завершённым. - **Следующий Implementation outcome:** 3.3 — income/summary из согласованного локального набора операций с отдельной готовностью selected/previous/yearAgo и сохранением прежнего полного результата при неудачной сверке. ### Checkpoint — local income/summary, 2026-09-25 - Закрыта **3.3**, completed **9/27**, remaining **18**. Income/summary читают операции, coverage и membership одной SQLite read transaction. Удалён последний synchronous operations collector; income больше не получает cursor pages или metadata до HTTP-ответа. - Selected, previous и yearAgo имеют отдельные coverage/status; неполный selected возвращает data:null, незагруженное сравнение — null без нулевой базы. Невозможное календарное/историческое сравнение имеет unavailableReason. Moscow inclusive dates преобразуются в half-open UTC; historical period не расширяется до now, current month сохраняет подтверждённый asOf. Расчёты используют прежние decimal helpers и source timestamps. - Наблюдённые проверки: `npm run verify` — **36 suites / 232 tests passed**, lint, app/test typecheck и build; `npm run openapi:generate` выполнен. `node test/sqlite.cjs tbank-income-local.e2e-spec.ts tbank-ledger-local.e2e-spec.ts tbank-operations-persistence.e2e-spec.ts tbank-operations-sync.e2e-spec.ts openapi-contract.e2e-spec.ts` — **7 + 5 + 5 + 17 + 1 passed**. Только временные изолированные SQLite. Income HTTP проверяет exact signed multi-currency sums, одинаковые ID разных accounts, correction без повторного учёта, partial all/complete empty, раздельные comparisons, другой period, source time/asOf, reopen, observe, blocked upstream, access/period validation и невидимость unfinished staging с сохранением старого финансового результата после failure. - Старые mock-only suites синхронного collector заменены SQLite income проверками; pure финансовые проверки сохранены. Backend OpenAPI содержит income envelopes и nullable previous. Передача consumer snapshot остаётся задачей 4.2; frontend/docs на этом этапе не изменялись. - В запрошенном batch **3.4–3.6 и 4.1 ещё не выполнены**. Общие источники, свечи, durable forecasts и public sync API требуют дальнейшей реализации. Измерения профиля 500 мс/RPC reduction и финальные gates не закрыты. Change не архивирован и implementation complete не заявлен. - **Следующий Implementation outcome:** 3.4 — общие сохранённые catalog, metadata, quotes, company/metrics с раздельной freshness и revision fence. ### Checkpoint — shared UID/FIGI metadata, 2026-09-25 - Продолжена **3.4**; checkbox остаётся открытым, completed **9/27**, remaining **18**. Existing InstrumentMetadataService теперь использует сохранённые Instrument/InstrumentLookup и private SyncWork вместо RAM TTL. Успешное отсутствие отделено от failed lookup; UID/FIGI fallback и aliases сохраняются, FIGI не превращается в выдуманный provider UID. - Успешная metadata переиспользуется между пользователями и после reopen. Для одинакового UID/FIGI descriptor requests объединяются в producer, наблюдатели получают собственные handles. Publication и ошибки fenced по текущей connection revision/attempt; удалённый/заменённый инициатор не изменяет даже общий timestamp. Ошибка его credentials не становится общим отрицательным lookup и не передаётся другому пользователю. - Worker запускается только запросом, читает credentials только для актуальной attempt и подаёт последовательные вызовы через прежний TbankClient. Observe и создание нового service не восстанавливают unfinished intent; новый обычный запрос меняет attempt. Нет startup scan, timer или retry loop. Внутренний force обходит TTL, присоединяется к активной работе и сохраняет ещё свежий источник/время при ошибке. Public screen sync остаётся в 4.1. - Portfolio normalization и ledger читают metadata из SQLite. Обычные запросы планируют отсутствующую/устаревшую metadata показанных позиций/операций; observe этого не делает. Изменение metadata журнала меняет stateVersion, сохраняя pagination binding и действующий cursor. Batch 1000 identities проверен реально: обнаруженный SQLite/Prisma parameter limit устранён ограниченными IN queries в одной read transaction. - Evidence: `npm run verify` — **35 suites / 216 tests passed**, lint, app/test typecheck и build. Старые RAM-only metadata mocks заменены реальной SQLite suite. `node test/sqlite.cjs tbank-metadata-persistence.e2e-spec.ts tbank-local-reads.e2e-spec.ts tbank-ledger-local.e2e-spec.ts portfolio-structure.e2e-spec.ts tbank-income-local.e2e-spec.ts openapi-contract.e2e-spec.ts` — **15 + 7 + 6 + 4 + 7 + 1 passed**. Проверены 20-way coalescing, два пользователя, UID/FIGI/negative/sparse outcomes, transient fallback, 86399/86400 seconds, failed force, late completion после replace/delete, superseded attempt, reopen/request-only recovery, сохранность финансовых read paths и runtime OpenAPI parity. Использованы только временные изолированные SQLite; `git diff --check` passed. - Не закрыты catalog discovery/enrichment, stock/bond company/metrics/quotes и оставшиеся shared projections 3.4; candles 3.5, forecasts 3.6 и API 4.1 также впереди. Полный профиль 500 мс/RPC reduction не измерен; новые RPC assertions относятся к указанным controlled-source tests. Frontend/docs не изменены, consumer artifact не передавался, change не архивирован. - **Следующий Implementation outcome:** продолжить 3.4 — persistent catalog discovery с отдельными enrichment/quote sources и локальные stock/bond reads, сохранив query identity, ticker ambiguity и MOEX/NCR semantics. ### Checkpoint — persistent catalog discovery owner, 2026-09-25 - Продолжена **3.4**, checkbox открыт: completed **9/27**, remaining **18**. Добавлен concrete CatalogDiscoveryRepository/Service в instruments module. Успешный discovery сохраняет упорядоченные UID по нормализованному query/type отдельно от минимальных public catalog identities в InstrumentSource. Отсутствующий query возвращает null; подтверждённый пустой — []. Сохранённый SBER не подтверждает GAZP или bond query. Enrichment не требуется для чтения найденных identities и не считается подтверждённым этим discovery. - Existing stock/bond selection вынесен в один используемый обоими owners helper: trade availability, exact ticker, preferred class, UID ordering, ISIN dedup и отдельные missing-ISIN UID сохранены. Discovery сохраняет прежний предел 30 после dedup. Минимальный catalog payload явно выбирает public поля и не перезаписывает уже имеющуюся полную Instrument metadata или её timestamp; InstrumentLookup completeness не создаётся автоматически. - Read/request/observe API нового owner использует local access, durable private work handles, дневной TTL и existing TbankClient. Одинаковые query/type двух пользователей объединяются; credentials берутся только у актуального producer. Shared writes и final states защищены connection/attempt fence. Recovery запускается только обычным запросом; observe и создание service работу не возобновляют. Failed force сохраняет прежний набор и timestamp. - Evidence: backend `npm run verify` — **35 suites / 216 tests passed**, lint, оба typecheck и build. `node test/sqlite.cjs tbank-catalog-discovery.e2e-spec.ts tbank-metadata-persistence.e2e-spec.ts` — **10 + 15 passed** на disposable SQLite со штатными migrations. Проверены normalized/different queries/types, successful empty/unknown, reopen, 20-way coalescing, private handles, whitelist shared fields, независимость полной metadata, late replace/delete, invalid-token isolation, superseded attempt, request-only recovery, failed force и 86399/86400-second boundary. - **Ограничение этапа:** новый discovery owner зарегистрирован в DI, но HTTP search/detail ещё использует legacy orchestration. Его переключение вместе с отдельными persistent enrichment/quote sources остаётся в 3.4; заявлять локальный HTTP-поиск или отсутствие его broker wait пока нельзя. Company, bond metrics/MOEX/NCR, candles, forecasts и public sync API также остаются. Wire contract не менялся; frontend/docs и consumer snapshot не затронуты. Профиль 500 мс/RPC navigation trace не измерялся; change не архивирован. - Specs `npm run verify` и native strict validation `persist-tbank-data` с явным `--store wealth-ledger-specs` успешны; backend/specs diff whitespace checks успешны, включая новые source/test files. ### Checkpoint — local stock/bond search and persistent enrichment, 2026-09-25 - Продолжена **3.4**, completed **9/27**, remaining **18**. HTTP GET `/stocks` и `/bonds` теперь читают сохранённые discovery/detail/last-price sources, возвращают `{data, meta}` и поддерживают `sync=observe`. Неизвестный query даёт null, подтверждённый пустой — []; найденные identities доступны при незавершённых/отказавших enrichment sources. Метаданные описывают отдельные зависимости, их availability/freshness/private work handles; resourceKey стабилен между missing и последующим результатом. - CatalogEnrichmentService сохраняет типизированные детали по UID и prices раздельно. TTL деталей — сутки, prices — минута; повторный query использует уже сохранённые sources независимо от пользователя. Cold discovery запускает запрошенные enrichment dependencies самостоятельно, поэтому observe не обязан инициировать следующий этап. UID работ объединяются между query/users; до 30 цен одного producer идут одним existing getLastPrices RPC, подробности запрашиваются последовательно через existing TbankClient. Новых dependencies, migration, scheduler или внешней очереди нет. - Публикация каждого source проверяет current connection/revision/attempt; batch дополнительно проверяет initiating attempt. Удаление/замена подключения или superseded initiating attempt не позволяют опубликовать остальные цены batch. Failed force оставляет прежние данные и timestamps. Shared payload явно выбирает public fields. Успешные полезные детали также обновляют canonical Instrument и UID/FIGI aliases внутри той же transaction: generic metadata owner переиспользует результат без повторного RPC. Successful typed miss не становится отрицательным generic UID lookup. - Сохранены decimal price mapping, bond pricePercent отдельно от Money, nominal/ACI, UID matching пакетных цен, selection/dedup/limit. Legacy mock tests синхронного search заменены реальными SQLite/HTTP сценариями; прежние ticker/market/company финансовые tests продолжают проходить. - Evidence на итоговом коде: backend `npm run verify` — **35 suites / 209 tests**, lint, оба typecheck и build passed. `npm run openapi:generate` выполнен. `node test/sqlite.cjs tbank-catalog-local.e2e-spec.ts tbank-catalog-discovery.e2e-spec.ts tbank-metadata-persistence.e2e-spec.ts tbank-ledger-local.e2e-spec.ts stocks.e2e-spec.ts bonds.e2e-spec.ts openapi-contract.e2e-spec.ts` — **15 + 10 + 15 + 6 + 16 + 18 + 1 = 81 passed**. HTTP sandbox EPERM повторён с разрешённым локальным loopback; итоговый прогон успешен. Только disposable SQLite, рабочая БД не использовалась. - Проверены blocked discovery/enrichment без ожидания HTTP, partial/empty/unknown, shared reuse после reopen без decrypt/GetAccounts/RPC, одна price batch на 30 бумаг, межпользовательские/private handles, failed force, независимые minute/ day TTL, wrong detail UID, late replace/delete и superseded batch origin, request-only recovery, финансовые строковые значения и configured access/DTO validation. Эти RPC assertions не заменяют полный профиль измерений 6.2: 500 мс и navigation RPC reduction пока не подтверждены. - **Остаток 3.4:** локальные UID/ticker detail endpoints, company/fundamentals, полноценные quote/metrics owners и MOEX/NCR semantics; legacy synchronous read paths этих sections пока сохранены. Candles/forecasts/public sync API остаются 3.5/3.6/4.1. Backend OpenAPI обновлён, явная передача consumer snapshot остаётся 4.2; frontend/docs в этом этапе не менялись. Change не архивирован, задача 3.4 и общий implementation complete не объявлены. ### Checkpoint — local instrument sections, 2026-09-25 - Завершена **3.4**, completed **10/27**, remaining **17**. UID/ticker, company/fundamentals, quotes и bond metrics читают SQLite и поддерживают observe; missing не превращается в пустой финансовый результат. Exact ticker проверяется до listing selection/ISIN dedup; неоднозначность сохраняется, optional alias не подменяет запрошенный UID другой площадкой. - Details/company/ratings и minute quote sources сохраняются раздельно. MOEX yield и NCR rating сохраняют source identity, точные значения и прежние timestamps при failed force. Shared sources не содержат private projections; два пользователя используют общий результат с private handles. Сохранённая metadata обновляет названия/логотипы portfolio без изменения финансовых сумм и времени portfolio snapshot. - Исправлена гонка присоединения наблюдателя во время SQLite publication: producer остаётся зарегистрированным до обработки всех присоединений. Реальный DB test доказывает один RPC и два завершённых private handles. - Evidence: `npm run verify` — **35 suites / 196 unit tests**, lint, app/test typecheck, build passed; `npm run openapi:generate` passed. SQLite/HTTP suites catalog-local/discovery/metadata/local-reads/portfolio/ledger/stocks/bonds/ openapi-contract: **22+10+15+7+4+6+16+18+1 passed**; после финальных additions local-reads **8 passed**, catalog-local **24 passed**. Runtime OpenAPI parity passed; HTTP fixtures используют постоянный loopback listener. Только disposable SQLite и synthetic credentials; `git diff --check` passed. - Tasks **3.5, 3.6, 4.1, 4.2** запрошенного batch ещё не завершены. Свечи, payouts/events пока сохраняют legacy orchestration. Передача OpenAPI consumer snapshot ещё не выполнена; frontend/docs не изменены. Полный профиль latency/ RPC 6.2 не измерен; implementation complete и archive не заявлены. - **Следующий Implementation outcome:** 3.5 — durable candle coverage с source-confirmed closed ranges, mutable tail и request-only recovery. ### Checkpoint — persistent candle reads and atomic reconciliation, 2026-09-25 - Продолжена **3.5**, checkbox открыт; completed **10/27**, remaining **17**. Stock/bond candles HTTP теперь возвращает локальный `{data, meta}` с observe. Durable CandleRepository использует существующие Candle/Coverage/SyncWork/ SyncStage; новых schema, dependencies, scheduler или startup scan нет. - Диапазоны до 365 суток собираются в staging и публикуются общей transaction. Повторная сверка удаляет исчезнувшие свечи только своего диапазона, сохраняет coverage вне него и при ошибке следующего окна оставляет предыдущие данные и timestamps целиком. Late/superseded/deleted attempts не публикуют данные. - Closed empty coverage переиспользуется после reopen; source isComplete и точные decimal strings сохраняются, bond close остаётся процентом. Текущий UTC-день, включая пустой, изменяемый с minute TTL; смена дня сама не закрывает старое empty/incomplete окно. Полнота ответа отделена от TTL: истечение минуты сохраняет полный результат с stale freshness. Unknown historyFrom для all сохраняет STOCK/BOND_HISTORY_START_UNAVAILABLE. - 20 одновременных запросов объединяются, typed metadata ожидается только внутри worker через существующего source owner. Observe не возобновляет abandoned intent; следующий обычный запрос меняет attempt и запускает работу. Worker последовательно подаёт RPC через existing TbankClient. - Evidence итогового кода: `npm run verify` — **36 suites / 197 unit tests**, lint, оба typecheck и build passed; дополнительный `npm run typecheck:test` после последнего SQLite scenario passed. OpenAPI generated; последовательный runtime parity passed. `node test/sqlite.cjs tbank-candles-persistence.e2e-spec.ts tbank-catalog-local.e2e-spec.ts tbank-local-reads.e2e-spec.ts stocks.e2e-spec.ts bonds.e2e-spec.ts openapi-contract.e2e-spec.ts` — **8+26+8+16+18+1 = 77 passed**. Первый parity run пересёкся с build и увидел прежний dist; итоговый прогон выполнен после завершения build/generation. Только disposable SQLite; `git diff --check` passed. - **Остаток 3.5:** portfolio-only prefetch через screen planner, продолжение дальней истории после показанного периода и интеграция quote comparison с общей candle coverage. Нужна итоговая проверка очередности/предзагрузки и полного crash/restart поведения после этой интеграции. Поэтому 3.5 не отмечена выполненной. Tasks **3.6, 4.1, 4.2** также не завершены; весь batch из пяти задач не выполнен. Frontend/docs и consumer snapshot не изменялись. Профиль p95 500 мс/RPC reduction не измерялся; archive не выполнялся. - **Следующий Implementation outcome:** завершить 3.5 — подключить planner предзагрузки только сохранённых portfolio instruments к тому же candle owner без циклических DI dependencies и подтвердить remaining Verification. ### Checkpoint — portfolio candle prefetch and screen priority, 2026-09-25 - Завершена **3.5**, completed **11/27**, remaining **16**. Existing shared instrument providers собраны в InstrumentSourcesModule без дублирования DI instances и forwardRef; PortfolioModule использует публичный CandleService. - Предзагрузка отбирает только сохранённые STOCK/BOND positions с UID, удаляет дубликаты и применяет existing screen planner. На warm portfolio read её DB планирование не блокирует HTTP; одинаковые активные prefetch объединяются. Открытый не входящий в portfolio инструмент получает собственную историю. - После показанного периода очередь продолжает all-history с меньшим приоритетом. Каждый RPC-window уступает место экранным dependencies; automatic windows публикуются постепенно, force остаётся атомарным для всего показанного периода. Coverage повторно проверяется между окнами. Quote comparison сохраняет и переиспользует тот же durable candle coverage. - Evidence: backend `npm run verify` — **36 suites / 197 tests**, lint, оба typecheck, build passed. OpenAPI generated. SQLite candles/catalog/local reads/ portfolio/OpenAPI suites — **9+26+8+4+1 = 48 passed**, включая ordering между окнами, portfolio-only scope, opening another instrument, request-only recovery, midnight/empty coverage, failed force, exact bond percentage и comparison reuse. Использована только disposable SQLite; latency/RPC profile 6.2 не измерялся. - **Следующий Implementation outcome:** 3.6 — shared payout calendars и private last-complete forecast fallback с исходными timestamps и membership/range fence. ### Checkpoint — durable payout calendars and forecasts, 2026-09-25 - Завершена **3.6**, completed **12/27**, remaining **15**. Instrument dividends, coupons и account/all events читают saved calendars + persistent portfolio, возвращают envelope и поддерживают observe. Stock/bond legacy RAM callbacks и отдельные synchronous calendar/portfolio fetch удалены. Общие источники сохраняют raw events без quantities/estimates; account bond events остаются MOEX, instrument coupons — T-Bank; missing MOEX block не становится []. - ForecastService/Repository принадлежат existing private portfolio owner и используют TbankForecast. Publication проверяет current connection/membership, portfolio versions и shared source versions/timestamps в SQLite transaction. Старый полный snapshot сохраняется при missing новой зависимости, ошибке календаря и reopen; другой applied range/membership не получает его данные. Successful одинаковые dependencies не меняют calculatedAt/исходные timestamps. Public payout rows при missing personal snapshot не получают неподтверждённые estimates; private calculations не возвращаются мимо publication fence. - Сохранены exact signed/fractional money, валюты, registry dates, cancelled dividends, offer без суммы, redemption отдельно от income totals, future unfixed payout entitlement и optional metadata fallback к portfolio ticker. - Evidence: `npm run verify` — **36 suites / 188 unit tests**, lint, оба typecheck, build passed; старые synchronous-cache orchestration tests заменены SQLite tests, pure financial checks сохранены. OpenAPI generated. SQLite/HTTP upcoming-events/catalog/candles/local reads/stocks/bonds/OpenAPI — **15+26+9+8+16+18+1 = 93 passed**, включая реальную optimistic-publication race, two-user reuse/private values, new holding failure + reopen, membership/range isolation, cancelled/empty/unknown calendars, MOEX failure, late connection deletion, default/inclusive dates и observer without RPC. Только disposable DB. - Consumer snapshot ещё не передан; frontend/docs не изменены. Профиль 500 мс/ RPC reduction остаётся 6.2, archive не выполнялся. - **Следующий Implementation outcome:** 4.1 — validated screen-scoped force dispatch и observational authorized status с DTO/OpenAPI и resource states. ### Checkpoint — sync contract preparation, 2026-09-25 - Запрошенная пятёрка **3.5, 3.6, 4.1, 4.2, 4.3**: первые две завершены; **4.1 остаётся открытой**, общий счёт **12/27**. Добавлены DTO и подготовка durable screen intent, нормализация разрешённых screen fields и scope; это пока не подключённые публичные POST/status endpoints. - Dependency DTO теперь описывает фактически возвращаемые dataRevision и stateVersion. Общий mapper учитывает running/queued/failed dependencies, сохраняя availability и successful timestamps прежнего результата. Candle meta явно возвращает requested/complete/missing coverage независимо от freshness; stale current tail не превращается в missing interval. - Проверки: backend `npm run verify` — **37 suites / 192 tests passed**, lint, оба typecheck и build; `npm run openapi:generate` passed. `node test/sqlite.cjs tbank-candles-persistence.e2e-spec.ts tbank-catalog-local.e2e-spec.ts tbank-local-reads.e2e-spec.ts upcoming-events.e2e-spec.ts openapi-contract.e2e-spec.ts` — **9+26+8+15+1 = 59 passed**. Только disposable SQLite и synthetic credentials. Исправлена устаревшая неполная metadata fixture candle-тестов; unit income изолирует Prisma import после расширения operations public provider exports. - Frontend snapshot не передан, frontend не изменён; existing docs edits сохранены. Полный профиль 500 мс/RPC 6.2 не измерялся; archive не выполнялся. - **Следующий Implementation outcome:** завершить 4.1: подключить scoped dispatcher к existing owners и observational status с текущими resource stateVersion, проверить configured HTTP authorization/validation/observe и coalescing на SQLite. Затем последовательно выполнить 4.2 и 4.3. ### Checkpoint — public sync/status and explicit OpenAPI handoff, 2026-09-25 - Завершены **4.1–4.2**, итог **14/27**. POST tbank-sync строго валидирует screen scope, нормализует поля, резервирует private handle и возвращает 202 до broker completion. Concrete coordinator раскрывает dependency graph через existing membership/portfolio/operations/catalog/calendar/candle owners. Force не запускает full-history prefetch и сохраняет атомарность показанного периода operations. Новая инфраструктура/dependencies не добавлены. - Status авторизует current connection/account, использует только observe reads, возвращает текущие resource stateVersion и terminal outcome. Поддержаны handles обычных GET; abandoned work не запускается. Screen progress фиксирует child attempts, superseded результат не приписывается прежнему запросу. - Evidence: backend `npm run verify` — **37 suites / 192 tests**, lint, app/test typecheck и build passed. SQLite/HTTP run screen-sync/all/local-reads/ledger/ income/catalog/candles/events/stocks/bonds — **10+18+8+6+7+26+9+15+16+18**. Финальный screen-sync — **11 passed**, включая empty coverage stateVersion без изменения dataRevision; runtime OpenAPI parity — **1 passed**. 20-way POST coalescing, 202 при заблокированном upstream, malformed/foreign scope, private handles, failure без retry, old-process cancellation и old-connection 404 проверены на disposable SQLite. All route tests обновлены с legacy synchronous mock на настоящую локальную DB boundary. - Backend `openapi.json` явно скопирован в frontend `src/shared/api/spec/openapi.json`; frontend `npm ci`, локальные `openapi:generate` и `openapi:check` успешны. Frontend CI не читает backend. **4.3 остаётся открытой** до итоговых frontend lifecycle tests/gates. - Профиль latency/RPC 6.2 не измерялся; archive не выполнялся. Следующий Implementation outcome: завершить entity query envelope/observe owners и доказать session/connection/access/latest-response fences во frontend. ### Checkpoint — frontend resource owners and response fences, 2026-09-25 - Завершена **4.3**, итог **15/27**, remaining **12**. Все investment entity query owners используют backend envelope. Canonical generated query identity хранит envelope, owners возвращают payload и meta существующим consumers. Missing null не становится []/нулевым финансовым успехом. Types derived from snapshot, включая nullable periods, проходят проверку всех consumers; account VM использует accounts owner вместо прежнего raw-array cache cast. - Observe использует тот же generated key с отдельным transport mode. При несовпадении ожидаемого stateVersion stale response не публикуется; повторяется только observational read. Transport объединяет identity ordinary/ observe для latest-request fencing. In-flight records с ограниченным временем жизни очищаются после завершения; новая инфраструктура или зависимости не добавлены. - Успешная connection mutation отменяет publication прежних data/status/mutation responses и сбрасывает финансовые GET caches, включая sync status. Failed mutation сохраняет caches/boundary. Session generation и unmount защищают ответы от прежней session. Confirmed private access loss очищает snapshots, отменяет связанные запросы и повышает access epoch; поздний success не восстанавливает скрытые данные. Обычный 503 сохраняет cached snapshot. - Sync mutation/status hooks готовы в existing tbank-connection feature; автоматический page observer и действия refresh остаются **5.1**, не включены в эти hooks. Existing frontend fixtures обновлены до нового wire envelope; generic transport tests проверяют envelope, presentation tests — payload. - Evidence: frontend `npm ci`, `openapi:generate`, `openapi:check`; полный `npm run verify` успешен: typecheck, Biome, **51 suites / 287 tests** с coverage, Knip, dependency/FSD и Storybook dependency gates, production build и Storybook build. После усиления status-publication assertions targeted sync tests **2 passed**, финальный typecheck passed. Полный gate ранее также прошёл на итоговом production code. MSW/RTL проверяют canonical observe cache, rejection старой версии, late ordinary/observe ordering, missing/failed null, access loss + late sibling response, connection/session status и mutation. Subscription на query cache подтверждает отсутствие публикации old status. - Backend финальный `npm run verify` — **192 tests**, lint/type/build; итоговые screen-sync **11 passed** и runtime OpenAPI parity **1 passed**. Nested descriptor errors содержат field pointers. Backend artifact и явно переданный frontend snapshot побайтово совпадают (`cmp`). Все DB проверки использовали disposable SQLite. Diff whitespace checks успешны. - Docs и root не менялись этим batch; прежние docs edits сохранены. Frontend production/Storybook builds сообщают предупреждения о крупных chunks; gates завершаются успешно. Browser proof/новые UI states остаются **6.3**, latency/RPC profile **6.2** не измерялся. Archive не выполнялся. - **Следующий Implementation outcome:** 5.1 — page-owned descriptor и passive observer известной работы по inline UI/UX revision 1, с отдельными transport и source lifecycle, остановкой observation после ухода или terminal outcome. ### Checkpoint — scoped screen refresh and populated rollback proof, 2026-09-25 - Завершены **5.1–5.4 и 6.1**, итог **20/27**, remaining **7**. Descriptors принадлежат page VMs; existing tbank-connection feature наблюдает только полученные handles. Status polling и canonical observe reads не инициируют новые imports; terminal/leave/logout останавливают polling. Dependency-only completion также перечитывает projection. Повторный POST текущего scope защищён; поздний acceptance другого scope не заменяет текущий handle. - Entity owner отдельно отдаёт transport status/error, сохраняя source metadata. Known access failures очищают private snapshots с существующим epoch fence; NOT_FOUND самого work handle не трактуется как потеря доступа ко всем счетам. Transient transport failure и failed source work показываются раздельно; прежние суммы, source timestamps и fresh до TTL сохраняются. - Accounts различает unknown и complete-empty; карточки показывают timestamps и freshness отдельных portfolio summaries. Account/all refresh охватывает membership, portfolio, operations, income и events. Частичный portfolio не показывает окончательные totals/structure; подтверждённые позиции и operations/events остаются видимыми с сообщением о неполноте. Overview sections сохраняют независимые partial/error/stale состояния. - Operations/income/events используют applied scope и source completeness. Partial empty не получает финансовый empty message; selected income не ждёт year comparison и не получает вымышленную нулевую базу. Cursor recovery возвращает первую страницу с прежними dates/categories. Смена периода не переименовывает прежний snapshot; сохранённый forecast виден с исходным временем при failed source refresh. - Stock/bond search и detail используют те же source states. Ручной refresh передаёт текущие UID, candle period и personal-history categories/limit, не сбрасывает график и не запрашивает весь каталог. Общий section adapter учитывает missing/partial/stale/failed и source timestamps; незавершённые свечи и неподтверждённые personal estimates не превращаются в нули. - Frontend evidence: итоговый `npm run verify` — **53 suites / 306 tests**, OpenAPI check, typecheck, Biome, coverage, Knip, FSD/dependency и Storybook dependency checks, production и Storybook builds passed. MSW/RTL проверяют duplicate POST, terminal/leave/logout, переход времени за TTL без ordinary GET, empty completion при ещё running history, dependency completion, access loss, fresh snapshot при failed force, scope stock/bond, independent overview/summary freshness, полный overview observe и invalid cursor recovery. Ранее созданные race/negative-correction/period-boundary проверки также входят в этот итоговый gate. Browser/reduced-motion/viewport proof остаётся **6.3**, успешная Storybook build его не заменяет. - Backend evidence: `npm run verify` — **37 suites / 192 tests**, lint, оба typecheck и build passed. Исправлены unsafe Jest asymmetric matcher values в screen-sync test, runtime assertions field pointers сохранены. Через `node test/sqlite.cjs` прошли operations-sync/migration/connection/catalog/ candles/events — **17+2+4+26+9+15**, затем operations-persistence/ledger-local/ screen-sync — **5+6+11**; всего **95 SQLite/HTTP checks**. Включены SIGKILL между страницами и до/после publish, отдельный concurrent SQLite reader, reopen/request-only recovery, membership replace/delete и shared fences. - Existing `test/bank-cards-durability.cjs` расширен populated T-Bank datasets, coverage, forecasts, shared sources, staging/progress и migration state. `npm run test:durability -- /tmp/wealthledger-tbank-rollback.PuzfjF` passed: equality после restart, rollback/return и restore в другую SQLite; integrity и FK checks; User/Session/connection/manual cards, refunds/tombstones и новые datasets сохранены. Evidence result: `/var/folders/j_/h2ft23gd3qq35ps3v5bcftfm0000gn/T/wealthledger-bank-durability-7MLwhL/result.json`. - Rollback pair проверена явно: JSON OpenAPI, сгенерированный прежним backend **0862d56c4e4d9dd554556c3992cc073193020ff1**, равен consumer snapshot frontend **a209d715892862bb6d48084df0c84a10b8d56bf1** (`db184c8^`). Более новый frontend HEAD содержит другой validation/conflict contract и не объявлен подходящей парой этого rollback build. Deploy/rollback реального приложения не выполнялись. Текущие backend OpenAPI и явно переданный frontend snapshot побайтово совпадают (`cmp`); новых public DTO изменений в этом batch нет. - Только disposable SQLite/synthetic credentials; рабочая БД не использовалась. Root/docs не менялись, прежние docs edits сохранены. `git diff --check` passed. Builds сохраняют предупреждения о крупных chunks. Профиль **500 мс/RPC reduction 6.2 ещё не измерен**; implementation complete не объявлена. Remaining: **6.2, 6.3, 7.1–7.5**. Archive/main-spec sync не выполнялись. - **Следующий Implementation outcome:** 6.2 — измерить HTTP/RPC по согласованному профилю и baseline trace; затем 6.3 — browser verification inline UI revision 1. ### Checkpoint — measured reads, browser proof and application gates, 2026-09-25 - Завершены **6.2, 6.3, 7.1, 7.2, 7.3**, итог **25/27**, remaining **2**. Backend сохраняет existing owners: batch reads coverage/source work заменяют загрузку свечей и N+1 queries при prefetch/projection; Intl formatter reused. Проверка source versions прогноза разбита на batches внутри одной transaction, чтобы 200 инструментов не превышали SQLite parameter limit. Financial publication fences и fallback сохранены; новой инфраструктуры нет. - Performance runner: `node test/sqlite.cjs tbank-read-baseline.e2e-spec.ts`. Evidence: backend `test/fixtures/tbank-read-persistent.json`. Изолированный Docker, network none, без volumes; cgroup 4 CPU / 8 GiB (VM доступно 7.65 GiB), Apple M1 Pro SSD host, Node 24.21.0. SQLite 619343872 bytes: 300000 операций, 1000000 свечей, 3 счёта / 200 инструментов. Dependency entries image lock совпадают с текущим lock; отличается только version корневого package. - **2300 warmed reads: 23 группы × 100, concurrency 10**. Server ingress → response finish p95 **7.3–382.6 ms**, все группы ≤500 ms. p50/p99/max/bytes сохранены. Первый DB-only read после Nest/provider restart: **71.2 ms client** (HTTP logger 16 ms). Это не OS-process restart; отдельный process crash/reopen проверен durability suite. Fresh mutable timestamps обновлялись перед каждой группой, чтобы измерять именно fresh path; полный прошлый coverage сохранён. - Baseline navigation trace: **42913 → 0** synthetic TbankClient calls (100% reduction), включая первые reads; baseline repeated-only часть — 41821. Реальный внешний broker network не измерялся; baseline host latency не сравнивается с container latency. 20 stale requests: один portfolio и один positions pass, retries 0; все ответы за 1717 ms при upstream delay 2000 ms. Cold import ответ 18.3 ms; завершённая работа без новых запросов RPC не делает. **Client p95 достигает 3556.4 ms**: server budget не означает end-to-end browser latency ≤500 ms; client timings сохранены отдельно. - Frontend: existing stories independent summary freshness/source failure; фоновые warnings используют polite status announcements. Chrome/Playwright **56 app checks**, **9 Storybook viewport checks**: 320/375/1440, длинные суммы, account/all, ledger, income, events, stock/bond, complete/partial/stale/failed/ missing, refresh, leave/reopen, connection replacement, keyboard/focus, skeleton/busy и reduced motion; JS errors 0. Synthetic API fixtures, без реальных credentials. Проверка resize ждёт завершения responsive chart layout; первоначальный transient overflow воспроизводился до перерасчёта, после него отсутствует. CSS workaround не добавлялся. Evidence текущего запуска: `/tmp/wealthledger-browser-evidence.json`, `/tmp/wealthledger-ui-final3.log`, `/tmp/wealthledger-stories-check.log`, screenshots `/tmp/wl-*.png`. - Backend: `npm ci`, `npm run verify` (**37 suites / 192 tests**), `npm run test:openapi-contract`, `npm run openapi:generate` passed. SQLite/HTTP candles/catalog/discovery/events/income/local reads/screen-sync: **86 checks passed**; durability/rollback повторно passed на disposable DB, result `wealthledger-bank-durability-kWQOEX`. Рабочая БД не использовалась. Финальный backend OpenAPI побайтово равен явно переданному frontend snapshot. - Frontend: `npm ci`, `npm run verify` (**53 suites / 306 tests**), включая local OpenAPI drift, type/lint/coverage/Knip/dependencies, production и Storybook builds passed. Крупные chunks остаются build warnings. - Docs обновляет storage/access/freshness, flows accounts/operations/portfolio/ income/instruments, HTTP handoff и glossary; ADR 017 сохраняет историческое решение и отмечает проверенную реализацию в рабочих ветках, не production deployment. README routes к темам/терминам/API сохранены. Полный отдельный semantic/diagram gate **7.4 остаётся открытым**. - Specs `npm ci` успешно повторён без изменения dependencies после прежнего registry 502. Diff/owner/callers review выполнен; чужие active changes и staged/unstaged изменения сохранены. Итоговая requirement-by-requirement сверка **7.5 остаётся открытой**. Реализация целиком завершённой не объявляется; archive/main-spec sync и deployment не выполнялись. - Финальные `npm run verify` docs (**46 Markdown files, 0 issues**) и specs passed; strict native validation change с explicit store passed. Native apply подтверждает **25 completed / 2 remaining**. Эти проверки не заменяют 7.4/7.5. - **Следующий Implementation outcome:** 7.4 — финальная semantic/link/diagram проверка docs, затем 7.5 — все 35 delta requirements и native final gates. ### Checkpoint — final semantic and requirement verification, 2026-09-26 - Завершены **7.4–7.5**, итог **27/27 implementation-owned tasks**. Сверены все **35 delta requirement headings**, включая REMOVED; таблица ниже связывает каждый heading с задачами и наблюдаемыми проверками. - Semantic review обнаружил и устранил пропуски frontend: список счетов и его skeleton теперь одноколоночные согласно delta requirement; аналитика показывает previous comparison через существующий компонент отдельно от yearAgo. Для каждого сравнения различаются incomplete, source failure и недоступность годового сравнения по календарю/истории; null не становится нулевой базой. Financial Money приходит с сервера, новые calculations/API поля не добавлялись. - Frontend `npm ci`, targeted income (**41 tests**) и `npm run verify` (**53 suites / 307 tests**) passed: local OpenAPI drift, type/lint/coverage, Knip/dependency checks, production и Storybook builds. Финальный browser run: **56 app cases**, **9 Storybook viewport checks**, затем **14 focused income checks**, включая видимость обоих сравнений на 320/375/1440 px; JS errors 0. Storybook проверяет расположение второй account card ниже первой на каждой ширине. Evidence: `/tmp/wealthledger-frontend-verify27.log`, `/tmp/wealthledger-ui27.log`, `/tmp/wealthledger-stories27.log`, `/tmp/wealthledger-income-browser27.log`, screenshots `/tmp/wl-previous-*.png`. - Docs: пройдены маршруты README → architecture/flows → glossary/HTTP API. Убраны оставшиеся утверждения о временном portfolio, потере snapshots после restart, отсутствии force action и совместимости старого клиента с envelope. Уточнены local filtering, private portfolio/shared calendars, предыдущий период дохода и уже согласованный applied period событий. Исторические ADR сохранены; отдельные прежние ограничения CURRENCY-card и налогового смысла dividend_net не скрыты и не объявлены исправленными этим change. - Уточнение evidence MOEX: успешный отсутствующий block даёт [] по существующему MoexClient и его unit test `treats a successful response without the requested block as no events`. Название старого e2e case про missing block моделирует rejected adapter promise, то есть source failure; оно не доказывает отказ реального adapter при отсутствующем block. Поведение adapter не менялось и соответствует delta scenario; повреждённый block/transport error — иной случай. - Docs `npm run verify`: **46 Markdown files, 0 issues**, relative links/anchors и diff passed. Изменённый label в существующей Mermaid sequence проверен по PUT transaction flow и синтаксису; доступного локального Mermaid renderer нет, **отрисовка диаграммы не проверена**. Это явно допустимое ограничение 7.4; Markdown gate не выдаётся за render proof. Нового renderer/dependency нет. - Backend production/tests не менялись в этом checkpoint; результаты 7.2, SQLite/crash/durability/rollback и versioned performance fixture актуальны. Backend OpenAPI и frontend snapshot по-прежнему побайтово равны. Серверный максимум p95 **382.6 ms** в профиле Design, client p95 до **3556.4 ms**; synthetic RPC boundary **42913 → 0**. Реальный broker network/production rollout этим не измерены. Рабочая пользовательская БД не использовалась. - Native gates: `openspec schema validate wealth-ledger-sdd --verbose`, `openspec validate persist-tbank-data --type change --strict --store wealth-ledger-specs`, `openspec validate --specs --strict --store wealth-ledger-specs` passed (**25 main specs / 0 failed**); `npm run verify` specs и final diff checks passed. Long requirement INFO не является validation failure. Проверены staged, unstaged и новые файлы; root/dependencies/main specs/чужие changes сохранены. - Implementation-owned work завершена. Independent review перед archive, archive/main-spec sync, commits/push и deployment этим checkpoint не выполняются. #### Requirement evidence index Здесь B — backend, F — frontend; пути служат адресами evidence, не входами CI соседнего repo. Результаты запусков приведены в checkpoint соответствующих задач. - **B-access:** `test/tbank-connection.e2e-spec.ts`, `test/tbank-local-reads.e2e-spec.ts`. - **B-ops:** `test/tbank-operations-persistence.e2e-spec.ts`, `test/tbank-operations-sync.e2e-spec.ts` (включая SIGKILL и concurrent reader). - **B-ledger:** `test/tbank-ledger-local.e2e-spec.ts`. - **B-income:** `test/tbank-income-local.e2e-spec.ts`, income period/analytics unit tests. - **B-catalog:** `test/tbank-catalog-local.e2e-spec.ts`, `test/tbank-catalog-discovery.e2e-spec.ts`. - **B-candles:** `test/tbank-candles-persistence.e2e-spec.ts`, candle coverage unit tests. - **B-events:** `test/upcoming-events.e2e-spec.ts`, `src/integrations/moex/moex.client.spec.ts`. - **B-sync:** `test/tbank-screen-sync.e2e-spec.ts`. - **B-perf:** `test/tbank-read-baseline.e2e-spec.ts`, `test/fixtures/tbank-read-persistent.json`. - **F-accounts:** `AccountsPage.test.tsx`, `BrokerageAccountList.test.tsx` и viewport stories. - **F-overview:** `AccountPage.test.tsx`, `AccountPage.vm.test.tsx`, `AllAccounts.test.tsx`. - **F-ledger:** `AccountOperationsPage.test.tsx`, filters tests и instrument page tests. - **F-income:** `AccountIncomePage.test.tsx`, filters tests; browser comparisons. - **F-events:** `AccountEventsPage.test.tsx`, filters tests, `BrokerageEventsPreview` consumers. - **F-boundary:** `src/shared/api/client.test.ts`, authenticated query tests, `src/features/tbank-connection/model/screen-sync.test.tsx`, `sync.test.tsx`. - **UI:** browser/reduced-motion/keyboard/state checks 6.3 и final checkpoint выше. | Capability / requirement | Tasks | Evidence | | --- | --- | --- | | `brokerage-account-income-analytics` — Realized income analytics is account-scoped and period-bound | 3.3, 5.3 | B-income, F-income | | `brokerage-account-income-analytics` — Period comparisons preserve calendar and currency meaning | 3.3, 5.3 | B-income, F-income; independent previous/year states | | `brokerage-account-income-analytics` — Realized analytics never presents an incomplete result as complete | 2.1, 3.3, 5.3 | B-ops, B-income, F-income | | `brokerage-account-income-analytics` — Account overview has an independent current-month income summary | 3.3, 5.2 | B-income, F-overview | | `brokerage-account-income-analytics` — Income payments remain traceable to exact Ledger Entries | 2.1, 3.3, 5.3 | B-ops, B-income, F-income; exact signed entries | | `brokerage-account-ledger` — User can retrieve an account ledger | 3.2, 5.3 | B-access, B-ledger, F-ledger | | `brokerage-account-ledger` — User can browse a filtered ledger | 3.2, 5.3 | B-ledger; revision-bound cursor and recovery | | `brokerage-account-ledger` — Ledger entries preserve broker operation meaning | 2.1, 3.2 | B-ops, B-ledger; exact money and identity | | `brokerage-account-ledger` — Account overview includes recent ledger events | 3.2, 5.2 | B-ledger, F-overview | | `brokerage-account-ledger` — Кэш страниц журнала ограничивает локальные ресурсы | 2.1, 3.2 | REMOVED: B-ledger reopen/no RPC; persistent row cursor replaces RAM page TTL | | `brokerage-account-upcoming-events` — User can retrieve upcoming events for an account | 3.6, 5.3 | B-events, F-events | | `brokerage-account-upcoming-events` — Forecasts preserve event meaning and uncertainty | 3.6 | B-events; decimal, cancelled, registry, null offer | | `brokerage-account-upcoming-events` — Upcoming events use complete source results | 3.6 | B-events; fallback/reopen/new dependency failure, MOEX adapter semantics | | `brokerage-account-upcoming-events` — Account page presents an upcoming events list | 5.3, 6.3 | F-events, UI | | `brokerage-account-upcoming-events` — Account overview includes upcoming events | 5.2 | F-overview, B-events | | `brokerage-accounts` — Список активных брокерских счетов | 1.3, 3.1 | B-access; order/empty/independent summaries | | `brokerage-accounts` — Состояния недоступности списка счетов | 1.3, 3.1 | B-access; known invalid/failed replacement/observe | | `brokerage-accounts` — Экран списка брокерских счетов | 5.2, 6.3 | F-accounts, UI; final single-column geometry | | `brokerage-accounts` — Клиентские состояния ошибки списка счетов | 4.3, 5.2 | F-accounts, F-boundary | | `frontend-data-resilience` — Client Cached Snapshot остаётся доступным при обновлении Accounts и Portfolio | 4.3, 5.1–5.4, 6.3 | F-boundary, F-accounts, F-overview, F-income, F-events, UI | | `portfolio-view` — Получение Portfolio выбранного Brokerage Account | 3.1 | B-access; blocked upstream/reopen/local membership | | `portfolio-view` — Свежесть и fallback полного Portfolio Snapshot | 3.1 | B-access; stale >5min/metadata overlay/late revision fence | | `portfolio-view` — Состояния и ошибки Portfolio на клиенте | 5.1–5.2, 6.3 | F-overview, F-boundary, UI | | `tbank-data-sync` — Все экраны читают сохранённые данные без ожидания T-Bank | 1.2, 3.1–3.6, 6.2 | B-access, B-ledger, B-income, B-catalog, B-candles, B-events, B-perf | | `tbank-data-sync` — Обновление запускается только запросом с учётом свежести | 2.2–2.3, 3.1–3.6 | B-ops, B-access, B-catalog, B-candles; TTL/observe/no startup work | | `tbank-data-sync` — Ручное обновление ограничено текущим экраном | 4.1, 5.1–5.4 | B-sync, F-boundary, F-ledger, F-income, UI | | `tbank-data-sync` — Первая загрузка приоритизирует экран и продолжает историю | 2.3, 3.5 | B-ops priority/replay/unknown floor; B-candles prefetch | | `tbank-data-sync` — Полнота подтверждается успешным покрытием интервалов | 2.1–2.3, 3.2–3.3 | B-ops, B-ledger, B-income; pages ≠ completeness | | `tbank-data-sync` — Сверка операций сохраняет идентичность и прежний результат | 2.1, 6.1 | B-ops; atomic quarter/all publish and separate reader | | `tbank-data-sync` — Прогресс переживает перезапуск и одновременные запросы | 2.2, 6.1 | B-ops, B-candles, B-catalog; SIGKILL/reopen/coalescing/fences | | `tbank-data-sync` — Общие данные инструментов отделены от личных | 1.2, 3.4–3.6 | B-catalog, B-events; two users/shared sources/private forecasts | | `tbank-data-sync` — Локальная проверка доступа сохраняет границу подключения | 1.3, 4.3 | B-access, B-sync, F-boundary | | `tbank-data-sync` — Завершённость свечей подтверждается источником | 3.5 | B-candles; incomplete prior day/current empty/closed gaps/failed force | | `tbank-data-sync` — Интерфейс различает свежесть полноту и состояние работы | 4.1–4.3, 5.1–5.4, 6.3 | B-sync, F-boundary, F-income, UI | | `tbank-data-sync` — Быстродействие и сокращение запросов проверяются измерениями | 6.2 | B-perf; 23×100, 10 clients, server p95, 20-way stale coalescing | ### Checkpoint — feature commit verification, 2026-09-26 - Implementation-owned status remains **27/27**; archive/main-spec synchronization and release preparation remain deferred by the Change Owner. - Fixed journal regressions after implementation: a current-day or paginated moving period preserves confirmed completeness; the moving requested end no longer changes `stateVersion` between unchanged status/observe reads. Actual coverage changes still change the version. Disposable SQLite regressions prove these outcomes without additional operations RPC. - Fresh `npm ci` completed in all four affected repositories. Docs required a retry with network access after the configured Nexus host returned ENOTFOUND; dependencies and lockfiles were not changed. - Backend `npm run verify` passed: **37 suites / 193 unit tests**, lint, both typechecks and build. Frontend `npm run verify` passed: **53 suites / 307 tests**, OpenAPI/type/lint/dependency gates, production and Storybook builds. Generated backend OpenAPI remains byte-identical to the explicitly supplied frontend snapshot. Docs verify: **46 files / 0 issues**. Native schema/change/main-spec validation passed; apply reports **27 complete / 0 remaining**. - Full backend `npm run test:e2e` passed in disposable Linux Docker: **21 suites / 226 tests**, including runtime OpenAPI, migrations, financial integrity, crash/restart, concurrency and the persisted read budget. Current tracked source was copied into the existing development image; dependency lock contents match exactly after excluding only root package version. Node **24.21.0**, **4 CPU / 8 GiB**, no network, no host data volumes. - This repeat of the Design profile measured **2300 warm reads**, maximum server **p95 215.7 ms**, synthetic RPC **42913 → 0**. The original versioned measurement remains in `test/fixtures/tbank-read-persistent.json`; the repeat is recorded in `/tmp/wealthledger-feature-linux-e2e-final.log` and `/tmp/wealthledger-feature-budget.json`. This is not a real-broker or production latency measurement and does not establish a 500 ms browser response budget. - Host macOS full HTTP verification is **not green**: two attempts aborted in the native `better-sqlite3` statement cleanup with Node `RemoveEnvironmentCleanupHook`. The same authentication suite and the complete HTTP gate passed in Linux; no dependency workaround or application change was introduced for the host failure. Earlier rollback/durability and browser evidence remains applicable; Mermaid rendering remains unverified as recorded in the preceding checkpoint. - Staged secret scans and whitespace checks passed. Three known public `income/yearAgo` resource identifiers have narrowly scoped Gitleaks comments; a false positive in the Design delivery-map terminology was reworded without changing its meaning. No credentials, working database, local backups or unrelated active changes enter the feature commits.