From e77e4a2ab7b8c468b2485e88a09192729d64d9f6 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Sun, 31 May 2026 19:51:53 +0300 Subject: [PATCH] docs(ET-008): analyst artifacts - BRD, TRZ, AC, TestPlan --- docs/work-items/ET-008/00-business-request.md | 81 ++++- docs/work-items/ET-008/01-brd.md | 120 +++++++ docs/work-items/ET-008/02-trz.md | 281 ++++++++++++++++ .../ET-008/03-acceptance-criteria.md | 177 +++++++++++ docs/work-items/ET-008/04-test-plan.yaml | 300 ++++++++++++++++++ docs/work-items/ET-008/04b-ui-test-cases.md | 230 ++++++++++++++ 6 files changed, 1185 insertions(+), 4 deletions(-) create mode 100644 docs/work-items/ET-008/01-brd.md create mode 100644 docs/work-items/ET-008/02-trz.md create mode 100644 docs/work-items/ET-008/03-acceptance-criteria.md create mode 100644 docs/work-items/ET-008/04-test-plan.yaml create mode 100644 docs/work-items/ET-008/04b-ui-test-cases.md diff --git a/docs/work-items/ET-008/00-business-request.md b/docs/work-items/ET-008/00-business-request.md index 3d17c0e..753c205 100644 --- a/docs/work-items/ET-008/00-business-request.md +++ b/docs/work-items/ET-008/00-business-request.md @@ -1,7 +1,80 @@ -# Business Request: Smoke test analyst integration +--- +type: business-request +work_item_id: ET-008 +title: "Smoke test analyst integration" +created_at: 2026-05-31 +source: pipeline-smoke +requester: claude-bot +synthetic: true +--- -Work Item ID: ET-008 +# Бизнес-запрос — ET-008 (Smoke test analyst integration) -## Description +## Контекст -TBD +Это **smoke-работа** для проверки интеграции аналитика в пайплайн +`analyst → architect → coder → tester`. Реального заказчика нет; +запрос синтезирован, чтобы проверить, что: + +1. Аналитик умеет создать полный пакет артефактов + (BRD / TRZ / AC / test-plan / UI test cases) без ручного вмешательства. +2. Архитектор может декомпозировать ТЗ в исполнимый план. +3. Кодер может реализовать минимальное изменение по плану. +4. Тестировщик может прогнать функциональные и Playwright-тесты, + и автоматически закрыть задачу. + +В отличие от ET-007 (dry-run по реальной фиче), ET-008 — это **smoke**: +скоуп ещё уже, никакого нового UX-функционала для пользователя нет, +только технический маркер, видимый Playwright-у. + +Требования к синтетическому скоупу (жёстче, чем у ET-007): + +- Изменение исключительно во фронтенде (`src/web/index.html`, + `src/web/app.css`). JavaScript **не трогаем**. +- Не ломает существующий функционал: карта, темы, роутинг, GPX, рельеф + (hillshade/TRI), POI, разведка, линейка, единицы измерения, поиск, + переключатели слоёв. +- Виден Playwright-у при специальном условии (`?smoke=et-008` в URL), + но **невидим** обычному пользователю при чистой загрузке. +- Тривиально откатывается: одна `
` в `index.html` + один CSS-блок. +- Не зависит от сети, БД, времени, пользовательских действий. + +## Исходная формулировка + +> Нужен невидимый по умолчанию DOM-маркер, который сигнализирует, что +> текущая сборка прошла полный конвейер аналитик → архитектор → кодер → +> тестировщик. Маркер должен появляться в углу карты только когда в +> URL присутствует параметр `?smoke=et-008` (или хеш `#smoke=et-008`). +> Это нужно автоматическим тестам пайплайна — они проверяют, что +> deploy на test содержит сборку правильного work-item, и что фронтенд +> отвечает на разметку без падений. + +## Уточнения (приняты по умолчанию для smoke) + +1. Видимый идентификатор маркера: `#pipeline-smoke`. +2. Текст маркера (на русском): «ET-008 ✓». +3. Позиция: левый нижний угол экрана (не конфликтует с + `#map-controls-r` справа, с `bottom-sheet` снизу-по центру, с + `.maplibregl-ctrl-attrib` справа-внизу). Конкретно — `left: 8px; + bottom: 8px`. +4. Размер: 11px шрифт, нижний регистр, полупрозрачный фон, нейтральный + тёмно-серый цвет; не должен закрывать ничего важного даже если + как-то стал видимым случайно. +5. Условие отображения: маркер присутствует в DOM **всегда**, но имеет + `display: none` по умолчанию. Видим становится, когда у `` + есть класс `smoke-mode`. Класс ставится автоматически инлайн-скриптом + в ``, если `location.search` содержит `smoke=et-008` ИЛИ + `location.hash` содержит `smoke=et-008`. +6. Не использовать `localStorage`. Маркер ничего не сохраняет — + только реагирует на URL текущего хита. +7. Доступность: `aria-hidden="true"`, `role="presentation"` — маркер + технический, не должен попадать в screen reader. +8. Семантика body-класса: имя `smoke-mode` зарезервировано **только** + за этим work item. Если в будущем понадобятся аналогичные маркеры + для других work items — расширяем семантику тем же классом, но с + дополнительными data-атрибутами. +9. Backend / БД / тайл-эндпоинты / OSRM / app.js / units.js / gpx.js + **не затрагиваются**. +10. Тёмная и светлая темы: маркер использует одинаковые цвета в обеих + темах (тёмный фон + светлый текст), читаемость гарантируется + собственными цветами, а не наследованием от темы. diff --git a/docs/work-items/ET-008/01-brd.md b/docs/work-items/ET-008/01-brd.md new file mode 100644 index 0000000..11be77e --- /dev/null +++ b/docs/work-items/ET-008/01-brd.md @@ -0,0 +1,120 @@ +--- +type: brd +work_item_id: ET-008 +title: "BRD: Smoke test analyst integration" +version: 1 +status: draft +created_at: 2026-05-31 +updated_at: 2026-05-31 +authors: + - "agent:analyst" +--- + +# BRD — ET-008: Smoke test analyst integration + +## 1. Цель + +Подтвердить, что цепочка агентов `analyst → architect → coder → tester` +работоспособна **end-to-end**: аналитик выдаёт валидные артефакты, +архитектор по ним строит план, кодер минимально его реализует, +тестировщик прогоняет автотесты (включая Playwright) и автоматически +закрывает задачу. + +Полезной фичи для конечного пользователя нет — это намеренно +технический smoke. Минимальное изменение во фронтенде нужно лишь как +«отпечаток сборки», который Playwright увидит и подтвердит. + +## 2. Контекст + +- Веб-приложение: MapLibre GL JS 4.7 + vanilla JS, без фреймворка. +- Базовая страница: `src/web/index.html`; стили — `src/web/app.css`; + логика — `src/web/app.js` (НЕ ТРОГАТЬ в рамках ET-008). +- ET-007 (Спутниковая карта) уже использовал такую же idea-pipeline + для dry-run; ET-008 — следующая итерация, ещё минимальнее: ноль JS, + ноль внешних зависимостей, ноль localStorage. +- Имеется работающая Playwright-инфра (`tests/web/e2e/`), которая + умеет открывать тест-окружение и снимать скриншоты. + +## 3. Scope + +### In scope + +| # | Функция | +|------|------------------------------------------------------------------------------------------------------| +| F-01 | DOM-элемент `#pipeline-smoke` с текстом «ET-008 ✓» в `src/web/index.html` | +| F-02 | CSS-правила для `#pipeline-smoke` в `src/web/app.css` (скрыт по умолчанию) | +| F-03 | CSS-правила для `body.smoke-mode #pipeline-smoke` (видим в smoke-режиме) | +| F-04 | Инлайн-скрипт в `` `src/web/index.html`, добавляющий `smoke-mode` к `` по URL-условию | +| F-05 | Условие активации: `location.search.includes('smoke=et-008')` ИЛИ `location.hash.includes('smoke=et-008')` | +| F-06 | По умолчанию (без параметра) маркер физически в DOM, но `display:none` | +| F-07 | Маркер `aria-hidden="true"` / `role="presentation"` — не попадает в screen reader | +| F-08 | Позиционирование: `position: fixed; left: 8px; bottom: 8px; z-index` ниже sheets/popup'ов | +| F-09 | Совместимость с тёмной и светлой темами — собственные цвета, не наследует темовые переменные | + +### Out of scope + +- JavaScript-логика в `src/web/app.js`, `units.js`, `gpx.js`. +- Любой backend / БД / OSRM / тайлы. +- Сохранение состояния (localStorage / sessionStorage / cookies). +- Видимость по нажатию кнопки / shortcut'у клавиатуры / тапу — только URL. +- Локализация (текст «ET-008 ✓» одинаков для всех языков). +- Анимации появления / скрытия. +- Управление через query API (REST/IPC). +- Мобильный layout-tuning (маркер одинаков на desktop и mobile). +- Любые другие work item identifiers, кроме `et-008`. + +## 4. Метрики успеха + +| Метрика | Критерий | +|-----------------------------------------------|-----------------------------------------------------------------------------------------| +| Наличие маркера в DOM | На любой загрузке `document.querySelector('#pipeline-smoke')` не null | +| Скрытость по умолчанию | На `?` (без параметра) `getComputedStyle(...).display === 'none'` | +| Видимость в smoke-режиме | На `?smoke=et-008` или `#smoke=et-008` маркер визуально различим в левом нижнем углу | +| Контент маркера | `textContent.trim() === 'ET-008 ✓'` | +| Корректность ARIA | `aria-hidden="true"`, `role="presentation"` | +| Отсутствие конфликтов | Маркер не перекрывает `#map-controls-r`, sheets, `.maplibregl-ctrl-attrib` | +| Стабильность тем | После `toggleTheme()` маркер остаётся видим/скрыт согласно своему правилу | +| Отсутствие регрессий | Все существующие E2E (ET-001..ET-007) остаются зелёными | +| Время от клика до отображения | После загрузки страницы маркер показан **до** `DOMContentLoaded` end (инлайн-скрипт) | +| Отсутствие сетевых запросов | ET-008 не порождает ни одного нового HTTP-запроса | +| Откатываемость | Полный откат — 3 диффа (HTML head + HTML body + CSS блок), 1 коммит | + +## 5. Риски + +| Риск | Вероятность | Влияние | Митигация | +|---------------------------------------------------------------------|-------------|---------|------------------------------------------------------------------------------------| +| Инлайн-скрипт в `` ломает CSP | Низкая | Среднее | CSP не настроен сейчас. Если когда-то будет — переключить на data-атрибут + CSS-only| +| `#pipeline-smoke` перекрывает важный UI (например `.maplibregl-ctrl-scale`) | Низкая | Низкое | `z-index: 1` — ниже всех плавающих контролов; позиция фиксирована подальше | +| Маркер случайно засветился пользователю (например shared link с `?smoke=et-008`) | Низкая | Низкое | Текст нейтральный, не раскрывает ничего внутреннего; стиль ненавязчивый | +| Body-класс `smoke-mode` конфликтует с будущим классом темы | Низкая | Низкое | Префикс `smoke-` зарезервирован; в проекте сейчас нет похожих имён | +| ARIA-атрибуты «protect» сломаются при mutation observer на body | Низкая | Низкое | `aria-hidden` ставится статически в HTML, не из JS | +| Маркер ломает Playwright-снимки других тестов | Низкая | Низкое | По умолчанию `display:none` — на скриншоте не виден, BB-rect = 0 | +| Лишний div снижает производительность DOM | Очень низкая| Очень низкое| 1 элемент, без подписок, без обработчиков | +| Старые браузеры не поддерживают `includes` на строках | Очень низкая| Низкое | `String.prototype.includes` — ES2015, поддержано во всех целевых браузерах | + +## 6. Зависимости + +- **Внешние сервисы**: нет. +- **Внутренние**: только `src/web/index.html`, `src/web/app.css`. +- Не зависит от ET-005 / ET-006 / ET-007. +- Не блокирует ни одну фазу (PH-1..PH-9). +- Не вносит изменений в `app.js`, `units.js`, `gpx.js`. +- Не меняет `style.json`, `style-dark.json`. +- Backend, БД, OSRM, миграции, контейнеры — не затрагиваются. +- CI/CD — не меняется. Только новые E2E-тесты для самого маркера в + `tests/web/e2e/pipeline-smoke.spec.ts`. + +## 7. Критерии smoke-успеха (для пайплайна) + +Эта работа считается завершённой, когда: + +1. Все 5 артефактов аналитика (`00`..`04b`) присутствуют и валидны. +2. Архитектор выдаёт минимум один план в `05-architecture.md` или + эквивалент. +3. Кодер вносит изменения только в `src/web/index.html` + + `src/web/app.css` (по diff'у видно). +4. Все тесты UT/IT/E2E зелёные на test-окружении. +5. Tester автоматически закрывает задачу. + +Само наличие зелёного smoke-прогона важнее, чем визуальная +эстетика маркера. diff --git a/docs/work-items/ET-008/02-trz.md b/docs/work-items/ET-008/02-trz.md new file mode 100644 index 0000000..8e50570 --- /dev/null +++ b/docs/work-items/ET-008/02-trz.md @@ -0,0 +1,281 @@ +--- +type: trz +work_item_id: ET-008 +title: "ТЗ: Smoke test analyst integration" +version: 1 +status: draft +created_at: 2026-05-31 +updated_at: 2026-05-31 +authors: + - "agent:analyst" +depends_on: + - "ET-008/01-brd.md" +--- + +# Техническое задание — ET-008: Smoke test analyst integration + +## 1. Общая архитектура изменений + +Изменение строго фронтовое и максимально минимальное. Затрагиваются +**ровно два файла**: + +- `src/web/index.html` + - В `` добавить инлайн-скрипт, который выставляет + `document.body.classList.add('smoke-mode')`, если в URL присутствует + `smoke=et-008` (в `search` или `hash`). + - В `` (рядом с `
` или сразу перед ``) + добавить элемент ``. +- `src/web/app.css` + - В конец файла добавить блок с правилами для `#pipeline-smoke`. + +**Запрещено** трогать: `src/web/app.js`, `src/web/units.js`, +`src/web/gpx.js`, `src/web/style.json`, `src/web/style-dark.json`, +`src/api/**`, `tests/api/**`, миграции, Docker-конфигурацию. + +## 2. Функциональные требования + +### REQ-F-01. DOM-маркер `#pipeline-smoke` + +В `src/web/index.html` добавить элемент: + +```html + +``` + +Размещение: после `
` (т.е. внутри ``, +сразу после карты), но **до** ``. Конкретное место — +после блока `
` или эквивалентного места, +где сейчас лежат «свободно плавающие» элементы (`#ruler-toast`, +`#app-toast`). + +Текст узла: ровно `ET-008 ✓` (без кавычек, с одним пробелом перед +галочкой, U+2713 CHECK MARK). + +### REQ-F-02. Инлайн-скрипт активации в `` + +В `` `src/web/index.html`, **после** `` +и **до** закрывающего ``, добавить: + +```html + +``` + +Замечания: +- Скрипт ставит класс на `` (`documentElement`), а не на + ``, потому что на момент выполнения (в ``) `` + ещё не существует. Эквивалентный селектор для CSS — + `html.smoke-mode #pipeline-smoke`. Это требование к CSS-блоку + (см. REQ-F-04). +- `try/catch` обязателен — если по какой-то причине `location` + не доступен (тест с jsdom без URL), скрипт не должен ронять + страницу. +- Скрипт **синхронный**, не модуль, без `defer`/`async` — он + должен сработать до того, как CSS попытается применить + `display:none` к видимому в smoke маркеру (избежать FOUC). + +### REQ-F-03. CSS базовое состояние (скрыт) + +В конец `src/web/app.css` добавить: + +```css +/* ── ET-008: pipeline smoke marker ─────────────────────────── + По умолчанию полностью скрыт. Включается классом .smoke-mode + на , который ставит инлайн-скрипт в , если + в URL присутствует ?smoke=et-008 или #smoke=et-008. + ──────────────────────────────────────────────────────────── */ +#pipeline-smoke { + display: none; +} +``` + +### REQ-F-04. CSS активное состояние (видим) + +Сразу после REQ-F-03 в `src/web/app.css`: + +```css +html.smoke-mode #pipeline-smoke { + display: inline-block; + position: fixed; + left: 8px; + bottom: 8px; + z-index: 1; + padding: 2px 6px; + font: 11px/1.4 system-ui, -apple-system, sans-serif; + color: #e7e7e7; + background: rgba(20, 20, 28, 0.7); + border-radius: 4px; + pointer-events: none; + user-select: none; + letter-spacing: 0.02em; +} +``` + +Значения цвета и фона **не зависят** от темы — это намеренно, чтобы +маркер был стабильно читаем и в светлой, и в тёмной теме без отдельных +правил `body.theme-dark`. + +### REQ-F-05. Условие активации + +Маркер показывается, если **любое** из условий выполнено: + +- `location.search` (часть URL после `?`) содержит подстроку + `smoke=et-008`; +- `location.hash` (часть URL после `#`) содержит подстроку + `smoke=et-008`. + +Сравнение **точное**, чувствительно к регистру. Любое отклонение +(`smoke=ET-008`, `smoke=et_008`, `smoke=et-007`, `smoketest=et-008`) +**не** активирует маркер. + +### REQ-F-06. Не-конфликтность с темами + +После `toggleTheme()` маркер: +- если был видим (smoke-mode) — остаётся видимым с теми же цветами; +- если был скрыт (no smoke-mode) — остаётся скрытым. + +То есть body-класс `theme-dark` не влияет на отображение +`#pipeline-smoke`. + +### REQ-F-07. Не-конфликтность с layout + +`z-index: 1` ниже, чем у `#map-controls-r` (фактический z-index у +существующих контролов — выше). Маркер не должен: +- перекрывать `#map-controls-r` (top-right); +- перекрывать `.maplibregl-ctrl-attrib` (bottom-right); +- мешать `#toolbar` на мобильном (нижняя панель); +- перекрывать любой `.bottom-sheet`, когда тот открыт. + +В частности на мобильном бутылочное горлышко — `#toolbar` снизу. +Маркер в `left: 8px; bottom: 8px` помещается слева, тулбар обычно +центрирован/растянут, так что небольшой риск перекрытия допустим, +но визуально не критичен (маркер маленький и полупрозрачный). + +### REQ-F-08. ARIA + +- `aria-hidden="true"` — обязательно. +- `role="presentation"` — обязательно. +- Никаких подсказок (`title`), `aria-label`, фокусируемых элементов + внутри. + +### REQ-F-09. Отсутствие сетевых эффектов + +Реализация не должна: +- добавлять `` / `