Files
easy-png-tools2/docs/plan-codebase-quality.md
T

28 KiB
Raw Blame History

План: линтеры, тесты и качество кодовой базы

Статус: draft — на ревью.

Источник: docs/backlog.md, аудит конфигурации web/, e2e-тестов и инфраструктурных скриптов. До подтверждения плана кодовые изменения не выполняются.

Цель: сделать качество кодовой базы воспроизводимым, убрать ложную «зелёность» проверок, стабилизировать тестовые контракты и только после этого расширять автоматические правила.

1. Границы и принципы

  1. Сначала stabilизировать существующие проверки и тестовые контракты, а не добавлять новые сложные lint-правила.
  2. Старый UI (src/lib/v1/, src/routes/v1/, app_v1.css) больше не является обязательной поддерживаемой версией: текущий production на корневых маршрутах уже достаточно стабилен для использования.
  3. Пока /v1 существует, старый и новый UI остаются изолированными. Не тратить время на исправления, тесты и документацию, которые нужны только v1.
  4. Удаление v1 — реальный следующий cleanup-задача (Q3). Не ждать, пока legacy начнёт мешать, и не тратить время на его поддержку; если задача упирается в v1, Q3 выполняется перед ней.
  5. core/ и theme/ — общие модули. Их изменения проверяются unit-тестами и smoke-сценариями для обеих веток, пока ветка v1 не удалена.
  6. Изменения делаются небольшими атомарными частями, в соответствии с AGENTS.md.
  7. Каждый новый lint-rule сначала появляется в report-only/warn-only режиме, получает fixtures и тесты, и только после очистки baseline становится blocking.
  8. Детали реализации правил остаются в web/eslint-plugins/README.md; AGENTS.md содержит краткие обязательные политики, понятные агенту без дополнительных поисков, и ссылки на подробные документы.

Политика legacy v1

  • v1 можно удалить; это разрешённый cleanup, а не обязательная работа перед каждой задачей.
  • Не добавлять новые v1-фичи, не чинить v1-баги и не расширять v1-тесты без прямой зависимости текущей задачи от legacy-кода.
  • Если задача требует изменений в v1 или общих модулях, сначала выполнить Q3, если это не противоречит атомарности текущей задачи, и продолжить работу только с production-веткой.
  • Если порядок работ изменится, Q3 можно перенести как целый cleanup, но не возвращать постоянную поддержку v1.
  • После удаления проверить маршруты, импорты, i18n, тесты, документацию и конфигурацию lint; старые ссылки не оставлять как «источник совместимости».

2. Что уже есть и что мешает

  • i18n/dict-consistency реализован и подключён как warn-only (web/eslint.config.js:177-188). Проверки ключей, пустых значений и placeholders есть, но текущий baseline ещё содержит расхождения.
  • lint:all запускает ESLint, Stylelint и token audit (web/scripts/lint-all.mjs:31-54), но не запускает typecheck, unit-тесты, Prettier или Playwright.
  • CI workflow сейчас проверяет только production build (.github/workflows/deploy.yml:40-53).
  • В e2e есть фиксированные числа, точные тексты, CSS-классы и alt-селекторы: web/e2e/catalog.spec.ts:4-55, web/e2e/text-and-verdicts.spec.ts:52-101.
  • Backlog и реализация расходятся по генераторам: продуктовая заметка требует автоматический запуск без Generate-кнопки (docs/backlog.md:115-122), а тест ожидает кнопку (web/e2e/generators.spec.ts:8-16).
  • resize-png и crop-png начинают с нулевых размеров и требуют отдельного продуктового решения (web/src/lib/registry/geometry.ts:191-297).

3. Этапы выполнения

Q0. Зафиксировать baseline и синхронизировать документацию

Статус: готов к ревью. Оценка: S. Зависимости: нет.

  • Проверить фактические команды и зафиксировать их в quality-gate документации.
  • Вынести расширенный workflow агента в docs/agent-workflow.md, оставив в AGENTS.md только обязательные инварианты и ссылки.
  • Обновить docs/backlog.md:
    • отметить dictionary linter как реализованный, но не доведённый до zero-warning;
    • убрать противоречие по кнопке Generate;
    • синхронизировать числа инструментов и тестовых сценариев.
  • Восстановить или исправить ссылку на раздел G в docs/checklist-manual-testing.md.
  • Убрать устаревшее утверждение про hardcoded debt в kit из AGENTS.md, если оно больше не соответствует коду.
  • Перенести явно устаревшие docs/analysis.md и docs/sorting-backend.md в docs/archive/, добавить даты архивирования и удаления через 30 дней.
  • Создать docs/README.md как индекс активных документов и карту источников истины; подробные правила не дублировать в корневых файлах.

