analyst(ET): auto-commit from analyst run_id=6
All checks were successful
CI / lint (push) Successful in 20s
CI / test (push) Successful in 59s
CI / build (push) Successful in 1m49s

This commit is contained in:
2026-06-14 01:26:41 +03:00
parent 9088b28edb
commit f27d503301
4 changed files with 344 additions and 161 deletions

View File

@@ -1,123 +1,103 @@
---
type: trz
work_item_id: ET-001
title: "ТЗ: Исключить шлагбаумы и тротуары из OSRM"
version: 1
status: approved
created_at: 2026-05-15
authors:
- "agent:stream"
title: "ТЗ: Чекбокс показа/скрытия POI в кнопке рельефа"
version: 2
status: proposed
created_at: 2026-06-14
author: "agent:analyst"
relates_to: ET-002
---
# Техническое задание — ET-001
# Техническое задание — ET-001: Видимость POI
## 1. Что менять
> Поведение, описанное ниже, **уже реализовано в рамках ET-002**. ТЗ
> служит спецификацией для **верификации** существующей реализации плюс
> единственной новой правки — подписи чекбокса (REQ-F-01). Описание
> текущей реализации приведено как **контекст для тестирования**, а не
> как предлагаемая архитектура.
### Файл: OSRM профиль `enduro.lua`
## 1. Функциональные требования
Расположение на сервере: `/home/slin/enduro-trails/osrm/enduro.lua`
В репо: `infra/osrm/enduro.lua` (скопировать текущий + внести изменения)
### REQ-F-01 — Подпись чекбокса «Показывать POI» (НОВАЯ ПРАВКА)
- В попапе рельефа (`#terrain-popup`) чекбокс `#poi-visible-cb` должен
иметь текстовую подпись **«Показывать POI»**.
- Текущее состояние: подпись — «POI» (`src/web/index.html`, узел
`<span>` рядом с `#poi-visible-cb`).
- Приёмка: видимый текст подписи равен «Показывать POI»; layout попапа не
ломается (одна строка, без обрезки) на desktop и mobile.
#### Изменение 1: process_node — блокировка шлагбаумов
### REQ-F-02 — Чекбокс присутствует в попапе рельефа
- Чекбокс находится внутри `#terrain-popup`, открываемого кнопкой
`#terrain-toggle` (`toggleTerrainPopup()`).
В функции `process_node` заменить текущую обработку barriers:
### REQ-F-03 — Включён по умолчанию
- При первом заходе (ключ `localStorage['poi-visible']` отсутствует)
чекбокс отмечен, POI видны.
```lua
-- Блокируемые типы препятствий (полный запрет проезда)
local blocked_barriers = {
gate = true,
bollard = true,
lift_gate = true,
chain = true,
cycle_barrier = true,
motorcycle_barrier = true,
border_control = true,
block = true,
}
### REQ-F-04 — Снятие чекбокса скрывает POI
- Снятие `#poi-visible-cb` скрывает все маркеры POI: слои `poi-circles`
и `poi-labels` получают `visibility: none`.
function process_node(profile, node, result)
local barrier = node:get_value_by_key("barrier")
if barrier and blocked_barriers[barrier] then
result.barrier = true
result.forward_mode = mode.inaccessible
result.backward_mode = mode.inaccessible
return
end
end
```
### REQ-F-05 — Установка чекбокса возвращает POI
- Обратная установка возвращает `visibility: visible` тем же слоям.
#### Изменение 2: process_way — исключение тротуаров
### REQ-F-06 — Персистентность между сессиями
- Выбор сохраняется в браузере и применяется при следующей загрузке
страницы (наблюдаемо: после перезагрузки состояние совпадает).
В начале функции `process_way`, после получения highway, добавить:
### REQ-F-07 — Устойчивость к смене темы
- Смена темы (`#btn-theme`, пересоздание стиля карты) не сбрасывает
выбранную видимость POI; чекбокс и слои остаются в согласованном
состоянии.
```lua
-- Исключаемые типы дорог (тротуары, пешеходные зоны)
local excluded_highways = {
footway = true,
pedestrian = true,
steps = true,
corridor = true,
}
## 2. Нефункциональные требования
-- В process_way, после local highway = way:get_value_by_key("highway"):
if excluded_highways[highway] then return end
```
### REQ-NF-01 — Без новых зависимостей
- Реализация остаётся клиентской, без новых npm/python пакетов
(ограничение инфраструктуры, ET-002 `07-infra-requirements.md`).
Также удалить `footway`, `pedestrian`, `steps` из таблицы `highway_rate` (если есть).
### REQ-NF-02 — Без изменения серверного контракта
- Эндпоинты `/api/tiles/{z}/{x}/{y}.mvt` и слой `poi` в MVT не меняются.
Управление видимостью — только переключение `visibility` слоёв
MapLibre на клиенте.
## 2. Пересборка графа
### REQ-NF-03 — Согласованность состояния
- Единый источник истины в рантайме — `layerState.poi`; чекбокс,
`localStorage` и фактическая видимость слоёв не расходятся.
После изменения lua-профиля — пересобрать граф:
## 3. Текущая реализация (контекст для верификации)
```bash
cd /home/slin/enduro-trails/osrm
docker run --rm -v $(pwd):/data ghcr.io/project-osrm/osrm-backend:latest osrm-extract -p /data/enduro.lua /data/enduro.osm.pbf
docker run --rm -v $(pwd):/data ghcr.io/project-osrm/osrm-backend:latest osrm-partition /data/enduro.osrm
docker run --rm -v $(pwd):/data ghcr.io/project-osrm/osrm-backend:latest osrm-customize /data/enduro.osrm
docker restart osrm-osrm-routed-1
```
> Информативно. Изменять требуется только подпись (REQ-F-01).
Время: ~40 мин (extract) + ~5 мин (partition + customize).
- `src/web/index.html`
- стр. ~8689: `<input type="checkbox" id="poi-visible-cb"
onchange="onPoiCheckbox()" checked>` и `<span>POI</span>` внутри
`#terrain-popup`.
- `src/web/app.js`
- `layerState.poi` (стр. ~406) и `layerGroups.poi = ['poi-circles',
'poi-labels']` (стр. ~410).
- `applyPoiVisibility(visible)` — переключает `visibility` слоёв POI и
синхронизирует `layerState.poi`.
- `onPoiCheckbox()` — пишет `localStorage['poi-visible']` ('1'/'0') и
вызывает `applyPoiVisibility()`.
- `restorePoiState()` — восстановление при загрузке и после смены темы;
дефолт (ключ отсутствует или '1') — POI видимы.
- Блок-маркеры `>>> ET-002 POI visibility block <<<`.
- ADR: `docs/work-items/ET-002/06-adr/adr-0001-poi-visibility-client-side.md`.
## 3. Что добавить в репо
## 4. Объём изменений для ET-001
1. `infra/osrm/enduro.lua` — обновлённый профиль
2. `scripts/rebuild-osrm.sh` — скрипт пересборки графа
3. `tests/integration/test_routing_barriers.py` тесты
1. `src/web/index.html`: заменить текст подписи `<span>POI</span>` →
`<span>Показывать POI</span>` у `#poi-visible-cb`.
2. Синхронно обновить unit-тест, если он проверяет текст подписи
(`tests/unit/poi_toggle.test.js`).
3. Прогнать регрессию по REQ-F-02…REQ-F-07 (поведение ET-002 не должно
измениться).
## 4. Тесты
## 5. Зависимости и ограничения
### Unit/Integration тесты (pytest + httpx)
```python
# tests/integration/test_routing_barriers.py
import pytest
from httpx import AsyncClient, ASGITransport
from src.api.main import app
OSRM_URL = "http://172.22.0.1:5559"
@pytest.mark.asyncio
async def test_route_avoids_barrier():
"""Маршрут через точку с известным шлагбаумом должен обходить его"""
# Точка с шлагбаумом: 55.7558, 37.6173 (пример)
# Тест проверяет что маршрут не проходит через эту ноду
pass # Architect определит конкретные координаты
@pytest.mark.asyncio
async def test_route_no_footway():
"""Маршрут в городе не должен проходить по тротуарам"""
pass # Architect определит конкретные координаты
@pytest.mark.asyncio
async def test_route_allows_cattle_grid():
"""Маршрут через cattle_grid должен работать (не заблокирован)"""
pass
```
## 5. Ограничения
- НЕ менять веса существующих дорог (только добавить блокировку)
- НЕ трогать scenic/link/recon логику
- cattle_grid и ford — НЕ блокировать
- Пересборка графа — отдельный ручной шаг (не в CI)
- Не править артефакты ET-002 и заархивированной барьерной задачи.
- Не закрывать ET-001 самостоятельно — закрытие за Owner/CI.
- Если Owner решит, что переименование не нужно — ТЗ аннулируется,
ET-001 закрывается как дубликат ET-002 (см. `09-analyst-decision-required.md`).

