Files
easy-png-tools2/docs/plan-codebase-quality.md
T
2026-09-25 14:20:44 +05:00

365 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План: линтеры, тесты и качество кодовой базы
> Статус: **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/analysis.md` и `docs/sorting-backend.md` в
`docs/archive/`, добавить даты архивирования и удаления через 30 дней.
- Создать `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/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 | Q3; при изменении тестовой архитектуры |
| `docs/architecture-overview.md` | Карта `core`, registry, executor, нового UI и `/v1`, shared-модули и зависимости | Q4 или перед крупным рефакторингом; не дублировать существующие планы |
| `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. **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, а какие —
отдельным ночным прогоном?