Перейти к основному содержимому

План завершения архитектурной миграции BELF

Архив. Этот план заменён docs/quality-gates-refactor-plan.md как единственным исполняемым документом для текущего цикла. Он сохранён только как исторический контекст и не должен использоваться как источник параллельных задач или критериев готовности.

1. Назначение

Этот документ описывает оставшиеся работы после миграции home, calculator, navigation и layout. План рассчитан на последовательное исполнение разработчиком или AI-агентом.

Цель: перевести partners и careers на локальное владение компонентами и CSS Modules, перенести общий контент из src/data в src/shared/data, удалить composition-файлы и завершить документацию без изменения интерфейса и поведения.

План сначала утверждается, затем исполняется строго по этапам. Commit, push и deploy в него не входят.

2. Зафиксированное текущее состояние

  • Home, calculator, navigation и общий footer уже используют CSS Modules.
  • npm run quality проходит: 11 unit/component tests и 72 Playwright tests.
  • Visual regression покрывает открытый и закрытый navbar на трёх маршрутах и шести viewport.
  • partners подключает шесть CSS-файлов через src/styles/pages/partners.css.
  • careers подключает пять CSS-файлов через src/styles/pages/careers.css.
  • PartnersOverviewSections.css и PartnersProgramSections.css владеют сразу несколькими секциями и должны быть разделены по фактическим владельцам.
  • CareersSections.css владеет несколькими секциями и также должен быть разделён.
  • Общие assets, contacts, modules, navigation и pricing находятся в src/data и импортируются из pages, components и features.
  • Рабочее дерево уже содержит пользовательские и ранее выполненные изменения. Они не должны быть сброшены, перезаписаны или включены в механическую очистку.

3. Неприкосновенные ограничения

Во время миграции запрещено:

  • менять тексты, DOM-порядок, маршруты, hash-якоря и SEO;
  • менять размеры, отступы, цвета, typography, breakpoints и анимации;
  • менять navbar, его прозрачность, контраст, overlay и focus management;
  • менять формулы calculator и содержимое mailto-заявок;
  • обновлять существующие screenshots для сокрытия расхождений;
  • одновременно мигрировать несколько несвязанных секций;
  • добавлять !important, отключения линтеров или ослаблять тесты;
  • создавать пустые архитектурные директории «на будущее»;
  • добавлять новые зависимости без доказанной необходимости;
  • выполнять commit, push или deploy без отдельного запроса владельца;
  • удалять или форматировать несвязанные пользовательские изменения.

Допустимы только архитектурные изменения с нулевой визуальной и поведенческой дельтой.

4. Целевая структура

src/
pages/
partners/
PartnersPage.tsx
data.ts
partners-utilities.css
sections/
PartnersHero/
PartnershipIntroSection/
PartnerTypesSection/
PartnerBenefitsSection/
ClientsRegistry/
CommissionSection/
PartnershipRulesSection/
TerritorySection/
InternationalSection/
PartnershipProcessSection/
PartnershipApplicationSection/
components/
ApplicationForm/
PartnersFooter/

careers/
CareersPage.tsx
data.ts
careers-utilities.css
sections/
CareersHero/
CandidateProfileSection/
ResponsibilitiesSection/
TrainingSection/
RequirementsSection/
ResumeSection/
components/
ResumeForm/
CareersFooter/

shared/
data/
assets.ts
contacts.ts
modules.ts
navigation.ts
pricing.ts
utils/

Каждая папка секции создаётся только в момент переноса реального компонента. Общие page-utilities остаются обычным CSS, импортируемым напрямую entrypoint, поскольку их классы намеренно используются несколькими секциями одной страницы. Все остальные стили принадлежат компоненту через *.module.css.

5. Gate 0 — неизменяемый baseline

Перед первой кодовой правкой:

git status --short
npm run quality
git diff --check

Дополнительно сохранить:

  • список текущих изменённых и untracked-файлов;
  • число существующих snapshot-файлов;
  • screenshots /partners/ и /careers/ на шести viewport;
  • результаты прямого открытия обоих URL;
  • текущие href обеих mailto-форм для фиксированных входных данных.

Gate 0

  • npm run quality — PASS;
  • все 72 существующих Playwright tests — PASS;
  • git diff --check — PASS;
  • baseline не создаётся поверх красного теста;
  • исходное dirty-состояние записано в статус миграции.

При FAIL выполнение останавливается до установления причины.

6. Этап 1 — усилить защиту до рефакторинга

Текущие visual tests проверяют navbar в пределах viewport и не гарантируют идентичность нижних секций. До переноса CSS добавить:

  1. Full-page visual baseline для /partners/ и /careers/ на всех шести Playwright projects.
  2. Проверку отсутствия horizontal overflow после прокрутки всей страницы.
  3. Проверку отсутствия pageerror и console.error на обоих маршрутах.
  4. Component tests для ApplicationForm и ResumeForm:
    • обязательные поля;
    • прежние subject/body;
    • кодирование кириллицы;
    • использование единого contacts.emailHref.
  5. Поведенческую проверку client registry: loading, данные и ошибка загрузки.