View File

@@ -1,33 +1,72 @@
---
type: acceptance-criteria
work_item_id: ET-001
version: 1
status: approved
title: "Критерии приёмки: Чекбокс показа/скрытия POI"
version: 2
status: proposed
created_at: 2026-06-14
author: "agent:analyst"
relates_to: ET-002
---
# Acceptance Criteria — ET-001
# Критерии приёмки — ET-001: Видимость POI
## AC-1: Шлагбаумы заблокированы в профиле
- [ ] В `enduro.lua` функция `process_node` блокирует ноды с barrier=gate|bollard|lift_gate|chain|cycle_barrier|motorcycle_barrier|border_control|block
- [ ] Блокировка через `mode.inaccessible` (не penalty)
- [ ] `cattle_grid` и `ford` НЕ заблокированы
Формат Given/When/Then. Среда проверки: test
(`https://openclaw.mva154.duckdns.org/enduro/`). Большинство критериев
(AC-02…AC-08) — **регрессия** уже поставленного в ET-002 поведения;
AC-01 — **новая дельта** (подпись).
## AC-2: Тротуары исключены из графа
- [ ] В `enduro.lua` функция `process_way` пропускает highway=footway|pedestrian|steps|corridor
- [ ] Эти типы удалены из `highway_rate` (если были)
## AC-01 — Подпись «Показывать POI» (новая дельта, REQ-F-01)
- **Given** открытое приложение.
- **When** пользователь нажимает `#terrain-toggle`.
- **Then** в `#terrain-popup` виден чекбокс `#poi-visible-cb` с подписью
ровно **«Показывать POI»**; подпись помещается в одну строку, layout
попапа не сломан.
## AC-3: Скрипт пересборки
- [ ] `scripts/rebuild-osrm.sh` — рабочий скрипт для пересборки графа
- [ ] Скрипт содержит extract + partition + customize + restart
## AC-02 — Чекбокс включён по умолчанию (REQ-F-03)
- **Given** первый заход (нет ключа `poi-visible` в localStorage).
- **When** открыт попап рельефа.
- **Then** `#poi-visible-cb` отмечен (checked), маркеры POI видны на карте.
## AC-4: Тесты
- [ ] Минимум 3 integration теста в `tests/integration/test_routing_barriers.py`
- [ ] Тесты проходят (pytest green)
## AC-03 — Снятие чекбокса скрывает POI (REQ-F-04)
- **Given** открытый попап, POI видны.
- **When** пользователь снимает `#poi-visible-cb`.
- **Then** все маркеры POI (`poi-circles`, `poi-labels`) исчезают с карты.
## AC-5: Lint
- [ ] `ruff check src/` — 0 ошибок
- [ ] Lua-файл синтаксически корректен
## AC-04 — Установка чекбокса возвращает POI (REQ-F-05)
- **Given** POI скрыты чекбоксом.
- **When** пользователь снова отмечает `#poi-visible-cb`.
- **Then** маркеры POI снова отображаются на карте.
## AC-6: Обратная совместимость
- [ ] Существующие маршруты (без шлагбаумов/тротуаров) строятся как раньше
- [ ] API `/api/route` и `/api/route` (POST) работают без изменений
## AC-05 — Сохранение состояния «скрыто» после перезагрузки (REQ-F-06)
- **Given** пользователь снял чекбокс (POI скрыты).
- **When** страница перезагружается.
- **Then** POI не отображаются сразу после загрузки, а `#poi-visible-cb`
при открытии попапа — снят.
## AC-06 — Сохранение состояния «показано» после перезагрузки (REQ-F-06)
- **Given** чекбокс отмечен (POI видны).
- **When** страница перезагружается.
- **Then** POI видны, чекбокс отмечен.
## AC-07 — Устойчивость к смене темы (REQ-F-07)
- **Given** POI скрыты чекбоксом.
- **When** пользователь переключает тему (`#btn-theme`).
- **Then** POI остаются скрытыми, `#poi-visible-cb` остаётся снятым.
## AC-08 — Согласованность состояния (REQ-NF-03)
- **Given** любое из действий выше.
- **Then** значение чекбокса, `localStorage['poi-visible']`
('1'/'0') и фактическая видимость слоёв POI не противоречат друг другу.
## AC-09 — Регрессия unit-тестов POI
- **Given** ветка с правкой подписи.
- **When** запускается `make test`.
- **Then** `tests/unit/poi_toggle.test.js` и
`tests/unit/test_poi_toggle.py` проходят (с обновлённым ожиданием
текста подписи, если оно проверяется).
## AC-10 — Без побочных эффектов на сервере (REQ-NF-02)
- **Given** переключение чекбокса.
- **Then** запросы к `/api/tiles/.../*.mvt` и серверная отдача слоя `poi`
не меняются; видимость управляется только на клиенте.

