From 2fc7801162eda3c0e9f524a156726b0b869c1b63 Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Sun, 27 Sep 2026 10:29:33 +0500 Subject: [PATCH] docs: update plans, backlog --- AGENTS.md | 2 + docs/README.md | 26 +++-- docs/architecture.md | 106 ++++++++++++++------- docs/archive/README.md | 12 ++- docs/backlog.md | 113 ++++++++++++++-------- docs/plan-fields-audit-fixes.md | 105 +++++++++++--------- docs/plan-platform.md | 45 +++++---- docs/plan-seo.md | 164 +++++++++++++++++++------------- docs/quality-gates.md | 17 ++-- docs/roadmap.md | 127 ++++++++++++------------- docs/tools-audit.md | 25 ++++- docs/tools-map.md | 21 ++-- package.json | 4 +- web/eslint-plugins/README.md | 7 +- 14 files changed, 463 insertions(+), 311 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7f8a275..c2faa8e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,6 +17,7 @@ | Юнит-тесты | `pnpm --dir web test` | | Тесты lint-правил | `pnpm --dir web test:rules` | | Линтинг | `pnpm --dir web lint:all` | +| Только токены | `pnpm --dir web lint:tokens` | | E2E | `pnpm --dir web test:e2e` | | Форматирование | `pnpm format` (код + docs) | | Проверка форматирования | `pnpm check:docs` + `pnpm --dir web format:check` | @@ -35,6 +36,7 @@ | Детали lint-правил и токенов | `web/eslint-plugins/README.md` | | Задачи и идеи | `docs/backlog.md` | | Актуальный список инструментов | `docs/tools-map.md` | +| Правка полей и раскладки по волнам | `docs/plan-fields-audit-fixes.md` | | Ручная приёмка UI | `docs/checklist-manual-testing.md` | | Индекс остальных документов | `docs/README.md` | diff --git a/docs/README.md b/docs/README.md index e81e50e..6d5ee2d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,19 +21,22 @@ | `docs/agent-workflow.md` | Порядок работы, нагрузка на машину, протокол ревью | active | | `docs/testing-strategy.md` | Правка e2e: locator-ы, fixtures, browser matrix | active | | `docs/backlog.md` | Продуктовые, UX- и инфраструктурные задачи | active | -| `docs/roadmap.md` | Направления развития, фазы 1–10 | active | +| `docs/roadmap.md` | Направления развития, фазы 1–11 | active | | `docs/tools-map.md` | Актуальный список инструментов против реестра | active | | `docs/tools-audit.md` | Сырые UX/UI-находки по инструментам (вход аудита) | active | | `docs/plan-fields-audit-fixes.md` | Разбивка аудита на волны правок | draft | | `docs/plan-seo.md` | SEO/GEO-план | active | | `docs/plan-platform.md` | API/PWA/шрифты-план | active | +| `docs/plan-domain.local.md` | Чек-лист переименования бренда и покупки домена | active | | `docs/checklist-manual-testing.md` | Ручная приёмка production UI | active | | `web/eslint-plugins/README.md` | Правка lint-правил, токенов и их конфигов | active | | `docs/archive/README.md` | Архивирование и удаление старых документов | active | -`docs/plan-domain.local.md` исключён из git через `.gitignore` (выбранное имя -домена не должно попасть в историю до покупки). Ссылки на него в `plan-seo.md` и -`backlog.md` при клонировании репозитория не разрешаются — это ожидаемо. +`docs/plan-domain.local.md` **исключён из git** через `.gitignore`: выбранное +имя домена не должно попасть в историю до покупки. В клоне файла нет — это +ожидаемо, и ссылки на него в `plan-seo.md` и `backlog.md` не разрешаются. Строка +в таблице оставлена, чтобы задачу R1/R2 можно было найти по индексу; сам +чек-лист лежит только на машине разработчика. ## Правила @@ -46,11 +49,22 @@ `docs/commands.md` или `docs/known-issues.md`: команды принадлежат `quality-gates`, известные проблемы — backlog и checklist. `README.md` в корне остаётся кратким обзором продукта, а не вторым руководством агента. -- Ссылаясь на инструмент по id, сверять id с реестром (`web/src/lib/registry/`): - исторические названия в старых планах не действуют. - `docs/backlog.md` содержит только открытые задачи: выполненные удаляются, а критичные для проекта факты из них переносятся в тематический документ. - `docs/archive/` — временная историческая справка, не источник критериев приёмки; срок хранения 30 дней, файлы восстановимы из git history. + Единственный документ в архиве со статусом `active` — + `docs/archive/README.md`: он описывает процедуру архивирования, а не архивный + материал, поэтому не подлежит 30-дневному удалению. +- Ссылаясь на инструмент по id, сверять id с реестром (`web/src/lib/registry/`): + исторические названия в старых планах не действуют. Сейчас `id` записи — это + одновременно адрес страницы `/tools/`, отдельного поля `slug` нет + (`docs/architecture.md`, раздел 3). +- Поиск по `docs/` задевает `docs/archive/` (объём больше, чем у активных + документов вместе). Для правок production-кода архив не нужен: grep по + `docs/*.md` без `archive/`. +- Проверка ссылок в документации не автоматизирована; ожидаемо неразрешимыми + считаются ссылки на `docs/plan-domain.local.md` (файл вне git). Всё остальное + неразрешимое — ошибка. - Протокол «остановиться и показать изменения» — `docs/agent-workflow.md`, раздел 6. diff --git a/docs/architecture.md b/docs/architecture.md index 8dcd385..025c6a9 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -23,7 +23,7 @@ web/src/lib/ web/src/routes/ +page.svelte # главная list-tools/ # каталог - tools/[id]/ # страница инструмента + tools/[id]/ # страница инструмента (адрес = id записи) kit/ # витрина компонентов (production, но исключена из i18n-гейта) ``` @@ -32,6 +32,21 @@ web/src/routes/ `registry/**` описывает данные и знает только `core/**` и `registry-schema.ts`. Нарушение этого порядка — повод не заводить импорт, а инвертировать зависимость. +### Чего в коде нет + +Страница инструмента работает ровно с одним инструментом: загрузил файл → +применил одну запись реестра → скачал результат. Отсутствуют: + +- **Пайплайн / цепочки шагов** — модуля нет, состояния нет, localStorage для + него нет. `docs/roadmap.md` описывает его как отдельную фазу, а не как + поставленное. Под будущую фазу зарезервированы `components/StepCard.svelte` + (сейчас импортируется только витриной `/kit`) и ключи `chain.*`, + `errors.badPipelineShape`, `errors.noSteps`. +- **Разделения `id` и `slug`** — раздел 3. + +Задачи по обоим пунктам — в `docs/backlog.md`; архитектурные решения по +пайплайну — `docs/roadmap.md`. + ## 2. Поток данных ```txt @@ -62,8 +77,8 @@ registry/*.ts ──(TOOLS: ToolEntry[]) Ключевые решения: -- **Реестр — единственный источник истины.** Страница, форма и пайплайн строятся - из записи; новый инструмент = новая запись + функция `run`. +- **Реестр — единственный источник истины.** Страница и форма строятся из + записи; новый инструмент = новая запись + функция `run`. - **Исполнение идёт только через `executor.execute`.** Компоненты не зовут `tool.run` напрямую — иначе нельзя перенести тяжёлое в worker/wasm без правки вызывающего кода. @@ -76,22 +91,35 @@ registry/*.ts ──(TOOLS: ToolEntry[]) `ToolEntry` (`web/src/lib/registry/types.ts`): -| Поле | Смысл | -| ------------- | ------------------------------------------------------------ | -| `id` | уникальный ключ; он же URL-anchor и ключ в пайплайне | -| `title` | EN-строка реестра, переводится через `tools.*.title` | -| `description` | EN-строка реестра, переводится через `tools.*.description` | -| `category` | id из `categories.ts` | -| `schema` | `toolSchema({ fields, layout?, meta? })` | -| `input` | `"image" \| "text" \| "none"` — что ждёт инструмент на входе | -| `result` | `"image" \| "text" \| "verdict" \| "files"` — что отдаёт | -| `output` | mime/ext/quality для download (не у всех инструментов) | -| `run(ctx)` | чистая функция: `ctx` → `ToolResult` | +| Поле | Смысл | +| ------------- | ------------------------------------------------------------------------------------------------ | +| `id` | идентичность инструмента **и** публичный адрес `/tools/` **и** база имени скачиваемого файла | +| `title` | EN-строка реестра, переводится через `tools.*.title` | +| `description` | EN-строка реестра, переводится через `tools.*.description` | +| `category` | id из `categories.ts` | +| `schema` | `toolSchema({ fields, layout?, meta? })` | +| `input` | `"image" \| "text" \| "none"` — что ждёт инструмент на входе | +| `result` | `"image" \| "text" \| "verdict" \| "files"` — что отдаёт | +| `domOnly` | инструмент требует DOM (canvas); превью-executor запускает его напрямую, минуя worker | +| `output` | mime/ext/quality для download (не у всех инструментов) | +| `icon` | id иконки из `tool-icons.ts` | +| `run(ctx)` | единственный метод: `ctx` → `ToolResult` | + +Отдельного поля `slug` **нет**: адрес страницы, ключ i18n (`tools..*`) и имя +файла скачивания — это один и тот же `id`. Инструмент работает с любым +поддержанным форматом, но страница держит png-интент, поэтому `-png` живёт +внутри `id` (`id: "crop-png"` → `/tools/crop-png` → `crop-png.png`). Следствие: +переименование `id` меняет адрес страницы, ключи `tools.*` и имя файла. Хелперы `genTool` / `imgTool` / `textGen` из `types.ts` задают `run` для типовых случаев (приведение типа результата), чтобы запись не повторяла обвязку. `TOOLS` собирается в `registry/index.ts` из восьми групп; `getTool(id)` — единственный -способ достать запись по id. +способ достать запись, `registry.test.ts` проверяет уникальность `id`. + +Разделение `id` (внутреннее имя) и `slug` (адрес) — решённое, но **не +реализованное** решение: задача и порядок волн в `docs/backlog.md`, раздел +«Мелочи всякие». До её выполнения этот документ описывает текущее состояние, а +id и slug совпадают. ## 4. Схема параметров @@ -133,15 +161,16 @@ EN-ключей `tools.*` и словарь-переводчик. Инвариа ## 7. Точки расширения -| Задача | Где править | -| ------------------------------ | ----------------------------------------------------------------- | -| Новый инструмент | запись в `registry/.ts` + i18n-ключи + тесты (рецепт ниже) | -| Новый вид поля | `registry-schema.ts` + контрол + `FIELDS` (раздел 4) | -| Новый маршрут/страница | `web/src/routes/**` + ссылка в каталоге | -| Новый визуальный элемент | компонент в `components/**` по образцу `ui/` или `layout/` | -| Новый дизайн-токен | `web/src/app.css` (только там) + потребитель сразу | -| Тяжёлая операция → worker/wasm | `executor/**`, без правок компонентов | -| Мультифайловый результат | `result: "files"` + `zip.ts` | +| Задача | Где править | +| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Новый инструмент | запись в `registry/.ts` + i18n-ключи + тесты (рецепт ниже) | +| Смена `id` | запись реестра + i18n-ключи `tools.*` + `tool-icons.ts` + хардкод id в тестах, `/kit` и e2e; меняется адрес страницы — операция с SEO-последствиями, не часть обычной задачи | +| Новый вид поля | `registry-schema.ts` + контрол + `FIELDS` (раздел 4) | +| Новый маршрут/страница | `web/src/routes/**` + ссылка в каталоге | +| Новый визуальный элемент | компонент в `components/**` по образцу `ui/` или `layout/` | +| Новый дизайн-токен | `web/src/app.css` (только там) + потребитель сразу | +| Тяжёлая операция → worker/wasm | `executor/**`, без правок компонентов | +| Мультифайловый результат | `result: "files"` + `zip.ts` | ## 8. Рецепт: добавить инструмент @@ -150,22 +179,27 @@ EN-ключей `tools.*` и словарь-переводчик. Инвариа 2. **Выбрать группу** (`geometry`/`alpha`/`color`/`convert`/`filters`/ `generate`/`text`/`analyze`) и положить запись в её экспорт; при новой категории — сначала `categories.ts`. -3. **Описать схему** через `field.*`, задать `layout`, если поля нужно +3. **Задать `id`.** Он же адрес страницы, он же ключ i18n, он же база имени + скачиваемого файла. Страница держит png-интент, поэтому суффикс `-png` входит + в `id` (`crop-png`, `resize-png`) — это осознанно, отдельного поля `slug` в + реестре нет (раздел 3). +4. **Описать схему** через `field.*`, задать `layout`, если поля нужно сгруппировать. -4. **Написать `run`** поверх `core/*`; пиксельные операции — чистые функции в +5. **Написать `run`** поверх `core/*`; пиксельные операции — чистые функции в `core/`, без DOM. -5. **Проверить обязательные контракты** для нового id: entry попадает в `TOOLS`, - страница `/tools/` prerender-ится, `input`/`result` согласованы с тем, - что делает `run`. -6. **Добавить i18n-ключи во все локали** сразу. -7. **Тесты:** unit — в `registry/*.test.ts` или рядом с `core`-функцией; +6. **Проверить обязательные контракты** для новой записи: она попадает в + `TOOLS`, страница `/tools/` prerender-ится, `input`/`result` согласованы + с тем, что делает `run`. +7. **Добавить i18n-ключи во все локали** сразу (ключ — по `id`). +8. **Тесты:** unit — в `registry/*.test.ts` или рядом с `core`-функцией; e2e-smoke — существующий spec по типу `input`/`result` (правила — `docs/testing-strategy.md`). -8. **Обновить `docs/tools-map.md`:** новый инструмент обязателен в разделе - «Реализовано», формат строки — в шапке раздела. Проверяет - `web/src/lib/registry/tools-map-doc.test.ts`: отсутствующий в карте id и - несуществующий в реестре id роняют тест. Обоснование и границы автоматизации - — `docs/decisions.md`, раздел 4. +9. **Обновить `docs/tools-map.md`:** новая страница обязательна в разделе + «Реализовано», формат строки — в шапке раздела. Карта перечисляет **`id`** + реестра, которые одновременно являются адресами страниц. Проверяет + `web/src/lib/registry/tools-map-doc.test.ts`: id без инструмента и инструмент + без записи в карте роняют тест. Обоснование и границы автоматизации — + `docs/decisions.md`, раздел 4. Ожидаемый минимум проверок: `pnpm --dir web check` и `pnpm --dir web test`; для инструмента, меняющего пользовательский поток, — e2e (см. раздел 3 diff --git a/docs/archive/README.md b/docs/archive/README.md index 39054cc..5044904 100644 --- a/docs/archive/README.md +++ b/docs/archive/README.md @@ -1,7 +1,9 @@ # Архив документов > Статус: **active**. Здесь хранятся завершённые, отменённые и явно устаревшие -> документы как временная историческая справка. +> документы как временная историческая справка. Этот README — единственный +> документ архива со статусом `active`: он описывает процедуру, а не архивный +> материал, поэтому не подлежит 30-дневному удалению. ## Назначение @@ -36,8 +38,12 @@ 2. Убрать из него ссылки на несуществующие пути и артефакты прошлых волн. 3. Добавить обязательные метаданные. 4. Переместить файл в `docs/archive/`. -5. Проверить ссылки из backlog, планов, checklist и `docs/README.md`: удалённые - файлы должны потерять и входящие ссылки. +5. Найти оставшиеся входящие ссылки: + `git grep -n "" -- 'docs/*.md' AGENTS.md README.md web/eslint-plugins/README.md`. + Шаг 4 ломает их, и агент без этого шага напишет в новом документе ссылку на + удалённый файл. Ожидаемо неразрешимыми остаются ссылки на + `docs/plan-domain.local.md` — он вне git, это не ошибка (`docs/README.md`, + раздел «Правила»). 6. Не менять архивный документ под новые требования. ## Удаление diff --git a/docs/backlog.md b/docs/backlog.md index e09dcdc..d7f0d7d 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -24,6 +24,10 @@ ## Мелочи всякие +Порядок правок полей и раскладки — `docs/plan-fields-audit-fixes.md`, сами +находки («что плохо», с датой аудита) — `docs/tools-audit.md`. Здесь — как это +исправить; находка в аудите не отменяет задачу здесь. + - [ ] Пересмотреть тесты - исправить всякие хрупкие, которые проверяют количество инструментов, точное совпадение текстов, поиск по `img[alt="Result image"]`, svelte классам и тому подобные @@ -55,6 +59,9 @@ шрифты с кириллицей? сделать галочку "только с кириллицей"??? (решение о наборе и лицензиях: `docs/plan-platform.md` §4 — только OFL/Apache с паспортом, семейства с кириллицей) +- [ ] поле ввода текста - сделать по умолчанию нормального размера, а не одну + строку для svg - форматирование или подсветку синтаксиса??? для bin\hex - + форматирование по колонкам??? для hex\bytes\rgba - пример в placeholder - [ ] сделать загрузку картинки исходника по ctrl+v и drag-and-drop (dropzone) - [ ] square-mask-png - проверить работу - параметры неверно считаются. width - 100, height - 100, x - 100, y - 100, обрезает 50% на 50% картинку @@ -64,16 +71,32 @@ значения - [ ] для keep Aspect field - пересчитывать второе поле, учитывать какое было изменено -- [ ] поле ввода текста - сделать по умолчанию нормального размера, а не одну - строку для svg - форматирование или подсветку синтаксиса??? для bin\hex - - форматирование по колонкам??? для hex\bytes\rgba - пример в placeholder - [ ] обновить страницу kit или сделать storybook +- [ ] Слаги инструментов (`*-png`) — **развести `id` и адрес страницы.** + Инструменты работают с любым форматом, но называются `crop-png`, + `resize-png`; имя в коде, пайплайнах и i18n должно быть `crop`, `resize`, + а адрес и имя скачиваемого файла — прежними (`/tools/crop-png` → + `crop-png.png`). Решение и его SEO-последствия: `docs/plan-seo.md` §0; + текущее состояние (поля `slug` нет, роут — `tools/[id]`) — + `docs/architecture.md`, раздел 3. Порядок работ: 1. добавить `slug` в + `ToolEntry` + `toolSlug()` / `getToolBySlug()` в `registry/index.ts`, + проверку уникальности `slug` в `registry.test.ts`; 2. перевести + `routes/tools/[id]` → `[slug]` (`entries()`, `load()`, `+page.svelte`), + `ToolCard`, крошку в `+layout.svelte` и имя файла download в + `SchemaToolView` на `toolSlug(tool)`; старые адреса продолжают работать, + редиректы не нужны; 3. переименовать `id` волнами по группам реестра + (`convert`, `alpha`, `color`, `geometry`, `filters`, `analyze`, + `generate`, `text`); в каждой волне — `registry/.ts`, ключи + `tools.*` в `en.ts`/`ru.ts`, `tool-icons.ts`, захардкоженные id в тестах и + e2e (`smoke-i18n.test.ts`, `kit/+page.svelte`); 4. `docs/tools-map.md` при + этом **не меняется**: карта перечисляет id, а они остаются прежними как + адреса. Обратной совместимости не делаем: формат пайплайна ещё не + устоялся, старые экспорты и записи в localStorage после переименования + просто перестают открываться — это осознанно, миграция усложнила бы код + ради пары пользователей. - [ ] придумать процесс редактирования и настройки pipeline - drag-n-drop, удаление, добавление инструментов. переход один инструмент - pipeline без перезагрузки -- [ ] Слаги инструментов (`*-png`) — надо переименовть, они работают с любыми - изображениями. Надо сделать отдельный интерфейс маппинга инструмент -> - ссылка - [ ] `CatalogToolbar`: фильтры используют сырой `