docs: update a lot of plans, readmes, descriptions

This commit is contained in:
2026-09-27 09:10:26 +05:00
parent 9c6f223b13
commit 82207c82f2
47 changed files with 1029 additions and 4615 deletions
+77 -99
View File
@@ -1,22 +1,30 @@
# Backlog
> Статус: **active**. Продуктовые, UX- и инфраструктурные задачи. Здесь только
> **открытые** задачи: выполненные удаляются, а критичные для проекта факты из
> них переносятся в тематический документ (архитектура, quality gates, lint,
> e2e) по мере закрытия.
>
> «Что сознательно не вводим и почему» живёт в `docs/decisions.md`, архитектура
> — в `docs/architecture.md`. Raw-находки UX-аудита — `docs/tools-audit.md`, их
> разбивка на волны — `docs/plan-fields-audit-fixes.md`.
>
> Ids инструментов сверять с `web/src/lib/registry/`; полный список —
> `docs/tools-map.md`.
## lint и прочие правила
- [x] Кросс-языковой линтер словарей (warn-only: паритет ключей, пустые
значения, совпадение `{placeholder}`-переменных между всеми локалями) —
правило `i18n/dict-consistency`, детали в `web/eslint-plugins/README.md`.
Правило реализовано; Q2 перевёл i18n baseline к zero-warning через
policy-aware fallback.
- [x] Проверка текстов в svelte/ts/html — реализовано правилом
`i18n/no-hardcoded-user-text` (warn, baseline 0): ловит текст в шаблоне и
в пользовательских атрибутах, исключения — бренд, форматы, имена файлов,
registry-строки и `/kit`. Детали в `web/eslint-plugins/README.md`.
- [ ] расширить `i18n/no-hardcoded-user-text` на `web/src/routes/**`: сейчас
правило навешено только на `components/**` (без `/kit`), поэтому
захардкоженный текст в `routes/**` проходит молча (`web/eslint.config.js`,
`web/eslint-plugins/README.md`)
- [ ] `tseslint.config(...)` deprecated: сигнатура
`(...configs: InfiniteDepthConfigWithExtends[]): ConfigArray` помечена
устаревшей, нужен переход на `defineConfig` из `typescript-eslint` —
`web/eslint.config.js`.
- [ ] удалить мёртвые `tools.*.params` из root i18n после проверки потребителей;
до этого Q2 держит pattern-based policy-исключение
до этого действует pattern-based policy-исключение
(`web/eslint-plugins/README.md`, раздел `dict-consistency`)
## Мелочи всякие
@@ -90,14 +98,13 @@
## Переезд
- [x] добавить i18n в preview
- [ ] множественные числа (часть/части/частей; «N параметров», счётчики) —
`tPlural()` и формат `PluralForms`; детали и критерии — в этом backlog
## SEO/GEO
Общий план: `docs/plan-seo.md` (S0–S4). C17 выполнен; старт возможен — пока
только domain-free часть S1.
Общий план: `docs/plan-seo.md` (S0–S4). Переезд preview на реальные маршруты
выполнен; старт возможен — пока только domain-free часть S1.
- [ ] переименование бренда + домен: чек-лист в локальном плане
`docs/plan-domain.local.md` (вне git, имя домена в репо не публикуется;
@@ -125,38 +132,12 @@
## Качество production UI
Q5–Q6 и Q7–Q8 закрывают известные preview-проблемы, special fixtures, smoke,
layout/view-model инварианты, browser matrix, coverage-гейт и линтеры; активных
`test.fixme` в e2e больше нет.
Политика проверок — `docs/quality-gates.md`, e2e — `docs/testing-strategy.md`.
- [x] Генераторы auto-run без кнопки Generate — `web/e2e/generators.spec.ts`.
- [x] `resize-png` и `crop-png` используют размеры текущего source через общий
source-aware schema resolver — `web/e2e/pipeline.spec.ts`.
- [x] Reset сохраняет source/text, восстанавливает defaults и запускает deferred
auto-run — `web/e2e/pipeline.spec.ts`.
- [x] Ошибки хранят i18n key/vars и переводятся при выводе; изменение языка
обновляет alert — `web/e2e/i18n.spec.ts`.
- [x] Malformed/special PNG fixtures: CRC, truncated, palette и 16-bit проходят
через upload без краша — `web/e2e/png-fixtures.spec.ts`.
- [x] Registry-wide smoke покрывает все 122 инструмента по input/result-типу —
`web/e2e/tools-smoke.spec.ts`, `generators.spec.ts`,
`text-and-verdicts.spec.ts`.
- [x] Layout-группировка вынесена в `resolveLayoutGroups` и покрыта
unit-тестами; `SchemaFields.svelte` использует общий seam.
- [x] `SchemaPreview` view-model вынесена в `buildSchemaPreviewModel` и покрыта
unit-тестами для всех input/result-типов.
- [x] Browser matrix: полный Chromium, Firefox/WebKit для browser-critical
спецификаций и mobile Chromium 390×844 — `web/playwright.config.ts`.
- [x] Расхождение декодеров зафиксировано как ожидаемое поведение: Firefox и
WebKit декодируют `truncated-no-iend` и `idat-cut`, а WebKit ещё и
`crc-bad-idat`. Таблица движков живёт в `web/e2e/png-fixtures.spec.ts`,
продукт не ужесточается, и любая выгрузка битого файла обязана давать
alert, а не падение или «пустой» результат.
- [ ] Component-тесты `SchemaToolView`/`SchemaPreview` требуют отдельного
решения: node Vitest не имеет DOM/canvas, а e2e уже покрывает поведение.
- [ ] Ошибка декодирования изображения из `createImageBitmap` пока показывается
сырым сообщением браузера; нужен `ToolError`-маппер и i18n-ключ. Это
продуктовая задача, не Q6d.
сырым сообщением браузера; нужен `ToolError`-маппер и i18n-ключ.
## Идеи
@@ -178,7 +159,7 @@ layout/view-model инварианты, browser matrix, coverage-гейт и л
4. **Batch-обработка архивов выбранным chain** — оценка L. Вход — zip-архив
картинок (распаковка в браузере), прогон текущего или выбранного сохранённого
chain по каждому файлу, сборка результата обратно в zip для скачивания.
Зависит от п.4 (выбор цепочки) и от экспортного формата pipeline JSON;
Зависит от идеи 3 (выбор цепочки) и от экспортного формата pipeline JSON;
прогресс и ошибки — пофайлово.
5. **Избранные инструменты (fav tools)** — оценка S/M. Тоггл-звёздочка на
@@ -188,59 +169,48 @@ layout/view-model инварианты, browser matrix, coverage-гейт и л
6. **Конвертация формата — НЕ отдельный инструмент, а выбор в кнопке Download**
— оценка M/L. Инструменты `convert-png-to-jpg` / `convert-png-to-webp` (и др.
форматы) не должны жить как самостоятельные инструменты цепочки. Вместо этого
— бесшовное внедрение выбора формата/качества прямо в кнопку/диалог
**Download**: юзер скачивает результат в нужном формате (mime/ext/quality), а
pipeline при этом не усложняется лишним звеном. **Сделано (2026-09):**
механическая часть реализована в preview — `ToolEntry.output`
(`OutputFormat`: mime/ext/qualityParamId) в `web/src/lib/registry/types.ts`;
`SchemaToolView.download()` кодирует по `output` (jpg/webp/bmp уже настроены;
`png-to-bmp` переведён сюда же). Q6c покрывает этот фиксированный контракт
unit/E2E-проверками; переключатель форматов и quality остаётся отдельным
UX-райзом. **Осталось (UX-райз «Download»):**
форматы) не должны жить как самостоятельные инструменты цепочки. Механическая
часть уже есть: `ToolEntry.output` (`OutputFormat`: mime/ext/qualityParamId)
и кодирование по нему в `SchemaToolView.download()` — `docs/architecture.md`,
раздел 3. Осталось (UX-райз «Download»):
- выбор формата/качества прямо в кнопке/диалоге Download для любого
результата (не отдельными конвертерами);
- экспорт с лимитом размера → закрывает отложенный `reduce-to-size-png`
(целевой KB, бинарный поиск по k из квантования). Проработать вместе с
достройкой download-флоу нового UI.
7. **`watermark-image-png` (водяной знак картинкой)** — оценка M. Отложен из
миграции (`archive/plan-migrate-remaining.md`). Нужна overlay-механика:
второй источник изображения (getOverlay/store), параметры scale/opacity/
position/margin/aspect. Решается вместе с вопросом, как второй источник
картинки вписывается в schema-driven preview (`SchemaToolView`).
7. **`watermark-image-png` (водяной знак картинкой)** — оценка M. Нужна
overlay-механика: второй источник изображения (getOverlay/store), параметры
scale/opacity/position/margin/aspect. Решается вместе с вопросом, как второй
источник картинки вписывается в schema-driven preview (`SchemaToolView`).
8. **`png-info` (детальная информация о PNG)** — оценка M/L. Отложен из
миграции. Отдельный райз: exif-теги, редактирование, структурированный вывод;
нужен свой отдельный случай в UI, не «ещё один text/verdict». возможно нужна
вообще отдельная страница, несовместимая с другими инструментами: 1) она
работает не с изображением, а с мета данными из файла, 2) она не может быть
частью цепочки, т.к. результат не является изображением, 3) если надо
изменить теги, никакого форматирования и изменения в изображение вносить не
надо, только в мета информацияю
8. **`png-info` (детальная информация о PNG)** — оценка M/L. Отдельный райз:
exif-теги, редактирование, структурированный вывод; нужен свой отдельный
случай в UI, не «ещё один text/verdict». Возможно нужна вообще отдельная
страница, несовместимая с другими инструментами: 1) она работает не с
изображением, а с метаданными из файла, 2) она не может быть частью цепочки,
т.к. результат не является изображением, 3) если надо изменить теги, никакого
форматирования и изменения в изображение вносить не надо, только в
метаинформацию.
9. **Region-инструменты** (censor/erase/pixelate-area/blur-area/sharpen-area/
reverse-area) — ждут UI выделения области на превью. Из
`archive/plan-gap-waves.md` («вне очереди»).
reverse-area) — ждут UI выделения области на превью. Вне очереди.
10. **Мультифайловые инструменты-потребители** (gif-to-frames, separate-colors)
— механизм «результат = набор файлов» (1 → many) реализован: `FileResult` +
`result: "files"` + скачивание zip-архивом + грид-превью частей. Первый
потребитель — `split-into-parts-png`. Остальные подключаются по мере нужды.
— механизм «результат = набор файлов» (1 → many) уже есть
(`docs/architecture.md`, раздел 7), первый потребитель —
`split-into-parts-png`. Остальные подключаются по мере нужды.
11. **Анимационные** (slow-reveal/fade/scrolling) — выход не PNG; отдельное
решение о формате. Из `archive/plan-gap-waves.md`.
решение о формате.
12. **HARD-серия** (glitch, barcode, signature-extract, handwritten-digital). Из
`archive/plan-gap-waves.md`.
12. **HARD-серия** (glitch, barcode, signature-extract, handwritten-digital).
13. **Контраст текста на акцентных кнопках — частично закрыт**. Для dark-темы
`--color-main`/`--color-accent` подняты до tone 56, чтобы пройти текущий
порог `palette.test.ts` 4.0; targeted-тест проходит. Light-тема сохраняет
контраст ~4.1–4.3, что ниже AA 4.5 для обычного текста, поэтому после
завершения редизайна нужно повторно поднять тона и вернуть порог 4.5. Также
проверить `--color-danger` (dark, тон 55): текст на нём 4.93 — ок, но
light-danger tone 48 = 4.25 на границе.
13. **Контраст текста на акцентных кнопках — частично закрыт**. Тона
`--color-main`/`--color-accent` подняты под текущий порог `palette.test.ts`;
targeted-тест проходит. Light-тема всё ещё ниже AA 4.5 для обычного текста,
а `--color-danger` в light-теме на границе: после завершения редизайна
вернуть порог 4.5 и перепроверить оба токена.
14. **Отображение маски для инструментов (runMask/preview-mask)** — придумать и
реализовать процесс показа маски результата. **Контекст:** в старом
@@ -252,25 +222,32 @@ layout/view-model инварианты, browser matrix, coverage-гейт и л
возможность вернуть (или инструмент — объявить) `runMask` — ч/б изображение
маски изменений либо иной подход (отдельное поле `mask` + функция маски,
второй результат, overlay). Оценка — на усмотрение при проработке (S/M).
Пока живём без неё. **Идея 2:** каждый `run` возвращает два изображения -
для отображения (показывает маску или сам результат), и для передачи в
следующий инструмент (всегда результат. Оценка — на усмотрение при
Пока живём без неё. **Идея 2:** каждый `run` возвращает два изображения —
для отображения (показывает маску или сам результат) и для передачи в
следующий инструмент (всегда результат). Оценка — на усмотрение при
проработке (S/M). Пока живём без неё.
15. **Процесс работы с инструментами 1 → many и many → 1** — абстракция
результата «набор файлов» оформлена и работает: тип `FileResult`,
`result: "files"` в реестре, сериализация через executor, скачивание
zip-архивом, грид-превью частей. Реализовано на первом потребителе
`split-into-parts-png` (2026-09, `docs/archive/plan-split-into-parts.md`).
Q6b закрывает контракт ZIP/download: unit-тесты `web/src/lib/zip.test.ts` и
browser-сценарий `web/e2e/pipeline.spec.ts` проверяют имена частей и
содержимое архива. **1 → many:** подключение остальных потребителей
(gif-to-frames, separate-colors) при необходимости; формат/качество файлов
внутри zip — отложено до UX-райза «Download» (п.7). **many → 1** (вход =
архив/несколько картинок → единый результат): не реализовано. Зависит от
batch-обработки архивов (п.5 идей, roadmap фаза 8 «batch-страница»). Нужна
отдельная проработка входа (распаковка zip в браузере, порядок файлов,
поведение в пайплайне — такие инструменты терминальны, как и 1 → many).
15. **Набор файлов в пайплайне: 1 → many не должен быть терминальным** — оценка
L. **Сейчас** `execute` принимает один `source: PixelImage | undefined` и
возвращает один `ToolResult`, а `SchemaToolView` раскладывает вывод в
`result` / `fileResult` / `textResult` по `resultKind` — поэтому шаг с
`result: "files"` упирается в конец цепочки. **Направление:** следующий
инструмент применяется **ко всем картинкам** предыдущего результата
(fan-out), а many → 1 (вход = архив или несколько файлов) — обратная сторона
того же контракта. Терминальными остаются только результаты, которые не
картинка (text, verdict). Что обдумать:
- где проходит граница: один вызов `run(ctx)` на файл (имя части склеивается
в `FileResult.files`) или батч целиком на стороне исполнителя;
`executor/protocol.ts` `files` уже сериализуются, но при батче нужен
прогресс и отмена;
- частичные ошибки: один битый файл не должен ронять весь шаг — нужен
per-file отчёт, а не один `ToolError` на шаг;
- имена частей на каждом шаге и Download для набора (сейчас zip по
`tool.id`, `SchemaToolView.download()`);
- обратная сторона: распаковка zip в браузере, порядок файлов, поведение
many → 1 → many в одной цепочке. Зависит от идеи 10 (остальные потребители
1 → many) и идеи 4 (batch по архиву), `docs/roadmap.md` фаза 8
«batch-страница».
16. **Главная должна отличаться от каталога** — оценка S. Сейчас
`src/routes/+page.svelte` и `src/routes/list-tools/+page.svelte` побайтово
@@ -278,5 +255,6 @@ layout/view-model инварианты, browser matrix, coverage-гейт и л
рабочий маршрут: на него ссылается крошка в `+layout.svelte` и он открыт
e2e-сценариями `catalog.spec.ts`, `i18n.spec.ts`, `navigation.spec.ts`.
Замысел: главная — крупнее и с более простым поиском, без категорий; каталог
остаётся группировкой с фильтрами. Найдено измерением дублирования разметки
по 65 `.svelte`-файлам: файлы побайтово идентичны.
остаётся группировкой с фильтрами. Детектор дублирования разметки
сознательно не вводим — `docs/decisions.md`, раздел 1, поэтому расхождение
ловится на ревью.