View File

@@ -1,41 +1,204 @@
work_item_id: ET-001
version: 1
# Test Plan — ET-001: Чекбокс показа/скрытия POI в кнопке рельефа
# ВНИМАНИЕ: функциональность уже поставлена в ET-002. Этот план —
# верификация/регрессия существующей реализации + проверка одной новой
# дельты (подпись «Показывать POI», REQ-F-01). UI-кейсы — в 04b-ui-test-cases.md.
# Среда e2e/ui: https://openclaw.mva154.duckdns.org/enduro/
work_item: ET-001
version: 2
relates_to: ET-002
related_acs: [AC-01, AC-02, AC-03, AC-04, AC-05, AC-06, AC-07, AC-08, AC-09, AC-10]
tests:
- id: TC-001
type: integration
title: "Маршрут обходит шлагбаум"
precondition: "OSRM граф пересобран с новым профилем"
steps:
- "POST /api/route с точками, между которыми есть шлагбаум"
- "Проверить что маршрут не проходит через ноду шлагбаума"
expected: "Маршрут обходит шлагбаум или возвращает 404"
- id: TC-002
type: integration
title: "Маршрут не идёт по тротуару"
precondition: "OSRM граф пересобран"
steps:
- "POST /api/route с точками в городе"
- "Проверить что геометрия маршрута не содержит footway-сегментов"
expected: "Маршрут идёт только по проезжим дорогам"
- id: TC-003
type: integration
title: "cattle_grid не блокирует маршрут"
steps:
- "POST /api/route через точку с cattle_grid"
expected: "Маршрут проходит через cattle_grid нормально"
- id: TC-004
# ─── Unit (frontend, JS) ────────────────────────────────────────────
- id: TC-U-01
type: unit
title: "Lua профиль — синтаксис"
steps:
- "luac -p infra/osrm/enduro.lua"
expected: "Exit code 0, нет ошибок"
layer: frontend
title: applyPoiVisibility(false) скрывает слои POI и синхронизирует layerState
target: src/web/app.js :: applyPoiVisibility
given: |
JSDOM/мок map с методами getLayer (true для poi-circles, poi-labels)
и setLayoutProperty (spy). layerState.poi = true.
when: |
Вызвать applyPoiVisibility(false).
then: |
- setLayoutProperty вызван для 'poi-circles' и 'poi-labels' со
значением 'none'.
- layerState.poi === false.
covers: [REQ-F-04, REQ-NF-03, AC-03, AC-08]
- id: TC-005
type: regression
title: "Существующий маршрут не сломан"
steps:
- "POST /api/route с точками без шлагбаумов/тротуаров"
expected: "Маршрут строится, distance > 0, geometry не пустая"
- id: TC-U-02
type: unit
layer: frontend
title: onPoiCheckbox пишет localStorage и применяет видимость
target: src/web/app.js :: onPoiCheckbox
given: |
JSDOM с #poi-visible-cb; spy на localStorage.setItem и
applyPoiVisibility.
when: |
Снять чекбокс (checked=false) и вызвать onPoiCheckbox();
затем отметить (checked=true) и вызвать снова.
then: |
- localStorage['poi-visible'] === '0', applyPoiVisibility(false).
- localStorage['poi-visible'] === '1', applyPoiVisibility(true).
covers: [REQ-F-04, REQ-F-05, REQ-F-06, AC-03, AC-04, AC-05]
- id: TC-U-03
type: unit
layer: frontend
title: restorePoiState — дефолт «видимы» при отсутствии ключа
target: src/web/app.js :: restorePoiState
given: |
localStorage без ключа 'poi-visible'; #poi-visible-cb в DOM.
when: |
Вызвать restorePoiState().
then: |
- #poi-visible-cb.checked === true.
- applyPoiVisibility(true) (слои POI видимы).
covers: [REQ-F-03, AC-02]
- id: TC-U-04
type: unit
layer: frontend
title: restorePoiState — восстановление «скрыто» из localStorage
target: src/web/app.js :: restorePoiState
given: |
localStorage['poi-visible'] === '0'; #poi-visible-cb в DOM.
when: |
Вызвать restorePoiState() (имитация загрузки/смены темы).
then: |
- #poi-visible-cb.checked === false.
- слои POI скрыты (visibility 'none').
covers: [REQ-F-06, REQ-F-07, AC-05, AC-07]
- id: TC-U-05
type: unit
layer: frontend
title: Подпись чекбокса равна «Показывать POI» (новая дельта)
target: src/web/index.html :: #poi-visible-cb label
given: |
Разобранный DOM index.html (или тест из poi_toggle.test.js,
проверяющий текст подписи).
when: |
Прочитать textContent <span> рядом с #poi-visible-cb.
then: |
Текст строго равен «Показывать POI».
note: |
ДО правки кейс обязан падать (сейчас «POI»). Обновить ожидание
синхронно с правкой index.html.
covers: [REQ-F-01, AC-01]
# ─── Unit (python, регресс серверного контракта) ────────────────────
- id: TC-U-06
type: unit
layer: backend
title: Серверная отдача слоя POI в MVT не изменилась
target: tests/unit/test_poi_toggle.py (регресс ET-002)
given: |
Существующий python-тест, фиксирующий, что видимость POI —
клиентская и /api/tiles по-прежнему включает слой 'poi'.
when: |
make test.
then: |
Тест зелёный; контракт MVT (layer 'poi') не тронут.
covers: [REQ-NF-02, AC-10]
# ─── Integration (DOM) ──────────────────────────────────────────────
- id: TC-I-01
type: integration
layer: frontend
title: Чекбокс POI присутствует в #terrain-popup и связан с обработчиком
given: |
Полный DOM из src/web/index.html.
when: |
Найти #poi-visible-cb внутри #terrain-popup.
then: |
- Элемент существует, имеет атрибут onchange="onPoiCheckbox()".
- По умолчанию checked.
covers: [REQ-F-02, REQ-F-03, AC-02]
- id: TC-I-02
type: integration
layer: frontend
title: Цикл скрыть→показать переключает visibility слоёв POI
given: |
Полный DOM + мок map (getLayer/setLayoutProperty).
when: |
Снять #poi-visible-cb → onPoiCheckbox(); затем отметить → onPoiCheckbox().
then: |
visibility 'poi-circles'/'poi-labels': none → visible.
covers: [REQ-F-04, REQ-F-05, AC-03, AC-04]
# ─── E2E / UI (Playwright-сценарии; детали — 04b-ui-test-cases.md) ──
- id: TC-E-01
type: e2e
layer: ui
title: Подпись «Показывать POI» и чекбокс включён по умолчанию
env: test
viewport: { width: 1440, height: 900 }
expected: |
#terrain-popup открыт; #poi-visible-cb checked; подпись
«Показывать POI» в одну строку.
covers: [AC-01, AC-02]
reference: 04b-ui-test-cases.md :: TC-UI-01
- id: TC-E-02
type: e2e
layer: ui
title: Снятие чекбокса скрывает POI, установка возвращает
env: test
viewport: { width: 1440, height: 900 }
expected: |
После снятия маркеры POI исчезают; после повторной установки — видны.
covers: [AC-03, AC-04]
reference: 04b-ui-test-cases.md :: TC-UI-02, TC-UI-03
- id: TC-E-03
type: e2e
layer: ui
title: Состояние «скрыто» сохраняется после перезагрузки
env: test
viewport: { width: 1440, height: 900 }
expected: |
После reload POI скрыты, чекбокс снят.
covers: [AC-05]
reference: 04b-ui-test-cases.md :: TC-UI-04
- id: TC-E-04
type: e2e
layer: ui
title: Видимость POI устойчива к смене темы
env: test
viewport: { width: 1440, height: 900 }
expected: |
После #btn-theme POI остаются скрытыми, чекбокс снят.
covers: [AC-07]
reference: 04b-ui-test-cases.md :: TC-UI-05
- id: TC-E-05
type: e2e
layer: ui
title: Mobile — чекбокс «Показывать POI» виден целиком, работает
env: test
viewport: { width: 390, height: 844 }
expected: |
Попап помещается; подпись не обрезана; снятие скрывает POI.
covers: [AC-01, AC-03]
reference: 04b-ui-test-cases.md :: TC-UI-06
# ─── Вне scope ──────────────────────────────────────────────────────────
out_of_scope:
- Разбивка POI по типам, отдельная кнопка POI, иконка-индикатор.
- Изменение серверной агрегации POI (/api/recon, /api/scenic).
- Производительность тайлов/роутинга.
# ─── Примечание ─────────────────────────────────────────────────────────
notes: |
Поведенческая суть (TC-U-01..04, TC-I-*) уже покрыта unit-тестами
ET-002 (tests/unit/poi_toggle.test.js, tests/unit/test_poi_toggle.py).
Реальная новая проверка ET-001 — TC-U-05 / TC-E-01 (подпись).
Playwright-инфраструктуры в репозитории нет (ET-002
07-infra-requirements.md запрещает новые npm-пакеты) — e2e-кейсы
исполняются вручную/визуально либо в существующем CI-раннере, если он
появится.

