Files
main/audits/2026-10-11/reports/previous/complexity-audit.md
T
ksv741 2b63bde934
Conventional commits / commits (pull_request) Successful in 13s
docs: archive technical audit 2026-10-11 in develop (#36)
2026-10-17 19:30:38 +03:00

71 KiB
Raw Blame History

WealthLedger — Complexity, Redundancy & Engineering Overhead Audit

Дата: 11 октября 2026 года.

Метод: ponytail-audit, статический анализ owners, consumers, проверок и последствий удаления.

Основание и ограничения

Изучены root, frontend, backend, docs, specs и обнаруженный отдельный репозиторий deploy. Первый отчёт technical-audit-2026-10-11.md прочитан. Его функциональные дефекты и уже перечисленные simplification opportunities не включены в новые findings.

Основные checkout совпадают с первым аудитом:

Репозиторий Commit
frontend c882120
backend 0ad84ff
docs e6fd4f6
specs fcdc805

Выполнены чтение, поиск, Git inspection и подсчёты через rg. Единственная дополнительная проверка инструментом:

source "$HOME/.nvm/nvm.sh"
nvm use --silent
node node_modules/openapi-typescript/bin/cli.js \
  src/shared/api/spec/openapi.json \
  -o src/shared/api/generated/schema.d.ts \
  --check

Результат: exit 0, установленный openapi-typescript 7.13.0. Проверка не записывает output: сравнение и выход происходят до mkdirSync/writeFileSync — frontend/node_modules/openapi-typescript/bin/cli.js:125–134,280–291.

Build, полные verify, тестовые наборы, установки, Docker и deployment не запускались. Финальные git status --short всех шести обследованных рабочих деревьев не показали изменений.

Время, стоимость CI, bundle size и расход токенов не измерялись.

A. Executive Summary

Главные источники избыточности

  1. Обязательный полный локальный workflow для любого code change.

    Frontend и backend требуют npm ci и полный verify перед завершением, независимо от изменённой области. Дополнительные conventions отдельно направляют к typecheck/lint/risk checks. Это расширяет небольшую задачу до полного bootstrap и проверки всего приложения.

    Evidence: frontend/.ai/conventions/engineering.md:58–66, backend/.ai/conventions/engineering.md:58–66, frontend/.ai/conventions/ui.md:165–170.

  2. Повторная работа внутри одной границы проверки.

    • Frontend verify вызывает TypeScript дважды.
    • Backend отдельно typecheck’ит application, хотя test typecheck включает те же application sources.
    • Backend CI собирает приложение в verify, затем повторно в test:e2e.
    • SQLite runner regression повторяет весь functional suite пять раз ради свойств самого runner.

    Evidence: frontend/package.json:26, backend/package.json:22–34, backend/tsconfig.typecheck.test.json:7–8, backend/.gitea/workflows/verify.yml:84–89, backend/test/sqlite-regression.cjs:20–22,77–91.

  3. Самописная проверка, уже реализованная установленным инструментом.

    check-openapi.mjs — 45 строк temp-directory/subprocess/cleanup orchestration для возможности openapi-typescript --check. Это наиболее уверенный tooling-cut с сохранением той же гарантии.

  4. Production API, поддерживаемые тестовыми consumers.

    • useAuthenticatedQueries: production callers отсутствуют.
    • InstrumentMetadataService.read: используется metadata persistence suite; production использует request/savedMany.

    Evidence: frontend/src/shared/api/authenticated-query.ts:15–32,61, frontend/src/shared/api/authenticated-query.test.tsx:9–23, backend/src/integrations/tbank/instrument-metadata.service.ts:41–63, backend/test/tbank-metadata-persistence.e2e-spec.ts:87–382.

  5. Тесты иногда обходят дешёвую существующую boundary.

    Чистые преобразования проверяются через fake Prisma transactions или background orchestration; page tests поддерживают fake query-result shapes параллельно существующей MSW boundary.

  6. Противоречивая процессная authority.

    Локальные инструкции задают opt-in OpenSpec и запрещают audit artifacts в docs. Действующие process specs требуют registry, snapshots и canonical workflow для audit-derived работы. Это создаёт дополнительные artifacts и решения о том, какую инструкцию исполнять.

    Evidence: specs/AGENTS.md:3–6, docs/AGENTS.md:12–14, specs/openspec/specs/project-foundation/spec.md:9–19, specs/openspec/specs/audit-remediation-workflow/spec.md:9–49.

Общая оценка

Масштабный архитектурный рефакторинг не нужен. Не подтверждена потребность вводить новые interfaces, generic workers, fixture frameworks, архитектурные validators или quality tools.

Самые полезные изменения сокращают число путей, запусков и обязательных artifacts, сохраняя существующие owners и реальные behavioral proofs.

B. Complexity Inventory

B1. Количественные показатели

Метрика Результат Метод и ограничения
Package script entries 67 Root 3; frontend 25; backend 27; docs 5; specs 5; UI/icons workspace builds 2. Это entrypoints и aliases, не 67 самописных программ
Custom script/adapter/harness/plugin files 21 Frontend 6; backend 10; docs 2; specs 1; deploy 2. Git hooks и декларативные configs отдельно
Custom Git hooks 3 Frontend pre-commit/commit-msg; specs commit-msg. Generated Husky files и Git samples исключены
Custom release hook declarations 4 Frontend/backend/docs/specs after:git:init; root такого helper не имеет
Frontend verify command stages 12 Разделение команды на последовательные стадии; вложенные workspace builds отдельно не разворачиваются
Backend verify command stages 6 Lint, lint-config tests, два typecheck, unit coverage, build
Operational verification families 29 Группы в разделе C; не количество отдельных ESLint rules или test assertions
Участки повторной/малоинформативной проверки 7 Frontend TS; backend TS subset; backend rebuild; full-suite runner repetition; preset-parity meta-tests; docs/specs clean-checkout diff checks
Test files frontend/backend 63 / 59 Backend: 39 colocated specs + 20 integration suites. Browser files входят в frontend 63
Test files вместе с deploy harness 123 122 TS/TSX test files + deploy/tests/deploy.sh; CJS инфраструктурные проверки здесь отдельно
Production TS/TSX 34 465 строк Frontend 16 967; backend 17 498. Generated, stories, fixtures/test support исключены
Test TS/TSX 23 679 строк Frontend 11 537; backend 12 142
Test/production ratio ≈ 0,69 Физические строки, включая comments/blank lines. Не критерий качества архитектуры
Frontend stories / support 18 файлов / 6 файлов 1 855 / 263 строки соответственно; не включены в test LOC
Классифицированные factory/polling definitions не менее 18 Frontend 3 общие factories; backend 4 service factories, 4 deferred helpers, 7 polling helpers. Локальные render/helpers не полностью включены
Frontend module mocks 4 в 3 файлах vi.mock; не учитывает spies и MSW handlers
Backend module mocks 18 в 12 unit files jest.mock; сам count не является finding
Snapshot assertions 0 найдено Поиск toMatchSnapshot, toMatchInlineSnapshot, toMatchFileSnapshot, __snapshots__ в обследованных test sources
Backend runtime SHA/HMAC mechanisms 8 7 createHash emission sites + один signed-cursor mechanism с encode/decode HMAC. Password bcrypt отдельно
Gitleaks archive checksum steps 4 Одна download-integrity policy в четырёх независимых repos
OCI digest publication paths 2 Frontend/backend image workflows
Подтверждённые точки удаления 18 Перечень в G; считаются удаляемые элементы/стадии, не файлы
Обследованные single-production-consumer abstractions 6 примеров RouteTransition, InstrumentSearch, useInstrumentSearch, metadata repository work, queueSnapshot, TBANK_ACCESS. Это выборка, не полный census

LOC и количества используются для описания масштаба. Они не доказывают избыточность.

B2. Все custom scripts и исполняемые adapters

Файл Назначение и consumers; автоматизация Пересечение / последствия удаления / решение
frontend/scripts/check-openapi.mjs:1–45 Freshness generated types; вызывается openapi:check и verify Полностью покрывается native --check. Удалить реализацию, сохранить проверку
frontend/scripts/check-release.cjs:1–24 Manifest version ↔ reachable stable tag; release-it hook Не эквивалентен requireCommits. KEEP: предотвращает повторную подготовку версии
frontend/scripts/test-eslint.mjs:23–395 Config/rule/fixer proofs; автоматически из test:lint/verify Смешивает проектные checks и exhaustive preset parity. SIMPLIFY, сохранять probes реальных exceptions/custom fixers
frontend/scripts/test-pre-commit.mjs:17–79 Staged-index scanning, redaction, fail-closed; security CI и ручная команда Full-history scan не доказывает index behavior. KEEP
frontend/scripts/check-image-publication.cjs:15–88 Модель retry после post-push failure, exact digest/revision/smoke Автоматических callers не найдено. Не считать dead только из-за этого: самостоятельный workflow proof. KEEP как targeted check, не обязательный gate каждой правки
frontend/eslint-rules.mjs:1–178 Два custom ESLint rules; загружается lint config Часть правил — formatting/обязательная форма кода. SIMPLIFY, не заменять новым analyzer
backend/scripts/check-release.cjs:1–11 Version/tag guard; release-it hook Штатный release guard не покрывает эту policy. KEEP
backend/scripts/generate-openapi.cjs:1–41 Swagger generation из built app без deployment config Package command и contract integration suite. TypeScript сам контракт не генерирует. KEEP
backend/test/sqlite.cjs:1–95 Per-suite temporary DB, migrations, subprocesses, signal cleanup Все SQLite entrypoints. Обычный Jest не гарантирует DB isolation. KEEP
backend/test/sqlite-regression.cjs:1–96 Runner isolation/failure/signal proof; ручной README entrypoint Пять полных успешных suite runs избыточны для runner properties. SIMPLIFY область прогонов
backend/test/e2e-env.cjs:1–17 Отказ от не-изолированной DB, synthetic credentials Jest setup и crash fixture. KEEP: защита данных developer
backend/test/fixtures/tbank-sync-crash.cjs:1–86 Управляемый kill процесса на durable boundaries Consumer — operations persistence suite. In-process mocks не заменяют crash proof. KEEP
backend/test/eslint-config.cjs:9–146 Profile scope, generated ignores, import exceptions Автоматически test:lint. SIMPLIFY: project scope/exception checks полезны; поведение каждой library rule не нужно доказывать заново
backend/test/runtime-check.cjs:1–8 Проверяет строку start command, наличие dist и require generated client Runtime callers не найдены; config test использует имя как fixture path. Real image smoke сильнее. DELETE
backend/test/container-smoke.cjs:1–77 Native modules/assets, migration, non-root/read-only runtime, auth/restart Image publication и manual package entrypoint. Host build это не доказывает. KEEP
backend/test/bank-cards-durability.cjs:1–219 Historical build → migration → restart → rollback → restore Risk-triggered manual entrypoint. Fresh DB suites не заменяют historical compatibility. KEEP
docs/scripts/check-release.cjs:1–10 Clean status + version/tag guard Release hook. Porcelain видит untracked files; native clean guard не полностью эквивалентен. KEEP
docs/.markdownlint-rule-relative-links.cjs:1 Adapter .default установленного link rule Оба markdownlint запуска. Не собственный validator. KEEP
specs/scripts/check-release.cjs:1–10 Clean status + version/tag guard Release hook. KEEP
deploy/deploy.sh:1–192 Tagged snapshot, preflight, lock/pending, backup, migration/readiness Ручной запуск, затем self-handoff к tagged script. KEEP
deploy/tests/deploy.sh:1–251 Real Git/files/locks + Docker double; optional bind-restore proof Ручной entrypoint. KEEP: orchestration и bind semantics не доказываются application tests

Не установлена необходимость централизовать десятистрочные release helpers между независимыми repos. Общий tooling package добавит dependency boundary и release ownership ради небольшого копирования.

B3. Package scripts: роль и оправданность

Определения: package.json:8–12, frontend/package.json:9–34, backend/package.json:11–38, docs/package.json:8–14, specs/package.json:8–14.

Группа entrypoints Consumers и оценка
Root release:preview, release:prepare, commitlint Release/operator и commits CI. Штатные CLI wrappers; оставить
Frontend dev, dev:catalog, build:catalog, preview:catalog, preview Developer/catalog lifecycle. Разные outputs; не дублируют одну проверку
Frontend build, build:packages, typecheck Application/workspace compilation. Packages нужны из-за dist-based exports; проблема — частота повторного запуска
Frontend lint, lint:eslint, lint:fix Alias, check, explicit edit. lint alias сам по себе не требует удаления
Frontend test, test:run, test:coverage, test:lint Watch, one-shot, coverage, tooling tests. Различимые режимы; уменьшать обязательность, не механически удалять entrypoints
Frontend openapi:generate, openapi:check Explicit generation и read-only freshness. Оставить оба; check реализовать native CLI
Frontend knip, deps, deps:storybook Dead usage, production boundaries, transitive catalog isolation — разные свойства
Frontend verify, prepare, release pair, commitlint Aggregate gate, Husky bootstrap, release и commit policy. verify упростить
Backend start, start:dev, start:debug, start:prod Различные runtime/debug modes; production также задаётся Docker
Backend build, openapi:generate Prisma/Nest output и public artifact; оставить standalone completeness
Backend format, lint, lint:check, lint:fix Aliases и явный check/edit. Небольшая стоимость, нет причины строить новые wrappers
Backend typecheck:app, typecheck:test Оставить targeted entrypoints; в полном gate достаточно test superset
Backend test, test:watch, test:cov, test:debug Runner modes; текущая необходимость debug не опровергнута отсутствием CI caller
Backend test:e2e, test:sqlite, test:performance, test:openapi-contract Full functional, auth/cards subset, отдельный benchmark, отдельный contract proof. Сокращать repeated build при orchestration, не смешивать наборы
Backend test:container, test:durability Image/historical-data boundaries; risk-triggered
Backend verify, test:lint, release pair, commitlint Aggregate/tooling/release policy; упростить aggregate
Docs lint, verify, release pair, commitlint Содержательный Markdown gate. Два lint запуска обрабатывают разные наборы с разными changelog rules
Specs verify, release pair, commitlint, prepare verify полезен только как local diff check в нынешнем виде; prepare незаметно меняет hooksPath
UI/icons build Vite bundle + TypeScript declarations для двух реально используемых packages

B4. Hash, SHA, freshness и integrity

Группа / механизм Реальный failure mode Альтернативные защиты и риск удаления Решение
Business idempotency: bank intent fingerprint Повтор запроса после lost response; тот же ID с другим содержимым Unique ID предотвращает вторую запись, но не различает повтор и конфликтующий intent. backend/src/modules/banking/bank-cards/application/bank-card-input.ts:74–81, bank-cards.service.ts:76–81, bank-operations.service.ts:216–223 KEEP
Security: refresh-token SHA и password bcrypt Чтение БД не должно раскрывать reusable token/password; rotation CAS CAS не заменяет безопасное хранение. backend/src/modules/auth/application/auth.service.ts:52,110–133,180,204–205 KEEP
Cursor integrity: HMAC + revision/filter binding Подмена cursor или применение к изменённому dataset/filter Ownership проверяет доступ, но не подписанность и согласованность cursor. backend/src/modules/investments/operations/application/brokerage-operations.service.ts:347–388, backend/src/modules/investments/operations/infrastructure/brokerage-operations.repository.ts:128–143 KEEP
Work identity: hash canonical operations intervals Разные диапазоны не должны случайно объединяться; одинаковые intents coalesce Возможна строковая canonical identity, но существующий механизм короткий и связан с durable keys. backend/src/modules/investments/operations/infrastructure/brokerage-operations.repository.ts:254–269 KEEP, нет доказанного выигрыша от замены
Resource identity/revisions: accounts, candles, operations Согласованность metadata и identity текущей read-model Это public/runtime metadata, не development gate. backend/src/modules/investments/brokerage-accounts/brokerage-accounts.service.ts:42–54, backend/src/modules/investments/instruments/infrastructure/candle.repository.ts:41–52, backend/src/modules/investments/operations/application/brokerage-operations.service.ts:238–239 KEEP до установленного contract-safe cut
Freshness metadata/TTL Отсутствие данных, stale и confirmed completeness нельзя смешивать Coverage/revisions защищают другие свойства. backend/src/modules/investments/investment-resource.mapper.ts:31–64,78–88, backend/src/integrations/tbank/tbank-source.policy.ts:1–21 KEEP; удалить только неиспользуемый candleTail key
Data integrity: SQLite integrity/FK checks Повреждение/невалидные связи после migration/restore Unit mocks и successful startup недостаточны. backend/test/bank-cards-durability.cjs:109–118,190–205, backend/test/container-smoke.cjs:58–64 KEEP на соответствующих boundaries
Generated artifacts: local OpenAPI → types Committed types расходятся с предоставленным snapshot TS не сравнивает types с JSON. Native --check покрывает custom script SIMPLIFY implementation, KEEP guarantee
Runtime OpenAPI generator parity Generator отличается от configured app schema Frontend freshness этого не доказывает. backend/test/openapi-contract.e2e-spec.ts:108–156 KEEP
Download integrity: Gitleaks tarball SHA-256 Исполнение не тех bytes скачанного binary HTTPS/version URL не эквивалентны pinned checksum. Frontend/backend verify 52–58, docs/specs security 24–30 KEEP
Image content identity: OCI digest/revision Smoke проверяет другой image, tag изменён, retry скрывает несовпадение Host tests не доказывают bytes опубликованного image. frontend/.gitea/workflows/image.yml:46–62, backend/.gitea/workflows/image.yml:42–55 KEEP
Process identity: release manifest/tag, deployment Git commit Повторная подготовка версии; deployment не из выбранного tagged snapshot Native release-it покрывает лишь часть; рабочий checkout не immutable input. deploy/deploy.sh:26–39 KEEP
Process visual SHA tables Approved export изменён отдельно от approval input Git commit binding может покрывать Git-only delivery; отдельно передаваемые exports — другой риск. specs/openspec/schemas/wealth-ledger-sdd-v2/schema.yaml:322–330, specs/openspec/schemas/wealth-ledger-sdd-v2/templates/design.md:38–61 Условный SIMPLIFY, не безусловное удаление
npm lockfile integrity Package bytes не соответствуют lockfile Стандартный механизм npm, не custom framework KEEP

Самописных self-hash/fingerprint validators для planning Markdown или hash-gated reuse CI результатов не обнаружено. Требования в prose не равны действующей автоматизации.

C. Redundancy Matrix

Фактическая цепочка

Frontend

Developer / AI:
  npm ci
  targeted typecheck/lint/tests
  full verify

pre-commit:
  staged Gitleaks → lint-staged ESLint → deps → build:packages

CI:
  commitlint → history Gitleaks / audit / hook proof
  → full verify

full verify:
  packages → OpenAPI freshness → TS → ESLint → lint-config tests
  → Vitest coverage → Knip → production graph → story graph
  → TS again → application build → Storybook build

Источники: frontend/.ai/conventions/engineering.md:58–66, frontend/.husky/pre-commit:1–3, frontend/.gitea/workflows/verify.yml:17–100, frontend/package.json:26.

Backend

Developer / AI:
  npm ci → targeted checks → full verify → risk-specific suites

CI:
  commitlint → history Gitleaks / audits
  → Prisma generate → verify
  → test:e2e → build again → isolated SQLite suites

Источники: backend/.ai/conventions/engineering.md:58–66, backend/.ai/conventions/testing.md:38–57, backend/.gitea/workflows/verify.yml:84–89, backend/package.json:28–34.

Docs / specs / deploy

  • Docs: Markdown/link lint + local diff check; CI content/security/commit checks.
  • Specs: local git diff --check; CI устанавливает Node dependencies и повторяет эту команду на чистом checkout. Native OpenSpec validation документирована отдельно, но не вызывается этим job.
  • Deploy: отдельный ручной lifecycle и shell harness, вне application CI.

Матрица

Частота ниже — сценарная, не измеренная: один local final verify, один commit и один CI event. Для checks outside этой цепочки указан их фактический trigger.

Mechanism Purpose / consumers Overlap и частота Cost Recommendation Confidence
1. TypeScript Source/tooling diagnostics; local/CI FE: 4 calls в двух verify. BE: по 2 app/test calls; test включает app Повтор compiler invocation; incremental может удешевлять Убрать FE второй call; BE app из aggregate High
2. ESLint Syntax, async, security/style policies FE: 2 full + staged hook; scopes различаются Typed lint всего проекта KEEP full CI; local scoped; staged сохранить High
3. Lint-config tests Scope/exceptions/custom fixers 2 full executions; часть заново доказывает presets Synthetic lintText/config calculations Сократить generic parity; project probes по tooling trigger High
4. Knip Dead exports/dependencies/entries 2 executions; TS не эквивалентен Whole-project analysis KEEP CI; local по соответствующему изменению High
5. Production dependency graph FSD/package/test boundaries, cycles FE: local + hook + CI = 3 Hook дополнительно builds packages Перенести из каждого commit в scoped local/CI High
6. Story reachable graph Catalog не достигает application data 2 executions; base config включён, но graph semantics отличаются Второй graph traversal KEEP: не объединять вслепую High
7. Generated OpenAPI freshness Snapshot ↔ types bytes 2 executions; TS не заменяет Custom temp/subprocess machinery Native --check High
8. Unit/RTL/MSW tests Own behavior, transport/UI results Обычно 2 full runs; local/CI разные trust boundaries Whole suite local Targeted local, full CI High
9. Browser layout Реальная геометрия narrow/wide Два viewport instances на run Chromium/runtime setup KEEP для geometry changes и CI High
10. Coverage FE floor; BE report По одному сбору на full test run Instrumentation/reporting CI report; local targeted без coverage High
11. Application build Emission/bundling/assets BE CI два builds подряд; Docker — отдельная boundary Prisma/Nest/Vite work Убрать same-job rebuild; Docker оставить High
12. Storybook build Catalog bundle Local/CI по одному; app build не заменяет Отдельный bundle CI/catalog-risk scope High
13. SQLite HTTP/integration DB constraints, guards, contract CI 19 functional suites; standalone 20-я performance отдельно Per-suite migration + Jest KEEP independent DB isolation High
14. Runner regression Isolation, cleanup, signals Пять успешных --all + failure/signal paths вручную 95 successful suite executions Representative two-suite runs High facts / Medium cut
15. Historical durability Migration/rollback/restore Schema/data-risk trigger Separate historical build/app runs KEEP risk-triggered High
16. Image smoke Actual image runtime/assets/persistence Publication/manual; host checks не эквивалентны Docker lifecycle KEEP High
17. Publication model test Retry/digest failure branches Только explicit invocation найден Stateful command double, YAML block extraction KEEP focused, не every-change gate Medium
18. Staged secret scan Не допустить secret в commit Каждый FE commit Index scan KEEP; history scan позднее High
19. History secret scan Secrets во всей Git history PR/push/schedule Full-history scan/download KEEP; оптимизировать только по измерениям High
20. Hook security proof Index vs worktree, redaction/fail-closed FE security CI Temp Git repo/real scanner KEEP; разные гарантии с №19 High
21. Dependency audit Known advisories CI; BE runtime/dev thresholds различаются Network/advisory processing KEEP; overlap не доказан одинаковыми properties High
22. Commitlint PR title и retained commits CI 2 invocations; local commit hook дополнительно App repos устанавливают полный manifest для job KEEP policy; не добавлять custom parser High
23. Release preparation guard Branch/tree/version lifecycle Explicit release prepare Несколько Git queries KEEP; preview не считать proof custom hook High
24. Image version/digest binding Tag/package/lock/revision/published bytes Release-tag workflow Metadata/registry checks KEEP release boundary High
25. Scanner checksum Downloaded scanner bytes 4 repo-local security paths Один hash command KEEP High
26. Markdown/link checks Docs syntax/local targets 2 disjoint lint commands/run 50 Markdown files KEEP; не второй custom link checker High
27. git diff --check Working diff whitespace/conflict markers Local useful; docs/specs CI clean checkout малоинформативен Specs CI ещё устанавливает deps KEEP local; удалить пустой CI work High
28. Native OpenSpec validation Schema/change/spec structure Manual; v2 instructions требуют после 7 stages Repeated CLI/context work Только explicitly selected SDD; proportional scope High facts / Medium policy
29. Deploy preflight/lifecycle tests Lock, backup, ordering, failure cleanup Manual deploy/harness Docker doubles/real locks/files KEEP High

Важные разграничения

  • Local и CI не объявлены дубликатами только потому, что запускают одинаковую команду. Сокращается обязательный local scope, CI остаётся независимой проверкой.
  • Production и Storybook dependency-cruiser отличаются tsPreCompilationDeps: true/false: frontend/dependency-cruiser.cjs:78–87, frontend/.storybook/dependency-cruiser.cjs:22. Один простой запуск не доказан эквивалентным двум.
  • OpenAPI generator parity и consumer type freshness проверяют разные отношения.
  • Coverage, browser layout и JSDOM behavior не взаимозаменяемы.

D. SOLID / DRY / KISS / YAGNI Findings

SRP

D1. Test-only orchestration внутри production metadata service

InstrumentMetadataService.read совмещает access, saved lookup, demand start и work lookup, но production callers используют отдельные existing methods.

  • Owner: backend/src/integrations/tbank/instrument-metadata.service.ts:41–63.
  • Production примеры: backend/src/modules/investments/portfolio/application/portfolio.service.ts:122–123,275–283,309–315, backend/src/modules/investments/operations/application/brokerage-operations.service.ts:213–216, backend/src/modules/investments/upcoming-events/upcoming-events.service.ts:200–206.
  • Test consumer: backend/test/tbank-metadata-persistence.e2e-spec.ts:87–382, 38 call sites.

Вывод: убрать совмещённый API после перевода тестов на production-used boundary. Не удалять persistence suite и её concurrency/restart proofs.

D2. Portfolio имеет ложную DI-зависимость и два имени одной операции

  • Неиспользуемый TbankMembershipService constructor dependency: backend/src/modules/investments/portfolio/application/portfolio.service.ts:9–18,45–53.
  • Public request → private queueSnapshot без дополнительной policy: тот же файл, 234–243.
  • Тест обходит public operation и читает private repository: backend/test/tbank-value-history.e2e-spec.ts:99–111,247–256,307–313.

Вывод: один public request, без unused DI; тест получает существующий repository provider напрямую. Не дробить queue/publication lifecycle.

OCP / YAGNI

D3. Plural authenticated-query boundary существует ради теста

frontend/src/shared/api/authenticated-query.ts:15–32,61; единственный consumer — frontend/src/shared/api/authenticated-query.test.tsx:9–23.

Тестовая plural branch содержит один query и берёт [0]. Приложение потребляет singular hook.

Вывод: удалить plural implementation и вариант test matrix. Singular auth gating оставить.

D4. InstrumentSearch сохраняет stock-вариант без product consumer

  • Union contract: frontend/src/features/instrument-search/ui/InstrumentSearch/InstrumentSearch.view.tsx:18–31.
  • Единственный production renderer consumer — BondsPage: frontend/src/pages/bonds/ui/BondsPage/BondsPage.view.tsx:26–113.
  • Stock-конфигурация используется тестом: frontend/src/features/instrument-search/ui/InstrumentSearch/InstrumentSearch.test.tsx:21–29.

Вывод: специализировать current renderer под bond, сохранив debounce, URL/search states и presentation cases. Не объединять bond search со stock screener.

D5. Малые невостребованные элементы поверхности

Элемент Evidence Минимальное действие
history.retry frontend/src/entities/broker-operation/model/useBrokerageOperationHistory.ts:52–61,76; все три VMs его не читают Удалить action; automatic invalid-cursor recovery 37–50 оставить
isFetching input frontend/src/shared/lib/initial-availability.ts:10–16,18–46; не читается Удалить из type, пяти callers и fixtures
membershipWork() backend/src/integrations/tbank/tbank-access.service.ts:90–97; callers не найдены Удалить метод, не одноимённое repository result field
candleTail TTL key backend/src/integrations/tbank/tbank-source.policy.ts:3–8; production references отсутствуют Удалить key; настоящую candle coverage/tail policy оставить
HourlySyncSectionDto backend/src/modules/investments/tbank-sync/tbank-sync.dto.ts:232–250; current problems DTO другой, 271–272 Удалить непривязанный class
Export totalsByCurrency backend/src/modules/investments/portfolio/infrastructure/tbank-portfolio.mapper.ts:56,109–141; используется внутри файла Удалить export, не calculation

ISP / DIP

D6. String DI alias для единственной реализации

  • Structural contract/string token: backend/src/modules/investments/instruments/stocks/application/stock-screener.service.ts:49–63.
  • Единственный useExisting alias: backend/src/modules/investments/instruments/instruments.module.ts:23–25.
  • Alternative implementations/overrides token не найдены.

Вывод: injection по существующему concrete class token. Узкий type можно сохранить через Pick, как уже сделано в backend/src/modules/investments/tbank-connection/tbank-connection.service.ts:11–19.

Это небольшой cleanup, не повод создавать interface.

D7. FormProvider без context consumers

frontend/src/features/auth/ui/AuthForm/AuthForm.tsx:50–86: поля используют локальный methods.register, descendants не используют form context.

Но frontend/.ai/conventions/ui.md:128–129 предписывает FormProvider.

Вывод: сначала сделать existing rule условным по наличию context consumers, затем убрать provider здесь. Не создавать consumers ради оправдания wrapper.

LSP

Для основной business architecture практически неприменим: нет собственной иерархии взаимозаменяемых domain implementations. Concrete providers/repositories — не нарушение LSP или DIP.

DTO inheritance может сохранять Swagger metadata/schema identity — например backend/src/modules/investments/instruments/bonds/presentation/bond.dto.ts:5–16. Удалять пустые DTO subclasses по визуальному сходству нельзя.

DRY

Подтверждены узкие дубли knowledge/assertions:

  • Anonymous /accounts redirect повторён table case и standalone case: frontend/src/app/routes/AppRoutes/AppRoutes.test.tsx:35–61.
  • Failed-image behavior повторяется на page level, хотя сильнее проверен EntryCard: frontend/src/pages/account-events/ui/AccountEventsPage/AccountEventsPage.test.tsx:166–169, frontend/packages/ui/src/EntryCard/EntryCard.test.tsx:24–63.
  • Process authority повторяет approval/cascade/context policies в canonical specs, schemas и config: specs/openspec/config.yaml:55–58, specs/openspec/specs/openspec-authority-and-lifecycle/spec.md:53–80, specs/openspec/schemas/wealth-ledger-sdd-v2/schema.yaml:554–566,625–642.

Не рекомендовано объединять:

  • короткие local money fixtures;
  • worker implementations с разной publication semantics;
  • repo-local release configs;
  • похожие UI/domain states с разными responsibilities.

KISS

D8. Motion dependency ради одного opacity transition

  • Единственный source consumer: frontend/src/app/routes/RouteTransition.tsx:3–30.
  • Единственный caller: frontend/src/app/routes/RouteFallback.tsx:70–81.
  • Dependency: frontend/package.json:52.

Минимум: локальный CSS fade-in с prefers-reduced-motion; сохранить key={pathname} и current mount boundary.

Потенциально удаляется одна runtime dependency. Bundle savings не измерены. Это replacement opportunity, а не unused package в текущем коде.

E. Test Suite Complexity

E1. Setup architecture

Frontend

Общая инфраструктура небольшая:

  • frontend/src/test/query.tsx:5–24: две Query factories, consumers — 7 и 20 test files.
  • frontend/src/test/resource.ts:6–25: одна resource-envelope factory, 20 test consumers.
  • frontend/src/test/setup.ts:13–48: MSW lifecycle, RTL cleanup, auth reset, browser substitutes.
  • frontend/src/test/server.ts:1–7: прямой MSW server.
  • frontend/src/test/storybook.test.tsx:19–57: isolation checks для девяти story modules.

Общего самописного test framework не обнаружено. Размножение локальных render/provider setups не требует автоматически создавать универсальный render helper.

Backend

  • 20 integration suites: 14 AppModule, 5 direct repository/service boundaries, одна migration suite.
  • 14 Nest bootstrap sites, 23 overrideProvider call sites.
  • 4 service factories, 4 deferred definitions, 7 polling helpers.
  • 8 CJS инфраструктурных/helper файлов, перечисленных в B2.

Fresh DB на suite, synthetic credentials и signal cleanup — необходимая стоимость. Не рекомендовано объединять все suites в общую DB ради меньшего setup.

E2. Участки для сокращения

В таблице ниже сокращённые frontend filenames принадлежат указанным page/component directories; backend filenames — src/modules или test по полным путям в разделах D и H.

Набор Что защищает Лишняя подготовка / overlap Что теряется и решение
frontend/src/pages/account-events/ui/AccountEventsPage/AccountEventsPage.test.tsx:13–28,40–61,83–205 Route scope, loading/busy, events/empty/error presentation Два module mocks и пять fake query shapes через as never; соседняя AccountEventsPage.filters.test.tsx:50–108 уже использует MSW Упростить, не удалять outcomes. Network cases — existing MSW; presentation-only — existing view
backend/src/modules/banking/bank-cards/application/get-bank-summary.use-case.spec.ts:11–48 Category mapping, точное 1.23, inconsistent category rejection Fake Prisma tx + настоящий repository, хотя use case вызывает только summaryData() Mock ближайшую repository boundary. DB proof не теряется: fake tx его не обеспечивал
backend/src/modules/investments/portfolio/application/portfolio.service.spec.ts:48–165 Signed nanos, unknown type, cash/quantity/currency mapping Background request, polling и publish.mock.calls для чистого mapper result Первые два cases напрямую через existing mapPortfolio; orchestration/integration proof оставить
backend/src/modules/investments/operations/presentation/brokerage-operations.controller.spec.ts:1–18 Передача args в mock service Prisma mock, casts, assertion прямого вызова; configured HTTP cases покрывают account/query/access Удалить. HTTP proof: backend/test/tbank-ledger-local.e2e-spec.ts:113–137,194–227,336–366, backend/test/all-accounts.e2e-spec.ts:63–104
frontend/src/app/routes/AppRoutes/AppRoutes.test.tsx:55–61 Anonymous redirect Более сильный table case уже на 35–53 Удалить standalone case
frontend/src/pages/account-events/ui/AccountEventsPage/AccountEventsPage.test.tsx:166–169 Image error fallback EntryCard test проверяет также same-source rerender/new-source reset Удалить только error exercise; event→logo/initial assertions оставить
backend/test/tbank-metadata-persistence.e2e-spec.ts:87–382 Reuse, coalescing, privacy, late publication, reopen, batch lookup Сценарии завязаны на production-unused read() Перевести boundary, не удалить suite
backend/test/bank-cards.e2e-spec.ts:371–389,710–753 Rename/default role, durability, FK/unique Три declarations зависят от предыдущих tests и их category state Сделать три cases самодостаточными существующим createCard; не fixture framework
backend/test/sqlite-regression.cjs:20–22,77–91 Runner isolation/cleanup/signals Пять повторов всех 19 functional suites По две representative suites/run; canonical full functional CI оставить
frontend/scripts/test-eslint.mjs:148–202 Все recommended plugin rules включены Exhaustive parity каждой library preset Удалить blanket parity; оставить project exceptions/scopes/custom behavior probes

E3. Assertions против стоимости setup

Наиболее явные несоразмерности:

  • 18 строк controller unit поддерживают исключительно mock delegation.
  • Две mock layers + пять query shapes конкурируют с уже существующей HTTP boundary в одном page area.
  • Пять полных SQLite runs защищают свойства runner, не пять разных domain scenarios.
  • Fake Prisma transaction требуется для двух assertions чистого summary use case.

Большие financial fixtures или длинный crash setup сами по себе не плохи: они могут защищать boundary, недоступную дешёвому test level.

E4. Что оставить

  • Денежные unit cases: signed nanos, значения выше 2^53, currencies, unknown≠zero.
  • Real SQLite CAS/transactions/replay/refund constraints.
  • Session transport/generation fencing.
  • Metadata/candle/operations late-publication и restart/crash cases.
  • Configured HTTP guards/pipes/cookie/status tests.
  • Browser geometry.
  • Historical migration/rollback/restore.
  • Story isolation, когда она доказывает отсутствие application network/storage access.

Примеры: backend/src/modules/banking/bank-cards/domain/bank-card.calculations.spec.ts:46–159, backend/test/bank-cards.e2e-spec.ts:462–523,622–683, backend/test/app.e2e-spec.ts:161–213, backend/test/tbank-operations-persistence.e2e-spec.ts:74–100.

Не установлено, какие tests были созданы исключительно ради coverage. Frontend floors (frontend/vitest.config.ts:19–24) создают constraint, но не доказывают происхождение тестов. Snapshot bloat не найден.

F. AI Agent & Developer Workflow

F1. Bootstrap и full gate обязательны слишком широко

Одинаковое требование в обоих application repos:

Code/dependency change: npm ci, полный npm run verify…

frontend/.ai/conventions/engineering.md:60–62, backend/.ai/conventions/engineering.md:60–62.

Для code-only изменения в уже подготовленном checkout повторная установка не устанавливает новый инвариант. Full frontend verify также запускает browser tests, Knip, оба dependency graphs и Storybook build.

Упростить: bootstrap при новом checkout/изменении lockfile или toolchain; local checks по affected behavior; полный независимый CI gate сохранить.

Потеря — более поздний feedback по незатронутым областям, а не отсутствие merge-time проверки.

F2. Pre-commit собирает packages и проверяет весь graph на каждом commit

frontend/.husky/pre-commit:1–3, frontend/package.json:25,33.

Даже Markdown commit достигает npm run deps, который сначала builds workspaces. UI/icons builds включают Vite и declaration compilation: frontend/packages/ui/package.json:23–25, frontend/packages/icons/package.json:19–21.

Перенести graph check из hook в scoped local/CI. Staged secret scan и staged ESLint оставить.

F3. Mechanical lint policy создаёт искусственную форму кода

  • Вложенные component helpers запрещены custom rule: frontend/eslint-rules.mjs:63–85.
  • Локальные Zod declarations/refinements требуют filename suffix: тот же файл, 20–36.
  • JSX sibling spacing имеет собственный AST traversal/fixer: тот же файл, 104–175.
  • Любой inline JSX callback/conditional prop запрещён: frontend/eslint.config.mjs:273–283.
  • Backend magic-number profile требует имена даже для 0, 1 и bigint literals: backend/test/eslint-config.cjs:78–92.

Часть этих правил защищает readability preferences, а не data flow или runtime correctness. Они увеличивают число именованных declarations, файлов и exceptions.

Упростить blanket restrictions, оставив semantic boundaries: no data fetching во view, безопасные promises, stable query client, доступность, named business policy values. Не заменять custom policy ещё одним инструментом.

F4. Generic skills конфликтуют с локальным соразмерным workflow

  • writing-plans автоматически применим к multi-step requirements: .agents/skills/workflow/writing-plans/SKILL.md:3.
  • Предписывает файл в docs/superpowers/plans: тот же файл, 16–17.
  • Добавляет fixed test/commit structure и Review Focus cases: тот же файл, 43–50,77–87,108–137.
  • TDD применяется к refactoring и требует failing test до любого production code: .agents/skills/workflow/test-driven-development/SKILL.md:18–45.
  • Локальный Test Intent не требует отдельного artifact, исключает trivial wrapper/declaration testing: frontend/.ai/conventions/engineering.md:49–55, backend/.ai/conventions/engineering.md:49–55.

Рекомендация: ограничить применение этих workflows явно выбранной planning/TDD задачей и реальным regression risk. Сохранить reproduction для bug fixes и meaningful proof; не требовать новый тест для удаления unused field/export.

Стандартные OpenSpec skills изменять не требуется.

F5. Opt-in OpenSpec против mandatory audit remediation

Противоречие:

  • Opt-in: specs/AGENTS.md:3–6, frontend/.ai/conventions/engineering.md:11–13, backend/.ai/conventions/engineering.md:11–13.
  • Mandatory audit-derived registry/workflow: specs/openspec/specs/project-foundation/spec.md:9–19.
  • Обязательные snapshots/registry: specs/openspec/specs/audit-remediation-workflow/spec.md:9–49.
  • Docs запрещает размещение audit/research reports: docs/AGENTS.md:12–14.

Упростить действующую process policy, согласовав область действия и место artifacts. Не создавать registry/SDD change автоматически для реализации этого аудита.

F6. Custom SDD workflow остаётся тяжёлым даже без behavioral delta

  • V2: семь planning artifact groups.
  • При skip_specs остаются шесть.
  • Schemas: 885 строк; templates: 335 строк.
  • Семь stage instructions требуют native validation после записи.
  • Apply preconditions перечисляют семь explicit approvals: specs/openspec/schemas/wealth-ledger-sdd-v2/schema.yaml:587–589.

Это не доказательство бесполезности анализа/QA. Однако small docs/tooling change не всегда требует отдельных System Analysis, QA Analysis, Docs Impact и sessions.

Сначала соблюдать opt-in режим. При отдельном пересмотре custom schema — соразмерный набор artifacts по реальному риску. Не удалять approval/data-safety boundaries вслепую.

F7. Specs CI даёт мало гарантии за полноценный install

specs/.gitea/workflows/verify.yml:17–22 → npm ci → git diff --check.

На чистом checkout команда не проверяет committed PR diff, semantic structure или OpenSpec artifacts. Зато npm prepare настраивает hooksPath: specs/package.json:13.

Удалить нынешний пустой job, предварительно установив required-check settings. Существующие native validations запускать для соответствующего изменения; этот аудит не требует нового verifier.

F8. Что не является проблемой

  • AGENTS routers уже ограничивают чтение affected topics.
  • Root и nested conventions не наследуются друг в друга — разные enum/style choices не конфликт.
  • Read-only archives/history не нужно удалять.
  • Повторение краткого stage-specific rule допустимо, если оно нужно executor текущей стадии.
  • Транзитивно избыточные schema edges нельзя удалять только по graph reachability: они могут влиять на CLI context inputs.

Необходимые измерения

Без новых tools достаточно existing CI logs и session usage:

  1. Duration каждой verify stage, cold/warm отдельно.
  2. Время workspace builds в local commands/hook.
  3. Частота local full verify и reinstall.
  4. CI critical path и full-history scan duration.
  5. Token/context volume на обычную задачу против explicitly selected SDD change.
  6. Какие gates действительно находят regressions и на какой boundary.

Сейчас денежная/временная экономия не оценена численно.

G. DELETE / SIMPLIFY / KEEP

DELETE — 18 подтверждённых точек

Удаление подразумевает сохранение указанного более сильного или эквивалентного механизма.

  1. Custom implementation check-openapi.mjs — заменить native check.
  2. Второй TypeScript call в frontend verify.
  3. typecheck:app stage из backend full verify — test typecheck superset оставить.
  4. Повторный backend build перед SQLite в том же CI job.
  5. Невызываемый runtime-check.cjs.
  6. useAuthenticatedQueries и исключительно его test branch.
  7. Неиспользуемый history.retry.
  8. Неиспользуемый isFetching input.
  9. Неиспользуемая Portfolio membership DI dependency.
  10. String alias TBANK_ACCESS — concrete provider оставить.
  11. Невызываемый TbankAccessService.membershipWork.
  12. Неиспользуемый candleTail policy key.
  13. Непривязанный HourlySyncSectionDto.
  14. Неиспользуемый внешний export totalsByCurrency.
  15. Delegation-only brokerage-operations.controller.spec.ts.
  16. Повторный standalone anonymous /accounts route test.
  17. Повторный image-error exercise в AccountEvents page test.
  18. Пустой specs CI verify job — после проверки branch requirements.

Evidence и consequences перечислены в B–E. Это 18 элементов/стадий, а не 18 файлов.

SIMPLIFY

  • Local gate scope и bootstrap frequency.
  • Dependency graph invocation в pre-commit.
  • SQLite runner regression scope.
  • Exhaustive preset parity и mechanical custom lint policy.
  • Metadata tests через production-used methods.
  • Portfolio request/private test access.
  • AccountEvents fake-query setup.
  • Pure mapper/use-case tests.
  • Три order-dependent bank cases.
  • Bond-only InstrumentSearch contract.
  • Motion → CSS.
  • FormProvider rule по наличию consumers.
  • Process specs/SDD activation.
  • Specs hook activation через явное подключение вместо npm lifecycle.
  • Visual SHA tables только там, где exports реально передаются отдельно от Git.

KEEP

  • Финансовая точность и business validation.
  • Intent fingerprint, unique IDs, versions, tombstones, refund transaction.
  • Refresh hashing/CAS, cursor signature/binding.
  • Connection revision и conditional publication.
  • Coverage/completeness/freshness как разные свойства.
  • Independent local/CI trust boundaries.
  • Per-suite DB isolation и crash/durability proofs.
  • Runtime OpenAPI parity и consumer artifact freshness.
  • Scanner checksum, exact image digest/revision checks.
  • Deployment lock, pending marker, backup staging, explicit recovery.
  • Repo-local небольшие configs/helpers вместо нового shared tooling package.
  • Исторические ADR/archives.
  • Реальные browser layout и Storybook isolation guarantees.

Условный кандидат, не DELETE: InvestmentRefreshState имеет ноль production callers, но четыре stories и catalog isolation consumer — frontend/src/features/tbank-connection/ui/InvestmentRefreshState/InvestmentRefreshState.view.tsx:1–61, frontend/src/features/tbank-connection/ui/InvestmentRefreshState/InvestmentRefreshState.stories.tsx:1–52, frontend/src/test/storybook.test.tsx:11,38. Его удаление уберёт catalog artifact; намерение owner не установлено.

H. Top 20 Complexity Reduction Opportunities

Порядок — по ожидаемому сокращению engineering overhead. Экономия указана в механизмах/запусках, не в выдуманных секундах.

Сокращённые filenames в таблице однозначно относятся к полным путям, указанным в B–F.

№ Файлы и доказательства Текущий механизм → минимальное изменение Что перестанет работать / ожидаемая экономия Риск · Confidence
1 FE/BE .ai/conventions/engineering.md:58–66 npm ci + full verify для любого code change → bootstrap по изменению inputs, local affected checks, full CI Исчезнет обязательный ранний full-project proof; меньше reinstall/full suites на малую задачу Medium · High
2 backend/test/sqlite-regression.cjs:20–22,77–91; backend/test/sqlite.cjs:10–17 Пять successful --all runs → по две representative suites Теряются повторные business runs внутри runner proof; 95 → 10 successful suite executions, canonical full CI остаётся Medium · High facts
3 frontend/package.json:26; frontend/tsconfig.app.json:17, frontend/tsconfig.node.json:12 Два TS calls с noEmit configs → один Второй call не выполняется; минус один compiler invocation/full verify Low · High
4 backend/package.json:22–34; typecheck configs app 7–8, test 7–8 App subset + test superset → test superset в aggregate Отдельная маркировка app-stage failure; минус один nonincremental TS pass Low · High
5 backend/.gitea/workflows/verify.yml:84–89; package 28,34 Verify build, затем E2E build → после verify existing node test/sqlite.cjs --all E2E stage перестанет пересобирать уже готовый output; standalone entrypoint сохранить Low · High
6 frontend/.husky/pre-commit:1–3; package 25,33; UI/icons package builds Whole graph + workspace build на каждый commit → local/CI graph Потеря hook-time graph feedback; минус один workspace build/graph traversal на commit Low–Medium · High
7 frontend/scripts/check-openapi.mjs:1–45; CLI 125–134 Custom temp/subprocess compare → openapi-typescript … -o … --check Ничего из freshness guarantee; 45 строк custom orchestration заменяются CLI option Low · High; native check executed
8 specs/package.json:9,13; specs/.gitea/workflows/verify.yml:17–22 Install + clean working diff check → удалить пустой job Теряется малоинформативный check status; минус job/install/hooks side effect Low после branch-setting review · High
9 FE eslint-rules.mjs:1–178; test-eslint.mjs:148–202,290–339 Mechanical AST policy + exhaustive preset parity → оставить semantic boundaries и custom-exception probes Меньше формальных style/shape guarantees; меньше custom rule/test maintenance Medium · High facts
10 frontend/src/app/routes/RouteTransition.tsx:3–30; package 52; caller RouteFallback.tsx:70–81 Motion для fade-in → CSS с reduced motion Library-driven fade-in заменяется; сохранить key/mount semantics; −1 runtime dependency Low–Medium · High
11 Metadata service 45–61; persistence tests 87–382; repository 159–170 Test-only read/start API → tests через request/savedMany, затем удалить API/work accessor Исчезнет unused combined operation; реальные reuse/race/restart proofs сохранить Medium · High
12 frontend/src/shared/api/authenticated-query.ts:15–32,61; test 9–23 Unused plural generic hook → удалить и test-only variant Multi-query convenience без product consumers; меньше generic surface/test matrix Low · High
13 Portfolio service 45–53,234–243; value-history tests 99–111,247–256 Unused DI + public/private alias → один request, прямой provider access в tests Private test route исчезнет; queue/publication не меняется Low · High
14 History hook 52–61,76; initial availability 10–46 Невостребованное action и непрочитанный input → удалить Никакой used behavior; automatic cursor recovery/wait budget остаются Low · High
15 InstrumentSearch view 18–31; BondsPage view 26–113; test 21–29 Stock/bond renderer при одном bond consumer → bond-specific current contract Исчезнет test-only stock mode; current product search не меняется Low–Medium · High
16 AccountEvents test 13–28,40–205; filters test 50–108 Fake hooks/query shapes → existing MSW/view boundaries Исчезнут internal-hook assertions и пять fake shapes; visible outcomes сохранить Medium · High
17 Summary spec 11–48; portfolio spec 48–165; mapper 33–138 Fake tx/background work ради чистого result → ближайший existing owner Unit не будет exercise’ить orchestration; configured DB/publication proofs остаются Low–Medium · High
18 Controller spec 1–18; route test 35–61; page image test 166–169 Delegation-only и одинаковые assertions → удалить узкие дубли Только internal-call/repeated fallback assertions; более сильные HTTP/route/EntryCard proofs остаются Low · High
19 backend/test/bank-cards.e2e-spec.ts:371–389,710–753; setup 86–105 Три tests с implicit prerequisites → собственный arrange через createCard Теряется зависимость от suite history, не business guarantee; targeted tests дешевле понимать Low–Medium · High
20 Specs AGENTS 3–6; foundation 9–19; remediation 9–49; writing-plans 16–17,77–87; TDD 18–45 Mandatory artifacts/SDD/TDD rules конфликтуют с opt-in/direct work → уточнить existing activation/scope Не будет автоматических planning/registry artifacts для каждой audit-derived правки; меньше context/approval loops Medium · High

Отдельные дешёвые dead-surface cuts из G можно делать при связанном изменении owner. Ради удаления одного export не нужен самостоятельный архитектурный проект.

I. Minimal Engineering Baseline

Это предложение сократить существующий workflow, не новая convention или набор инструментов.

Local development

Оставить:

  • Активировать local Node version.
  • Bootstrap при новом checkout или изменении dependency/toolchain inputs.
  • Targeted test на cheapest reliable boundary.
  • Relevant typecheck/lint.
  • Semantic review affected behavior и git diff --check.
  • Risk-triggered DB/browser/contract/durability proof.

Убрать обязательный npm ci и весь full-project gate после каждого code-only изменения.

Full verify остаётся доступным локально, но его обязательная независимая граница — CI.

Pre-commit

Оставить frontend:

  1. Staged Gitleaks с redaction/fail-closed.
  2. Staged ESLint.
  3. Commit-msg policy при подключённом hook.

Перенести whole dependency graph и workspace builds из pre-commit.

Specs commit-msg можно оставить; подключение hooks сделать явным вместо автоматического prepare. Это не отменит уже записанный hooksPath само по себе.

CI

Frontend

Оставить:

  • Native OpenAPI freshness.
  • Один TypeScript pass.
  • Один ESLint run.
  • Behavioral tests + coverage.
  • Knip.
  • Production и Storybook graph checks с сохранением различающихся semantics.
  • Application и catalog builds.
  • Security и commit policy.

Lint-config tests сократить до project-specific scopes/exceptions/custom behavior; изменение tooling требует соответствующего focused proof.

Backend

Оставить:

  • Generated Prisma client до checks.
  • Один full-source/test typecheck.
  • ESLint.
  • Unit suite.
  • Один build.
  • Изолированные functional SQLite suites, включая runtime OpenAPI contract.
  • Security и commit policy.

После уже выполненного build использовать existing runner без повторного build. Performance и historical durability остаются отдельными risk-triggered командами.

Docs / specs

  • Docs Markdown/link lint сохранить.
  • Working-diff check оставить локально.
  • Specs пустой verify job удалить после проверки branch requirements.
  • Native OpenSpec validation использовать по изменению schema/spec/change и только в выбранном SDD scope.
  • Security/release/commit mechanisms сохранить.

Testing layers

Минимально достаточные существующие layers:

  1. Pure domain/unit — деньги, normalizers, mappers.
  2. RTL/MSW — UI, forms, route/session/transport behavior.
  3. Configured HTTP + real SQLite — pipes, guards, transactions, CAS, persistence.
  4. Browser — geometry/lifecycle, которые JSDOM не доказывает.
  5. Image/historical/deploy — соответствующие packaging/data-recovery risks.

Удалять одинаковый proof, а не целый layer.

Architecture constraints

Оставить:

  • Production не зависит от test code.
  • Package не зависит от app.
  • FSD public API/layer/cycle boundaries.
  • Presentation не выполняет application fetching.
  • Story graph не достигает application data.
  • Pure domain не зависит от persistence/transport.

Не добавлять interface перед каждым concrete provider, общий worker framework или новые архитектурные checks.

AI instructions

Оставить:

  • Local AGENTS router.
  • Owner/callers/invariants до изменения.
  • Сохранение чужих изменений.
  • Context по affected topics.
  • Meaningful verification evidence.
  • Opt-in OpenSpec.

Сократить:

  • Universal plan-file creation.
  • Новый failing test для каждого mechanical refactor.
  • Mandatory full reinstall/full verify на любую правку.
  • Blanket FormProvider/VM/helper/style mechanics без current responsibility.
  • Повторные process authority descriptions и обязательные artifacts с конфликтующим размещением.

Итог

Наиболее выгодный путь: сократить обязательную частоту и scope проверок → удалить доказанную невостребованную поверхность → упростить test boundaries → согласовать процессную authority.

Не требуется менять финансовую архитектуру, добавлять инструменты или объединять независимые repositories.

Net: точный line delta не подготовлен; подтверждена замена 45-строчного OpenAPI checker native CLI, 18 точек удаления и возможность убрать одну runtime dependency после CSS-замены. Экономия времени и токенов требует измерений.