Новые baseline создаются только один раз до миграции и просматриваются вручную. После начала этапа 2 любые --update-snapshots запрещены.

Gate 1

  • новые тесты краснеют при намеренной локальной поломке и проходят после её отмены;
  • 12 full-page baseline существуют и визуально соответствуют текущему сайту;
  • npm run quality — PASS;
  • существующие 72 snapshots не изменены;
  • git diff --check — PASS.

7. Этап 2 — миграция partners

Работать строго в указанном порядке. После каждого пункта выполнять локальный gate и не переходить дальше при visual diff.

2.1 Page utilities

  • Перенести только реально общие классы из PartnersShared.css в partners-utilities.css.
  • Подключить utilities напрямую из src/app/partners.tsx.
  • Не переносить в utilities стили, используемые одним компонентом.

2.2 Overview

  • Разделить PartnersOverviewSections.tsx на PartnersHero, PartnershipIntroSection, PartnerTypesSection и PartnerBenefitsSection.
  • Разделить PartnersOverviewSections.css на четыре CSS Module без изменения деклараций и порядка media queries.
  • Обновить PartnersPage.tsx как тонкую композицию.

2.3 Registry

  • Перенести ClientsRegistry.tsx и ClientsRegistry.css в одну папку.
  • Сохранить загрузку partners/clients.json, состояния loading/error и текущую таблицу без изменения содержимого.

2.4 Program sections

Последовательно выделить из PartnersProgramSections.css стили владельцев:

  1. CommissionSection;
  2. PartnershipRulesSection;
  3. TerritorySection;
  4. InternationalSection;
  5. PartnershipProcessSection;
  6. PartnershipApplicationSection.

Правило: selector переносится к компоненту, JSX которого содержит целевой className. Общие селекторы сначала получают доказанное общее назначение; копирование одного правила в несколько модулей без объяснения запрещено.

  • Перенести ApplicationForm с собственным CSS Module и тестом.
  • Перенести PartnersFooter с собственным CSS Module.
  • Удалить src/styles/pages/partners.css только когда его последний import исчез и rg не находит ссылок на старые CSS.

Локальный gate после каждой partners-секции

npm run format:check
npm run lint
npm run lint:css
npm run typecheck
npm run test
npm run build
npx playwright test tests/e2e/navigation.spec.ts --grep "partners"

Также запускать full-page visual test /partners/ на шести viewport без обновления baseline.

Gate 2

  • /partners/ открывается напрямую;
  • все anchors и CTA ведут на прежние цели;
  • registry показывает те же данные и состояния;
  • application mailto совпадает побайтно после URL-decoding;
  • нет horizontal overflow, console errors и layout shift;
  • navbar tests и full-page screenshots — PASS на шести viewport;
  • src/styles/pages/partners.css и старые component CSS удалены;
  • PartnersPage.tsx содержит только композицию секций;
  • npm run check — PASS.

8. Этап 3 — миграция careers

Порядок:

  1. Общие классы CareersShared.csscareers-utilities.css, прямой import из src/app/careers.tsx.
  2. CareersHero → отдельная папка и CSS Module.
  3. Разделить CareersSections.css между:
    • CandidateProfileSection;
    • ResponsibilitiesSection;
    • TrainingSection;
    • RequirementsSection.
  4. ResumeSection и ResumeForm разнести на section и внутренний component, каждому дать собственный CSS Module.
  5. CareersFooter → отдельная папка и CSS Module.
  6. Удалить src/styles/pages/careers.css после удаления последнего import.

Сохранить текущие input names, required-атрибуты, accept для файла, тексты, mailto subject/body и anchors.

Локальный gate после каждой careers-секции

Использовать тот же статический набор команд, затем:

npx playwright test tests/e2e/navigation.spec.ts --grep "careers"

И отдельно full-page visual test /careers/ на шести viewport.

Gate 3

  • /careers/ открывается напрямую;
  • все CTA и #resume работают;
  • resume form имеет прежнюю клавиатурную доступность и mailto;
  • выбранный файл отображается как раньше;
  • нет horizontal overflow и console errors;
  • navbar tests и full-page screenshots — PASS на шести viewport;
  • src/styles/pages/careers.css и старые component CSS удалены;
  • CareersPage.tsx остаётся тонкой композицией;
  • npm run check — PASS.

9. Этап 4 — перенос общего контента

Этот этап начинается только после зелёных Gates 2 и 3.

Переносить по одному файлу:

  1. assets.ts;
  2. contacts.ts;
  3. navigation.ts;
  4. modules.ts;
  5. pricing.ts.

