docs: add codebase quality plan

This commit is contained in:
2026-09-25 14:00:35 +05:00
parent becf03f416
commit c187619933
+348
View File
@@ -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, а какие —
отдельным ночным прогоном?