mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
docs: update a lot of plans, readmes, descriptions
This commit is contained in:
+55
-169
@@ -1,12 +1,12 @@
|
||||
# Quality gates
|
||||
|
||||
> Статус: **active**. Каноническое описание быстрых проверок репозитория.
|
||||
> Краткие обязательные команды остаются в `AGENTS.md`.
|
||||
> Статус: **active**. Каноническое описание быстрых проверок: команды, coverage,
|
||||
> warnings, CI. Почему гейт такой, а не иначе, — `docs/decisions.md`.
|
||||
|
||||
Команды выполняются из корня репозитория.
|
||||
|
||||
## Каноническая команда
|
||||
|
||||
Запускать из корня репозитория:
|
||||
|
||||
```text
|
||||
pnpm verify
|
||||
```
|
||||
@@ -28,25 +28,40 @@ pnpm verify
|
||||
## Coverage
|
||||
|
||||
`pnpm --dir web test:coverage` считает покрытие только по `src/lib` и падает
|
||||
ниже порога. Scope и список исключений — в `web/vitest.config.ts`, обоснование —
|
||||
в `docs/testing-strategy.md`.
|
||||
ниже порога. Scope и список исключений — в `web/vitest.config.ts`.
|
||||
|
||||
| Метрика | Порог | Baseline |
|
||||
| ---------- | ----- | -------- |
|
||||
| statements | 90 | 91.77% |
|
||||
| branches | 82 | 83.3% |
|
||||
| functions | 72 | 74.31% |
|
||||
| lines | 91 | 92.53% |
|
||||
| Метрика | Порог |
|
||||
| ---------- | ----- |
|
||||
| statements | 90 |
|
||||
| branches | 82 |
|
||||
| functions | 72 |
|
||||
| lines | 91 |
|
||||
|
||||
Порог — нижняя граница от текущего baseline, а не оценка качества: он блокирует
|
||||
регрессию и не требует сначала закрывать весь долг. Локальный замер занимает ~30
|
||||
с, поэтому отдельного прогона в `verify` нет — `test:coverage` заменяет `test`.
|
||||
Порог — нижняя граница, а не оценка качества: он блокирует регрессию и не
|
||||
требует сначала закрывать весь долг. Актуальные проценты даёт
|
||||
`pnpm --dir web test:coverage`; здесь они не дублируются, чтобы число не
|
||||
устарело молча (`AGENTS.md`). Локальный замер занимает единицы секунд, поэтому
|
||||
отдельного прогона в `verify` нет — `test:coverage` заменяет `test`.
|
||||
|
||||
Исключения из scope и их причины:
|
||||
|
||||
| Исключение | Причина |
|
||||
| ------------------------------------------- | ------------------------------------------- |
|
||||
| `**/*.test.ts`, `**/test-helpers.ts` | сами тесты |
|
||||
| `**/*.svelte.ts` | runes, не работают в node |
|
||||
| `executor/executor.worker.ts` | entry worker, исполняется только в браузере |
|
||||
| `components/define.ts` | type-only, нет исполняемого кода |
|
||||
| `core/domText.ts`, `core/io.ts` | canvas, `createImageBitmap`, нужен браузер |
|
||||
| `i18n/en.ts`, `i18n/ru.ts`, `tool-icons.ts` | данные, а не логика |
|
||||
|
||||
`registry/*` из scope НЕ исключены: низкое покрытие там означает непокрытую
|
||||
логику, а не ограничение окружения. Включение браузерных модулей в scope —
|
||||
отдельное решение, а не молчаливое расширение списка.
|
||||
|
||||
## E2E
|
||||
|
||||
E2E не входит в `verify`, потому что Playwright поднимает build и статический
|
||||
сервер. Locator, fixture, i18n и `test.fixme`-политика описаны в
|
||||
`docs/testing-strategy.md`:
|
||||
сервер:
|
||||
|
||||
```text
|
||||
pnpm --dir web test:e2e
|
||||
@@ -55,104 +70,41 @@ pnpm --dir web test:e2e
|
||||
Запускать его обязательно для изменений маршрутов, загрузки файла, результата,
|
||||
download, темы или локализации. Изменения runtime fixtures/загрузки файла
|
||||
проверяются отдельным `web/e2e/png-fixtures.spec.ts`; ручные бинарники из
|
||||
`tests/fixtures/` не входят в `verify`. В текущем CI это отдельный non-blocking
|
||||
baseline; после закрытия известных ошибок его можно сделать blocking.
|
||||
`tests/fixtures/` не входят в `verify`.
|
||||
|
||||
Локально прогон идёт с `workers: 1` и заметно медленнее: это осознанный размен,
|
||||
экономит память и оставляет компьютер отзывчивым. Playwright не умеет
|
||||
per-project лимит воркеров, а browser matrix упирается в память, а не CPU.
|
||||
Тяжёлые прогоны запускаются по команде пользователя — по одному, без фонового
|
||||
запуска и циклов повторов; детали в `docs/agent-workflow.md`.
|
||||
Локально прогон идёт с `workers: 1` и заметно медленнее. Правила нагрузки на
|
||||
машину пользователя и диагностика флаков — `docs/agent-workflow.md`, раздел 3;
|
||||
матрица проектов и ожидаемое поведение декодеров — `docs/testing-strategy.md`,
|
||||
раздел 7; статус e2e в CI и порядок чтения прогона — `docs/decisions.md`,
|
||||
разделы 9–10.
|
||||
|
||||
## Быстрые подмножества
|
||||
|
||||
| Изменение | Команда |
|
||||
| ---------------------------- | ------------------------------------------------------- |
|
||||
| Только Markdown | `pnpm check:docs` |
|
||||
| TypeScript/Svelte | `pnpm --dir web check` и `pnpm --dir web test` |
|
||||
| Lint-правило или lint-конфиг | `pnpm --dir web test:rules` и `pnpm --dir web lint:all` |
|
||||
| Пользовательский поток | `pnpm --dir web test:e2e` |
|
||||
| Fixtures/загрузка файла | `pnpm --dir web test:e2e` |
|
||||
| Полный локальный gate | `pnpm verify` |
|
||||
Матрица «изменение → минимальный набор проверок»:
|
||||
|
||||
| Изменение | Команда |
|
||||
| ---------------------------------------------------- | ------------------------------------------------------- |
|
||||
| Только Markdown | `pnpm check:docs` |
|
||||
| TypeScript/Svelte | `pnpm --dir web check` и `pnpm --dir web test` |
|
||||
| Lint-правило или lint-конфиг | `pnpm --dir web test:rules` и `pnpm --dir web lint:all` |
|
||||
| Маршрут, загрузка, результат, download, тема, локаль | `pnpm --dir web test:e2e` |
|
||||
| Перед ревью или merge | `pnpm verify` |
|
||||
|
||||
## Errors и warnings
|
||||
|
||||
- `errors` завершают соответствующий инструмент ненулевым кодом.
|
||||
- После Q2 ESLint запускается с `--max-warnings=0`: новые ESLint warnings
|
||||
блокируют gate.
|
||||
- Token audit оставляет unused-token сообщение неблокирующим: после Q7a пыль
|
||||
вычищена, решение о fail-режиме зафиксировано в Q7d — новый токен появляется
|
||||
вместе с потребителем, но стиль не блокирует деплой.
|
||||
- ESLint запускается с `--max-warnings=0`: новые ESLint warnings блокируют gate.
|
||||
- Token audit оставляет unused-token сообщение неблокирующим: новый токен
|
||||
появляется вместе с потребителем, но стиль не блокирует деплой (решение —
|
||||
`docs/decisions.md`, раздел 6).
|
||||
- Резолв `var()` в `app.css` — ошибка: несуществующий токен молча роняет
|
||||
объявление, поэтому этот check failing, в отличие от unused.
|
||||
- `lint:all` сейчас чист: 0 errors, 0 i18n warnings, 0 unused tokens.
|
||||
- `dict-consistency` использует base-locale fallback для registry metadata и
|
||||
pattern-based policy для временно неиспользуемых `tools.*.params`; это не
|
||||
молчаливый `allowPaths`-список.
|
||||
|
||||
## Решения, принятые без автоматизации
|
||||
|
||||
Здесь лежат решения «что сознательно НЕ вводим», чтобы не пересматривать их
|
||||
заново через полгода. Для каждого — причина и то, что пересмотрело бы решение. В
|
||||
`docs/backlog.md` такие пункты не дублируются: backlog живёт задачами, а не
|
||||
историей решений.
|
||||
|
||||
### Детектор дублирования разметки — не вводим
|
||||
|
||||
Ни свой AST-правило, ни готовая зависимость (jscpd, `eslint-plugin-sonarjs`).
|
||||
|
||||
- Измерение по 65 `.svelte` в `components/**` и `routes/**`: при пороге 5
|
||||
нормализованных строк — одна осмысленная пара, при пороге 3 строки — 17 пар и
|
||||
все они шум (`</label>`, `{/each}`, `{#if children}`). Семейство
|
||||
schema-контролов делит максимум 4 строки — это законное сходство by design.
|
||||
- Причина: построчное сравнение Svelte-разметки принципиально ненадёжно —
|
||||
одинаковый контейнер с разным содержимым даёт ложное срабатывание, а намеренно
|
||||
общий класс — ложную тишину. Чтобы не ловить шум, порог пришлось бы поднять до
|
||||
12+ строк, и тогда правило срабатывает ровно один раз.
|
||||
- Контроль остаётся на ревью (расхождение видно в диффе) и на поведенческих
|
||||
e2e-проверках; извлечение общей разметки закреплено конвенцией в `AGENTS.md`.
|
||||
- Пересмотреть, если появится реально «уехавшая» копипаста в компонентах или
|
||||
библиотека разрастётся на уровень композиций страниц.
|
||||
|
||||
### Линтер согласованности комментариев — не вводим
|
||||
|
||||
Описания инструментов различаются осознанно, и ловить это текстовым правилом
|
||||
дороже, чем смотреть на ревью. Действенная часть выполнена вручную: все
|
||||
`TODO`/`FIXME` перенесены в backlog, незарегистрированных пометок в коде нет;
|
||||
новые запрещены правилом в `AGENTS.md`.
|
||||
|
||||
### Visual snapshots — не вводим
|
||||
|
||||
`toHaveScreenshot` сравнивает страницу с PNG-baseline из прошлого коммита. При
|
||||
активно меняющемся визуальном языке это превращает каждый дизайн-PR в
|
||||
перегенерацию и ревью картинок, а baseline платформенные (снимок с Windows не
|
||||
совпадёт на `ubuntu-latest`). Потребность закрывают e2e-поведение, `lint:tokens`
|
||||
с token audit, i18n-гейт и ручной чеклист. Вернуться стоит, когда визуальный
|
||||
язык стабилизируется; тогда первым идёт `/kit` в двух темах, а baseline
|
||||
рождаются на Linux.
|
||||
|
||||
### Fail-режим для unused-token аудита — не вводим
|
||||
|
||||
Остаётся предупреждением: `verify` входит в deploy-workflow, поэтому стилевой
|
||||
долг блокировал бы деплой сайта. Кроме того, аудит видит только ссылки
|
||||
`var(--x)`, и чтение токена из JS дало бы ложное срабатывание. Правило «новый
|
||||
токен — вместе с потребителем» живёт в `AGENTS.md`.
|
||||
|
||||
### Per-project `expect.timeout` — не задаём
|
||||
|
||||
Firefox и WebKit отдают результат так же быстро, как Chromium: расхождения
|
||||
объясняются памятью, а не скоростью движка. Таймаут под конкретную машину —
|
||||
магическое число, которое придётся подстраивать на каждом раннере, поэтому
|
||||
`lint`/Playwright-конфиг остаётся с дефолтами, а проблема решается лимитом
|
||||
воркеров.
|
||||
|
||||
### Coverage: браузерные модули вне scope
|
||||
|
||||
`src/lib/core/domText.ts` и `src/lib/core/io.ts` (canvas, `createImageBitmap`)
|
||||
исключены из coverage-гейта: в node-Vitest они не исполнимы, и их включение
|
||||
превращало бы метрику в шум. `registry/*` из scope НЕ исключены — низкое
|
||||
покрытие там означает непокрытую логику, а не ограничение окружения. Список
|
||||
исключений с причинами — в `docs/testing-strategy.md`.
|
||||
`lint:all` может завершиться успешно при warnings — это не означает чистый
|
||||
baseline. Агент показывает число errors, warnings и token warnings отдельно.
|
||||
|
||||
## CI
|
||||
|
||||
@@ -165,76 +117,10 @@ Firefox и WebKit отдают результат так же быстро, ка
|
||||
`.github/workflows/deploy.yml` перед production build запускает тот же
|
||||
`pnpm verify`, поэтому deploy не должен проходить при ошибке быстрых проверок.
|
||||
|
||||
### Что и когда запускается
|
||||
|
||||
| Workflow | Триггер | Jobs |
|
||||
| ------------------------ | --------------------------------------- | --------------------------- |
|
||||
| `Deploy to GitHub Pages` | push в `main`, dispatch | `verify`, `build`, `deploy` |
|
||||
| `Quality` | push в `main`, `pull_request`, dispatch | `verify`, `e2e` |
|
||||
|
||||
Пуш в `main` запускает оба workflow: deploy проверяет быстрый gate и собирает
|
||||
сайт, `Quality` прогоняет тот же `verify` и browser matrix. Дублирование
|
||||
`verify` (~1 мин) сознательное: matrix на каждый пуш стоит ~3 мин, и условные
|
||||
job-и ради минуты не окупаются. Browser matrix проверяется на каждом пуше, а
|
||||
ручной `gh workflow run quality.yml` нужен только для перепрогона старого
|
||||
коммита.
|
||||
|
||||
### Проверка результатов CI после пуша
|
||||
|
||||
Первый реальный прогон browser matrix происходит на runner, а не на локальной
|
||||
машине: локально Firefox и WebKit проходят на 1 воркере, но состав, скорость и
|
||||
память Linux-раннера отличаются. Поэтому после пуша разработчика:
|
||||
|
||||
1. дождаться завершения workflow и посмотреть, какие job вообще запустились;
|
||||
2. смотреть статусы **отдельных job**, а не общий conclusion прогона: у `e2e`
|
||||
стоит `continue-on-error: true`, поэтому прогон с упавшим e2e целиком
|
||||
помечается как `success` — проверено на run `36225579363` (`E2E: failure` при
|
||||
`conclusion: success`);
|
||||
3. если `e2e` запускался и зелёный — сообщить фактические числа passed, failed,
|
||||
skipped;
|
||||
4. если `e2e` не запускался, сказать это прямо: matrix на раннере не проверена,
|
||||
и её можно прогнать через `gh workflow run quality.yml`;
|
||||
5. красный `e2e` только из-за ресурсов раннера фиксируется как ограничение
|
||||
окружения: сначала проверяется один проект и один spec, а не увеличиваются
|
||||
таймауты под конкретную машину.
|
||||
|
||||
### Измеренная стоимость прогона
|
||||
|
||||
Замер на ручном запуске `quality.yml` (276 e2e-тестов, 4 проекта,
|
||||
ubuntu-latest):
|
||||
|
||||
| Этап | Время |
|
||||
| ----------------- | -------- |
|
||||
| `verify` job | ~1 мин |
|
||||
| `e2e` job целиком | ~3.1 мин |
|
||||
| из них сами тесты | ~2.2 мин |
|
||||
| весь run | ~4.2 мин |
|
||||
|
||||
Browser matrix стоит около трёх минут, поэтому её дешёво держать на каждом PR.
|
||||
Полный прогон локально на 1 воркере — заметно дольше (~7 мин), и именно поэтому
|
||||
локальные правила нагрузки описаны в `docs/agent-workflow.md`.
|
||||
|
||||
## Политика e2e в CI
|
||||
|
||||
Текущее состояние: `e2e` — non-blocking baseline, запускается на каждом пуше в
|
||||
`main` и на каждом PR целиком (все четыре проекта matrix). Ночного разделения
|
||||
нет: при стоимости job около трёх минут оно не окупается, поэтому новые
|
||||
browser-critical спецификации просто добавляются в `browserContractTests`.
|
||||
|
||||
`e2e` станет blocking, когда выполнятся три условия:
|
||||
|
||||
1. Условия matrix пересмотрены: решено, какие спецификации обязаны идти в
|
||||
`browserContractTests` и `mobileTests`, нужен ли `png-fixtures` вне Chromium
|
||||
и что делать с engine-специфичными расхождениями декодеров.
|
||||
2. Накопились стабильные прогоны на раннере без падений по таймингу.
|
||||
3. Вместе с `continue-on-error` снимается и сам trick с общим conclusion: иначе
|
||||
зелёный прогон при красном `e2e` останется возможен.
|
||||
|
||||
Пока условия не выполнены, `e2e` остаётся non-blocking, а его статус читается по
|
||||
отдельному job.
|
||||
|
||||
## Локальная диагностика
|
||||
|
||||
При медленном полном прогоне сначала запускай минимальную команду из таблицы, а
|
||||
перед ревью или merge — `pnpm verify`. После каждого шага плана результат команд
|
||||
и текущий baseline фиксируются в отчёте агента.
|
||||
Результат после пуша читается **по отдельным job** — процедура в
|
||||
`docs/decisions.md`, раздел 10.
|
||||
|
||||
Reference in New Issue
Block a user