From c187619933b6cc4d9fca8e43f4b7431335c41f33 Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Fri, 25 Sep 2026 13:52:58 +0500 Subject: [PATCH] docs: add codebase quality plan --- docs/plan-codebase-quality.md | 348 ++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 docs/plan-codebase-quality.md diff --git a/docs/plan-codebase-quality.md b/docs/plan-codebase-quality.md new file mode 100644 index 0000000..e5aabb4 --- /dev/null +++ b/docs/plan-codebase-quality.md @@ -0,0 +1,348 @@ +# План: линтеры, тесты и качество кодовой базы + +> Статус: **draft — на ревью**. +> +> Источник: `docs/backlog.md`, аудит конфигурации `web/`, e2e-тестов и +> инфраструктурных скриптов. До подтверждения плана кодовые изменения не +> выполняются. +> +> Цель: сделать качество кодовой базы воспроизводимым, убрать ложную «зелёность» +> проверок, стабилизировать тестовые контракты и только после этого расширять +> автоматические правила. + +## 1. Границы и принципы + +1. Сначала stabilизировать существующие проверки и тестовые контракты, а не + добавлять новые сложные lint-правила. +2. Старый UI (`src/lib/v1/`, `src/routes/v1/`, `app_v1.css`) и новый UI + (`src/lib/components/`, `src/routes/` без `v1/`) остаются изолированными. + Глобальное расширение recommended-правил выполняется только в рамках C19. +3. `core/` и `theme/` — общие модули. Их изменения проверяются unit-тестами и + smoke-сценариями для обеих веток. +4. Изменения делаются небольшими атомарными частями, в соответствии с + `AGENTS.md`. +5. Каждый новый lint-rule сначала появляется в report-only/warn-only режиме, + получает fixtures и тесты, и только после очистки baseline становится + blocking. +6. Детали реализации правил остаются в `web/eslint-plugins/README.md`; + `AGENTS.md` содержит краткие обязательные политики, понятные агенту без + дополнительных поисков, и ссылки на подробные документы. + +## 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/README.md` как индекс активных документов и карту источников + истины; подробные правила не дублировать в корневых файлах. + +**Готово, когда:** один документ описывает текущие команды, актуальный baseline +и все известные `test.fixme` имеют ссылки на зарегистрированный баг. + +### Q1. Единый quality gate и CI + +**Оценка:** S–M. **Зависимости:** Q0. + +Добавить read-only `verify`-команду, которая запускает: + +```text +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 оставить отдельным тяжёлым гейтом: + +```text +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 + +**Оценка:** M. **Зависимости:** Q0, Q1. + +- Решить, являются ли `registry.title/description` физическими ключами словарей + или допустимым английским fallback. +- Не исправлять расхождения массовым allowlist-ом. Сначала классифицировать их + на реальные пропуски и осознанные fallback-источники. +- Дополнить словари до согласованной схемы, включая реальные пропуски в `ru.ts`. +- После очистки включить zero-warning gate. +- Отдельно проверить, что изменения в i18n не требуют синхронного изменения + `v1`-словарей: новая и legacy-ветки изолированы. +- Не начинать plural-формы до решения модели `string | PluralForms` + (`docs/plan-preview-i18n.md:289-307`). + +**Готово, когда:** dictionary linter даёт ноль несогласованностей без +молчаливого подавления ошибок, а тесты словарей проходят в обеих локалях. + +### Q3. Тестовый контракт e2e + +**Оценка:** M. **Зависимости:** Q0, решение по 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. + +**Готово, когда:** изменение формулировки, класса или порядка элементов не +ломает поведенческий тест без изменения пользовательского контракта. + +### Q4. Закрыть известные preview-баги + +**Оценка:** M. **Зависимости:** Q3. + +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 либо исправлен и покрыт зелёным тестом, +либо явно перенесён в отдельную продуктовую задачу с владельцем и критерием. + +### Q5. Расширение unit и browser-покрытия + +**Оценка:** M–L. **Зависимости:** Q3, Q4. + +Сначала: + +- 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-инструментам. + +### Q6. Укрепление lint-инфраструктуры + +**Оценка:** M. **Зависимости:** Q1, Q2. + +- Очистить или использовать 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. + +### Q7. Новые автоматические правила + +**Оценка:** L. **Зависимости:** Q3, Q6. + +#### Дублирование HTML/Svelte-разметки + +Сначала провести report-only аудит новых `components/**` и `routes/**`. +Определить: + +- минимальный размер клона; +- нормализацию Svelte blocks и динамических классов; +- список допустимых fixture/allowlist-случаев; +- исключение `v1`. + +Только после оценки 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 и запрет глобального расширения lint до C19. +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/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 | Q3; при изменении тестовой архитектуры | +| `docs/architecture-overview.md` | Карта `core`, registry, executor, нового UI и `/v1`, shared-модули и зависимости | Q4 или перед крупным рефакторингом; не дублировать существующие планы | +| `web/eslint-plugins/README.md` | Детали custom lint rules, token policy и fixtures | Уже существует; менять только вместе с правилами | + +Не создавать отдельные `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. **Q3** — тестовый контракт и stale-тесты. +4. **Q4** — preview-баги и снятие `fixme`. +5. **Q2** — i18n parity и strict warning gate. +6. **Q6** — тесты lint-инфраструктуры и unused tokens. +7. **Q5** — расширенное покрытие. +8. **Q7** — report-only duplicate/text audits; blocking — только после baseline. + +Каждый PR должен быть атомарным и небольшим; не объединять `SchemaPreview` +refactor, новые i18n-правила и исправление продуктовых багов в одну работу. + +## 6. Отложить за пределы этого плана + +- удаление `/v1` и глобальное расширение recommended (C19); +- полноценный 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, а какие — + отдельным ночным прогоном?