Готово, когда: один документ описывает текущие команды, актуальный baseline и все известные test.fixme имеют ссылки на зарегистрированный баг.

Q1. Единый quality gate и CI

Статус: готов к ревью. Проверено: pnpm verify проходит; E2E оставлен отдельным non-blocking job. Оценка: S–M. Зависимости: Q0.

Добавить read-only verify-команду, которая запускает:

pnpm --dir web check
pnpm --dir web test
pnpm --dir web test:rules
pnpm --dir web lint:all
pnpm --dir web exec prettier --check .
pnpm check:docs
pnpm --dir web build

E2E оставить отдельным тяжёлым гейтом:

pnpm --dir web test:e2e
  • Не дублировать вручную аргументы ESLint/Stylelint в нескольких скриптах; оркестратор должен вызывать package scripts или единый общий модуль.
  • Описать фактические команды и semantics ошибок/warnings в docs/quality-gates.md; здесь нужна точная процедура, а не длинный дубль в AGENTS.md.
  • На первом этапе явно разделить errors и warnings.
  • После очистки i18n baseline добавить строгий режим --max-warnings=0.
  • Добавить отдельный workflow для pull request: typecheck, unit, rule-тесты, lint, format и build.
  • E2E сначала запускать отдельным job; сделать его blocking после закрытия известных ошибок и стабилизации baseline.

Готово, когда: одна команда воспроизводит все быстрые проверки, а deploy не может пройти при type/unit/lint/build-ошибке.

Q2. Политика i18n и zero-warning baseline

Статус: готов к ревью. Проверено: i18n lint даёт 0 warnings, rule-тесты и полный pnpm verify проходят. Оценка: M. Зависимости: Q0, Q1.

  • BASE_LOCALE — единственный источник registry-English fallback для tools.*.title и tools.*.description; остальные локали требуют физические ключи.
  • Legacy tools.*.params исключён pattern-based policy до отдельной очистки мёртвого словаря; пустые значения и placeholders не подавляются.
  • Исправлены три реальных RU option-label gaps и удалены неиспользуемые legacy option-группы из ru.ts.
  • Исправлен tie-break placeholder parity: при равенстве голосов выбирается BASE_LOCALE.
  • lint-all запускает ESLint с --max-warnings=0; token audit пока оставляет 4 unused-token warnings отдельным debt.
  • Plural-формы остаются отдельной задачей после Q2 и не смешиваются с этим этапом.

Q3. Удалить v1 (следующий cleanup)