Для каждого файла:

  • перенести его без изменения exported values и public types;
  • заменить потребителей на alias @/shared/data/<name>;
  • выполнить rg по старому пути;
  • запустить typecheck, unit tests и build;
  • для contacts дополнительно проверить navbar, footers и обе формы;
  • для modules/pricing дополнительно прогнать calculator tests;
  • удалить исходный файл только после нулевого числа старых импортов.

После последнего переноса добавить ESLint boundary, запрещающий новые импорты из @/data/* и зависимости shared от pages, features или app. Barrel export не создавать, если он скрывает владельца или создаёт циклическую зависимость.

Gate 4

  • rg не находит импортов из src/data;
  • директория src/data отсутствует либо пуста и удалена;
  • значения контактов, assets, navigation, modules и pricing не изменились;
  • calculator unit tests — PASS;
  • navbar, оба footer и обе формы используют один contacts source;
  • циклических импортов нет;
  • npm run quality — PASS;
  • full-page visual baseline — PASS без обновления.

10. Этап 5 — очистка и документация

  • Удалить только доказанно неиспользуемые CSS и exports.
  • Проверить отсутствие пустых папок и orphan CSS Modules.
  • Обновить README.md, CONTRIBUTING.md, docs/architecture.md и файл статуса.
  • Добавить фактическое дерево partners, careers, shared/data.
  • Удалить из документации слова «legacy» только после реального удаления composition-файлов.
  • Проверить инструкции запуска с чистой установкой через npm ci без удаления текущего node_modules и без модификации lockfile.

Gate 5

  • каждый *.module.css импортируется ровно своим владельцем;
  • нет src/styles/pages/partners.css и careers.css;
  • глобальный CSS содержит только tokens, reset, fonts и документированные utilities;
  • README и architecture docs соответствуют фактическому дереву;
  • нет несуществующих команд или путей в документации;
  • npm run quality — PASS;
  • git diff --check — PASS.

11. Финальный quality gate

Работа завершена только при одновременном PASS всех пунктов.

Статика

  • npm run format:check;
  • npm run lint;
  • npm run lint:css;
  • npm run typecheck;
  • npm run test;
  • npm run build;
  • npm run quality;
  • git diff --check.

Архитектура

  • PartnersPage и CareersPage — тонкие композиции;
  • каждая смысловая секция имеет собственную папку;
  • локальный компонент импортирует собственный CSS Module;
  • отсутствуют page composition CSS;
  • отсутствуют orphan CSS и неиспользуемые exports;
  • общий контент находится в shared/data и имеет один источник истины;
  • page-specific data остаются рядом со своей страницей;
  • ESLint проверяет направление импортов;
  • не добавлены отключения линтеров, новые !important или зависимости.

Поведение

  • /, /partners/, /careers/ открываются напрямую;
  • navigation и все hash-якоря работают;
  • navbar сохраняет фон, opacity, backdrop-filter и контраст;
  • mobile overlay полностью перекрывает viewport;
  • обе формы создают прежние mailto-ссылки;
  • registry загружает прежние данные;
  • calculator выдаёт прежние результаты;
  • нет pageerror, console.error, horizontal overflow и layout shift.

Визуальная идентичность

  • существующие navbar snapshots проходят для 3 маршрутов × 6 viewport;
  • full-page snapshots проходят для partners и careers × 6 viewport;
  • baseline не обновлялся после начала миграции;
  • representative mobile, tablet и desktop screenshots просмотрены вручную;
  • тексты, размеры, цвета, spacing, typography и breakpoints не изменились.

Git и CI

  • исходные пользовательские изменения сохранены;
  • deploy по-прежнему зависит от quality/e2e;
  • commit, push и deploy не выполнялись без отдельного запроса;
  • итоговый отчёт содержит git status --short.

12. Стоп-условия

Текущая итерация немедленно останавливается, если:

  • screenshot отличается от baseline;
  • изменилась computed style, геометрия или DOM-последовательность;
  • появился pageerror, console.error или horizontal overflow;
  • перестал работать URL, anchor, navbar, registry или форма;
  • тест становится зелёным только после ослабления assertion;
  • требуется !important или изменение CSS declaration для компенсации каскада;
  • обнаружено пересечение с неизвестным пользовательским изменением.

При остановке snapshot не обновляется. Сначала фиксируются точный selector, computed property и причина дельты, затем исправляется архитектурная ошибка и повторяется полный gate текущего этапа.

13. Формат отчёта после этапа

Этап
- какие владельцы и файлы мигрированы;
- какие старые файлы доказанно удалены;
- какие обязанности разделены.

Проверки
- каждая команда: PASS/FAIL;
- маршруты и viewport;
- количество unit/e2e tests;
- visual comparison без update: PASS/FAIL.

Визуальная дельта
- отсутствует;
- либо точная причина и статус остановки.

Риски и остаток
- что ещё не мигрировано;
- какие compatibility utilities временно сохранены.

Git
- status;
- commit/push/deploy status.