View File

@@ -2,13 +2,14 @@
type: ui-test-cases
work_item_id: ET-001
title: "UI тест-кейсы: Чекбокс показа/скрытия POI"
version: 6
version: 7
status: proposed
created_at: 2026-06-10
updated_at: 2026-06-12
updated_at: 2026-06-14
author: "agent:analyst"
relates_to: ET-002
purpose: >
Верификация дельты ET-001 (подпись чекбокса «Показывать POI», ТЗ §1.1)
Верификация дельты ET-001 (подпись чекбокса «Показывать POI», ТЗ REQ-F-01)
+ регрессия поведения, поставленного в ET-002 (скрытие/возврат POI,
персистентность между сессиями, устойчивость к смене темы). До правки
подписи TC-UI-01 обязан падать (в UI сейчас «POI»).
@@ -41,7 +42,7 @@ base_url: "https://openclaw.mva154.duckdns.org/enduro/"
2. wait: 5000
3. click: #terrain-toggle
4. wait: 500
5. check-visual: попап `#terrain-popup` открыт, виден чекбокс POI с подписью «Показывать POI» (целевое состояние ET-001, ТЗ §1.1; до реализации подпись «POI» — кейс обязан падать)
5. check-visual: попап `#terrain-popup` открыт, виден чекбокс POI с подписью «Показывать POI» (целевое состояние ET-001, ТЗ REQ-F-01; до реализации подпись «POI» — кейс обязан падать)
6. check-visual: чекбокс `#poi-visible-cb` отмечен (checked)
7. check-visual: подпись помещается в одну строку, layout попапа не сломан
8. screenshot: poi-checkbox-default-on