Статус: следующий шаг после Q2. Оценка: M. Зависимости: Q0, Q1, Q2.

  • Удалить web/src/routes/v1/**, web/src/lib/v1/**, app_v1.css, v1-specific i18n/tests и оставшиеся v1-ссылки.
  • Убрать v1 из isolation/lint/test-конфигураций и документации; не оставлять исключения только ради удалённого кода.
  • Обновить shared core/theme проверки: после удаления v1 проверять только production-потребителя.
  • Прогнать pnpm verify и отдельный e2e smoke production-маршрутов.
  • Не выполнять удаление как побочный эффект другого PR; это отдельная атомарная задача.

Готово, когда: production build и verify зелёные, v1-маршруты и файлы отсутствуют, а ссылки и конфиги не содержат legacy-путей.

Q4. Тестовый контракт e2e

Оценка: M. Зависимости: Q0–Q3, решение по i18n и генераторам.

  • Основной locator: role, aria-*, getByLabel, stable id/href.
  • data-testid использовать только там, где семантического API недостаточно: source, result, empty-state, download.
  • Убрать зависимость от:
    • абсолютных чисел TOTAL/GROUPS;
    • точного количества fuzzy-search результатов;
    • внутренних CSS-классов;
    • img[alt="Result image"];
    • полных локализованных предложений.
  • Для каталога проверять конкретные инструменты и согласованность отображённых карточек общему числу, а не фиксированное число 122.
  • Централизовать helpers для открытия инструмента, загрузки, результата, ошибки и download.
  • Зафиксировать locator/i18n/fixture/fixme-политику в docs/testing-strategy.md; детали конкретных тестов оставлять рядом с ними.
  • В unit-тестах проверять ключи через t() и i18n helpers. В e2e проверять поведение и отдельный i18n smoke; data-i18n-key добавлять только при реальной необходимости тестировать ключ в DOM.
  • Убрать нестандартные символы из поведенческих ожиданий (→, длинные тире, ×); названия тестов не переписывать механически без необходимости.
  • Исправить stale-проверки темы, source-locator и locale assertions.

Готово, когда: изменение формулировки, класса или порядка элементов не ломает поведенческий тест без изменения пользовательского контракта.

Q5. Закрыть известные preview-баги

Оценка: M. Зависимости: Q4.

  1. Выбрать поведение resize-png и crop-png при загрузке изображения: source-aware defaults, осмысленные статические defaults или отдельный автоматический repair.
  2. Исправить registry/schema и только после этого снять соответствующие test.fixme.
  3. Зафиксировать auto-run для генераторов и переписать e2e под фактическое автоматическое поведение; кнопку Generate не добавлять без отдельного UX решения.
  4. Определить семантику Reset: очистка результата, немедленный повторный run или временное отключение auto-run.
  5. Перенести проверку локализованной ошибки на независимый детерминированный invalid-input сценарий.

Готово, когда: каждый known issue либо исправлен и покрыт зелёным тестом, либо явно перенесён в отдельную продуктовую задачу с владельцем и критерием.

Q6. Расширение unit и browser-покрытия

Оценка: M–L. Зависимости: Q4, Q5.

Сначала:

  • executor и worker/fallback;
  • FileResult, ZIP и download;
  • debounce и auto-run;
  • output MIME/quality;
  • malformed и special PNG fixtures: CRC, truncated, palette, 16-bit;
  • smoke всех типов инструментов из registry.

Затем отдельно:

  • component-тесты SchemaToolView, SchemaPreview и schema fields;
  • browser matrix, mobile viewport и visual snapshots;
  • coverage thresholds.

Не применять один одинаковый smoke-сценарий к image-, text-, generator- и file-result-инструментам.

Q7. Укрепление lint-инфраструктуры

Оценка: M. Зависимости: Q1, Q2, Q3.

  • Очистить или использовать unused design tokens; после очистки решить, должен ли unused audit быть fail-режимом.
  • Добавить тесты для token audit и PostCSS HCT-плагина.
  • Проверить/исправить расхождение документации isolation rule и реально передаваемых options.
  • Покрыть базовым JS recommended сам код ESLint-плагинов и lint-скриптов.
  • Отдельно решить, должен ли обычный CSS проходить проверку undefined tokens и hardcoded colors наравне со Svelte styles.
  • Новые правила подключать только после fixtures, test:rules и baseline.

Q8. Новые автоматические правила

Оценка: L. Зависимости: Q4, Q7.

Дублирование HTML/Svelte-разметки

Сначала провести report-only аудит новых components/** и routes/**. Определить:

  • минимальный размер клона;
  • нормализацию Svelte blocks и динамических классов;
  • список допустимых fixture/allowlist-случаев.

Только после оценки false positives выбирать между готовым detector и собственным AST-правилом. Не включать detector в blocking gate сразу.

Пользовательские тексты вне i18n

Сделать warn-only пилот с исключениями для:

  • бренда и версии;
  • форматов и имён файлов;
  • X/Y и технических значений;
  • registry source strings;
  • /kit;
  • тестовых данных и внутренних сообщений.

Blanket-запрет всех string literals не использовать.

Согласованность комментариев

Автоматический lint не делать. Это review/process policy: комментарий должен объяснять причину исключения, а TODO/FIXME — ссылаться на backlog или issue и иметь критерий закрытия.

4. Что описать в AGENTS.md

В AGENTS.md добавить только следующие неочевидные правила:

  1. Какой набор команд считается полным quality gate и что означает успешный результат при warnings.
  2. Старый/new scope и политику v1: v1 можно удалить, но пока он существует, не расширять на него новые правила и не тратить время на его поддержку.
  3. Политику e2e: semantic locators, допустимый data-testid, запрет бессмысленных counts/classes/alt/exact prose.
  4. Политику i18n: новые пользовательские тексты через i18n; registry source, brand, formats и /kit — явные исключения.
  5. Жизненный цикл test.fixme: только для зарегистрированного бага, с ссылкой; исправление и удаление теста происходят вместе.
  6. Комментарии и TODO/FIXME должны объяснять «почему» и иметь ссылку на работу.
  7. Shared-модули core/theme требуют проверки обеих веток.

Синтаксические списки ESLint-правил и подробные токены остаются в web/eslint-plugins/README.md.

Политика документации для агентов

AGENTS.md не должен превращаться в полный справочник проекта. В нём оставляем только обязательный рабочий контракт: команды, границы old/new, ключевые инварианты, исключения и ссылки на подробные документы. Если агенту нужно понять причину или workflow, в AGENTS.md должна быть короткая понятная формулировка; длинные примеры, точные процедуры, таблицы и критерии проверки переносятся в docs/ или в README рядом с соответствующей подсистемой.

Принцип выбора места документа:

  1. Поведение агента, которое нельзя пропустить — кратко в AGENTS.md.
  2. Точная команда, скрипт, параметр или критерий качества — в docs/quality-gates.md или в README соответствующей подсистемы.
  3. Архитектурное решение, поток данных и границы модулей — в docs/architecture-overview.md или существующем плане.
  4. Реализация конкретного lint-правила и его fixtures — только в web/eslint-plugins/README.md и исходниках правила.
  5. Продуктовая задача, backlog и ручная приёмка — в docs/backlog.md, активном плане или docs/checklist-manual-testing.md.

Подробные документы не дублируются в нескольких местах: у документа должен быть один источник истины, а остальные файлы ссылаются на него. Все подробные материалы хранятся в docs/, чтобы не засорять корень репозитория.

Активный документ должен иметь статус (draft, active, completed или archived) и понятную область применения. Архивные планы не используются как текущие критерии приёмки без отдельной сверки с кодом. Новый документ создаётся только когда темы нет в существующем файле; иначе обновляется существующий.

Архивирование и срок хранения

Завершённые, отменённые или явно устаревшие документы переносятся в docs/archive/, а не остаются в корне docs/ как рабочие планы. При переносе добавляются дата архивирования, дата удаления и причина. Архивный документ — временная справка для быстрого просмотра прошлых решений, но не источник текущих требований.

Срок хранения после архивирования — 30 дней. После этой даты документ можно удалить после проверки ссылок; если он снова нужен, его восстанавливают из git history или пересоздают как новый активный документ. Подробная процедура и шаблон метаданных находятся в docs/archive/README.md.

Какие документы подготовить

Документ Назначение Когда создавать/обновлять
docs/README.md Индекс активных документов, карта источников истины и краткий порядок чтения для агента Q0; при добавлении нового активного документа
docs/agent-workflow.md Подробный workflow: исследование, изменение, проверка, работа с legacy и обновление документации Q0–Q1; только для процессов, не описанных кратко в AGENTS.md
docs/quality-gates.md Команды проверки, semantics errors/warnings, порядок запуска и требования CI Q1; при изменении scripts/config/CI
docs/testing-strategy.md Слои тестов, locator policy, i18n assertions, fixtures, test.fixme и правила e2e Q4; при изменении тестовой архитектуры
docs/architecture-overview.md Карта core, registry, executor, нового UI и /v1, shared-модули и зависимости Q5 или перед крупным рефакторингом; не дублировать существующие планы
web/eslint-plugins/README.md Детали custom lint rules, token policy и fixtures Уже существует; менять только вместе с правилами
docs/archive/README.md Политика временного архива, даты и удаления через 30 дней Q0; обновлять при изменении архивной политики

Не создавать отдельные docs/commands.md, docs/known-issues.md или копию backlog: команды принадлежат quality-gates, известные проблемы — backlog и checklist. README.md в корне остаётся кратким обзором продукта, а не вторым руководством агента.

5. Порядок PR

  1. Q0 — синхронизация backlog/checklist/AGENTS.
  2. Q1 — verify и PR quality gate.
  3. Q2 — i18n parity и strict warning gate.
  4. Q3 — удалить v1 отдельной атомарной задачей.
  5. Q4 — тестовый контракт и stale-тесты для production UI.
  6. Q5 — preview-баги и снятие fixme.
  7. Q6 — расширенное покрытие.
  8. Q7 — тесты lint-инфраструктуры и unused tokens.
  9. Q8 — report-only duplicate/text audits; blocking — только после baseline.

Каждый PR должен быть атомарным и небольшим; не объединять SchemaPreview refactor, новые i18n-правила и исправление продуктовых багов в одну работу.

6. Отдельные направления и что не начинать автоматически

  • полноценный browser/visual/coverage matrix;
  • полноценная PWA/API/WASM-платформа;
  • SchemaPreview state/view-model refactor;
  • plural-формы до модели словаря;
  • универсальный линтер одинаковых комментариев;
  • batch/архивы, region-инструменты и остальные продуктовые волны из backlog.

7. Решения, которые нужно принять на ревью

  • Оставляем ли dictionary linter warn-only до очистки или сразу вводим blocking baseline?
  • Считаем ли registry.title/description физическими i18n-ключами или допустимым английским fallback?
  • Подтверждаем ли auto-run генераторов без кнопки Generate?
  • Что именно должен делать Reset при включённом auto-run?
  • Какие browser/e2e проверки должны быть обязательными для PR, а какие — отдельным ночным прогоном?