diff --git a/docs/work-items/ET-013/12-review.md b/docs/work-items/ET-013/12-review.md index 5e6e3b1..bf1aba2 100644 --- a/docs/work-items/ET-013/12-review.md +++ b/docs/work-items/ET-013/12-review.md @@ -2,7 +2,7 @@ type: review work_item_id: ET-013 verdict: APPROVED -version: 15 +version: 16 created_at: 2026-06-04 updated_at: 2026-06-06 authors: @@ -14,96 +14,44 @@ related: - "ET-013:test-report" --- -# Review ET-013 — Перепады высот на z9-z11 (re-run #15) +# Review ET-013 — Перепады высот на z9-z11 (re-run #16) -> **Re-run #15 (independent).** Триггер — перепрогон Tester v10 (BLOCKED). -> Перечитаны TRZ, AC, ADR-017, CLAUDE.md, Test Report v10. -> - `git diff 099669d..HEAD -- src/ tests/` → **пусто**: код побайтово -> идентичен merged/deployed-состоянию (`5be81f9` feat, `099669d` -> fix-whitelist). С Review v14 в `src/`/`tests/` изменений нет — новый -> код для ревью отсутствует. -> - Повторно сверено по факту: `HILLSHADE_PAINT` (app.js:2734-2752) opacity -> 9:0.65→14:0.40, contrast 9:0.40→14:0.00, `nearest`; `TRI_PAINT` -> (app.js:2755-2768) z8=0.70, z9=0.80, пик z10-11=0.85, спад z15=0.70, -> `nearest`; `updateHillshadeAvailability` `if (zoom < 9)` (app.js:3425), -> `if (zoom < 10)` отсутствует. Stops точно соответствуют REQ-F-05/F-08 -> и решениям 4/5 ADR-017. -> - **Разбор Tester v10 BLOCKED.** Блокер — AC-19/REQ-F-20 §1 pre-deploy -> probe: на test-среде **отсутствуют нарезанные z9-тайлы hillshade** -> (z10/z11 есть, TRI z9/z10/z11 есть). Сам тестер квалифицирует это как -> **инфраструктурный дефект (нет данных PH-6), не дефект кода**: unit 17/17, -> integration 6 PASS/7 skip, полный регресс 254 passed, lint clean, деплой -> корректно запрашивает z9 hillshade. Это вопрос data/deploy-этапа -> (PH-6 follow-up — догенерить `data/terrain/hillshade/9/*` над ЦФО), -> **вне content-review кода**. Кодовых P0/P1 не порождает. -> - UI Playwright (TC-UI-01..12) — NOT EXECUTED в песочнице тестера -> (нет runner/браузеров): инфраструктура приёмки, не код. -> -> Вердикт по коду подтверждён повторно: **APPROVED**. Разблокировка задачи — -> зона Деплой/Инфра (нарезать z9 hillshade + повторный AC-19/Playwright), -> не Review. - -> **Re-run #14 (independent).** Перечитаны TRZ, AC, ADR-017, CLAUDE.md. -> Построчно сверена реализация в рабочем дереве со всеми REQ-F-01..F-19 -> и решениями ADR-017 (P-A, O-B, C-A, R-A, U-A, A-A, M-A): -> - `HILLSHADE_PAINT` (app.js:2734-2752) и `TRI_PAINT` (app.js:2755-2768) -> — stops побайтово совпадают с REQ-F-05/F-08 и решениями 4/5 ADR-017 -> (hillshade opacity 9:0.65→14:0.40, contrast 9:0.40→14:0.00, nearest; -> TRI opacity z8=0.70, пик z9-z11=0.85, спад до z15=0.70, nearest). -> - `applyTerrainLayer` (app.js:3371-3414) — нормализация number→legacy -> (`raster-opacity`+`linear`) / object as-is; `paint: paint` в `addLayer`. -> - `updateHillshadeAvailability` (app.js:3425) — `zoom < 9`, `zoom < 10` -> отсутствует; вызовы (app.js:2825-2826) — hillshade minzoom=9/HILLSHADE_PAINT, -> TRI minzoom=5/maxzoom=15/TRI_PAINT. -> - `index.html:60` — hint «Зум 9+». -> - `terrain_tile` (main.py:1240-1266) — whitelist `("hypso","hillshade","tri")`, -> `Cache-Control: ...immutable` сохранён → REQ-F-18 соблюдён. -> - Unit-тесты перезапущены локально — **17/17 PASS (0.03 s)**. -> - Integration (`test_terrain_z9_tiles.py`) присутствует, корректно -> спроектирован: whitelist/404-регрессии работают без данных, -> тайло-зависимые кейсы `skipif` при отсутствии PH-6 тайлов. -> -> **Наблюдение по ветке (не finding):** фича ET-013 уже смержена в `main` -> (PR #26, `be7a052`) и задеплоена (`v0.0.5`); `main` ушёл вперёд на -> ET-014/ET-015. `git diff main..HEAD` показывает «удаления» только потому, -> что ветка отстала от `main` — содержательный код ET-013 в рабочем дереве -> корректен и идентичен merged-состоянию. Это вопрос мержа/процесса, а не -> качества кода ET-013. -> -> Вердикт подтверждён повторно: **APPROVED**. - -> **Re-run #13 (independent).** Перечитаны TRZ (`02-trz.md`), +> **Re-run #16 (independent).** Перечитаны TRZ (`02-trz.md`), > AC (`03-acceptance-criteria.md`), ADR-017, CLAUDE.md. Построчно сверена -> реализация в рабочем дереве (`src/web/app.js`, `src/web/index.html`, -> `src/api/main.py`) с REQ-F-01..F-19 и решениями ADR-017 (P-A, O-B, -> C-A, R-A, U-A, A-A, M-A). Содержательные коммиты фичи уже в `main`; -> ветка `feature/ET-013-z9-z11-z8` относительно `main` содержит **только -> docs** (`12-review.md`, `13-test-report.md`) — `src/`/`tests/` идентичны -> merged-состоянию. +> реализация в рабочем дереве с REQ-F-01..F-19 и решениями ADR-017. > -> Сверено в этой итерации: -> - `HILLSHADE_PAINT` (app.js:2734) и `TRI_PAINT` (app.js:2755) — stops -> побайтово совпадают с REQ-F-05/F-08 и решением 4/5 ADR-017. -> - `applyTerrainLayer` (app.js:3371) — нормализация number→legacy/object -> as-is; `updateHillshadeAvailability` (app.js:3425) — `zoom < 9`; -> вызовы (app.js:2825-2826) — hillshade minzoom=9/paint, TRI minzoom=5/paint. -> - `index.html:60` — hint «Зум 9+». -> - `terrain_tile` (main.py:1240-1264) — whitelist `("hypso","hillshade","tri")`, -> `Cache-Control: ...immutable` сохранён → REQ-F-18 соблюдён. -> - Unit-тесты перезапущены локально — **17/17 PASS (0.04 s)**. -> - Integration (`test_terrain_z9_tiles.py`): в review-песочнице падает -> на импорте (`ModuleNotFoundError: shapely`). `shapely==2.0.4` объявлен -> в `pyproject.toml`; это **дефект окружения песочницы, не кода** — -> в CI с установленными зависимостями кейс отрабатывает (`skipif` при -> отсутствии PH-6 тайлов). Не finding. +> Состояние ветки: фича ET-013 уже смержена в `main` и задеплоена; +> `git diff origin/main...HEAD` по `src/`/`tests/` пуст — кодовая часть +> побайтово идентична merged/deployed-состоянию. В ветке относительно +> `main` отличаются только docs (`12-review.md`, `13-test-report.md`). +> Нового кода для ревью нет; повторно подтверждаю корректность merged-кода. +> +> Сверено по факту в этой итерации: +> - `HILLSHADE_PAINT` (app.js:2734-2752) — opacity 9:0.65→10:0.60→11:0.55→ +> 12:0.50→14:0.40; contrast 9:0.40→10:0.35→11:0.30→12:0.15→14:0.00; +> `raster-resampling: 'nearest'`. Точно по REQ-F-05/06/07 и решению 4 ADR-017. +> - `TRI_PAINT` (app.js:2755-2768) — opacity z5:0.55, z7:0.65, **z8:0.70 +> (регрессия)**, z9:0.80, пик z10-z11:0.85, спад z12:0.75, z15:0.70; +> `nearest`. Точно по REQ-F-08/09. +> - `applyTerrainLayer` (app.js:3371-3414) — нормализация: число → +> `{raster-opacity, raster-resampling:'linear'}` (legacy), объект → as-is; +> `paint: paint` в `addLayer`. Обратная совместимость соблюдена (REQ-F-04). +> - `onTerrainCheckbox` вызовы (app.js:2825-2826) — hillshade minzoom=9 + +> HILLSHADE_PAINT (REQ-F-02), TRI minzoom=5/maxzoom=15 + TRI_PAINT (REQ-F-03). +> - `updateHillshadeAvailability` (app.js:3425) — `if (zoom < 9)`; старый +> `< 10` отсутствует (REQ-F-01/11). +> - `index.html:60` — hint «Зум 9+» (REQ-F-10). +> - `terrain_tile` (main.py) — whitelist `("hypso","hillshade","tri")`, +> `Cache-Control: public, max-age=31536000, immutable` сохранён → контракт +> endpoint'а не нарушен (REQ-F-18). +> - Unit-тесты перезапущены локально — **17/17 PASS (0.03 s)**. > > Вердикт подтверждён повторно: **APPROVED**. ## TL;DR - **Branch:** `feature/ET-013-z9-z11-z8` (фича уже в `main`; в ветке — docs). -- **Содержательные коммиты:** `5be81f9` (feat: zoom-aware paint), - `099669d` (fix: whitelist `tri`). +- **Содержательные коммиты:** feat zoom-aware paint + fix whitelist `tri`. - **Scope:** zoom-aware paint hillshade/TRI на z9-z11, понижение UI-минзума hillshade z10→z9, обратно-совместимое расширение `applyTerrainLayer`, расширение backend-whitelist на `tri`. @@ -117,14 +65,14 @@ related: | F-01/11 | `updateHillshadeAvailability`: `zoom < 9` (app.js:3425) | ✅ старый `< 10` отсутствует | | F-02 | hillshade minzoom=9, paint=HILLSHADE_PAINT (app.js:2825) | ✅ | | F-03 | TRI minzoom=5/maxzoom=15, paint=TRI_PAINT (app.js:2826) | ✅ не тронут | -| F-04 | `applyTerrainLayer(opacityOrPaint)` (app.js:3371-3380) | ✅ number→legacy(linear) / object as-is | +| F-04 | `applyTerrainLayer(opacityOrPaint)` (app.js:3371-3414) | ✅ number→legacy(linear) / object as-is | | F-05/06/07 | HILLSHADE_PAINT opacity 9:0.65→14:0.40; contrast 9:0.40→14:0.00; nearest | ✅ stops точно по TRZ/ADR | | F-08/09 | TRI_PAINT opacity z8=0.70, пик z9-z11=0.85, спад до 0.70; nearest | ✅ stops точно | | F-10 | hint «Зум 9+» (index.html:60) | ✅ | | F-12 | контракт `onTerrainCheckbox`, persistence `localStorage`, `.active` | ✅ без изменений | | F-13/14 | unit-тесты (Вариант B, Python-парсер) + регрессии | ✅ 17 тестов, PASS | | F-15 | integration smoke z9 (`test_terrain_z9_tiles.py`) с `skipif` | ✅ присутствует | -| F-18 | API контракт `/terrain/{layer}/{z}/{x}/{y}.png`, `Cache-Control: immutable` | ✅ сохранён (main.py:1260) | +| F-18 | API контракт `/terrain/{layer}/{z}/{x}/{y}.png`, `Cache-Control: immutable` | ✅ сохранён | | F-19 | style.json/style-dark.json/app.css/config не тронуты | ✅ diff чист | ## Соответствие ADR-017 @@ -136,20 +84,20 @@ related: глобально), U-A (UI-порог z9), A-A (обратно-совместимая сигнатура), M-A (константы в `app.js`) — все соблюдены. ✅ - Отклонённые «жирные» альтернативы (z-factor 2.5, raster-dem, - theme-specific paint) корректно вынесены в follow-up (TD-1..TD-5). ✅ + theme-specific paint) корректно вынесены в follow-up. ✅ ## Findings | # | Severity | Файл | Описание | Статус | |---|---|---|---|---| -| F-1 | (resolved) | `src/api/main.py:1252` | Whitelist endpoint'а не включал `tri` → 404 в dev без nginx. | Исправлено в `099669d`, документировано, покрыто integration-регрессией. | +| F-1 | (resolved) | `src/api/main.py` | Whitelist endpoint'а не включал `tri` → 404 в dev без nginx. | Исправлено, документировано, покрыто integration-регрессией. | | N-1 | P3 (info) | `src/api/main.py` | TRZ §2 декларировал backend «без изменений», но фикс F-1 — необходимая корректная правка (TRI был latent-broken в dev). Контракт endpoint'а (URL, коды, `Cache-Control`) не нарушен → REQ-F-18 соблюдён. Не дефект. | Принято. | ## Качество кода - `applyTerrainLayer` расширен обратно-совместимо; ветвление `typeof opacityOrPaint === 'number'` собирает legacy-paint - (`raster-opacity` + `linear`) либо пробрасывает object as-is. JSDoc/комментарии на месте. + (`raster-opacity` + `linear`) либо пробрасывает object as-is. JSDoc на месте. - `HILLSHADE_PAINT`/`TRI_PAINT` вынесены рядом с `TERRAIN_BASE_URL` с пояснением логики stops; конфигурируемость через env/config справедливо отвергнута (калибровка живёт в коде). @@ -160,17 +108,21 @@ related: - **Unit (17):** opacity/contrast stops, монотонность, `nearest`, регрессия z8=0.70, пик z9-z11≥0.80, обратная совместимость `applyTerrainLayer`, порог `zoom < 9`, текст hint, число call-site, - привязка paint-константы и minzoom к каждому слою. Парсер устойчив к - пробелам/переносам. **17/17 PASS локально (0.03 s).** + привязка paint-константы и minzoom к каждому слою. **17/17 PASS локально (0.03 s).** - **Integration:** TestClient против `src.api.main:app`; тайло-зависимые кейсы `skipped` при отсутствии PH-6 данных, whitelist/404-регрессии работают всегда. +## Замечание по статусу тестирования (вне content-review) + +Test Report фиксирует BLOCKED на AC-19/REQ-F-20 §1: на test-среде +отсутствуют нарезанные z9-тайлы hillshade (PH-6 data). Это **инфраструктурный +дефект данных/деплоя, не дефект кода ET-013** — код корректно запрашивает +z9 hillshade, unit/integration/lint зелёные. Разблокировка — зона +Деплой/Инфра (догенерить `data/terrain/hillshade/9/*` + повторный +AC-19/Playwright), не Review. Кодовых P0/P1 не порождает. + ## Вердикт Нет P0/P1. Реализация полностью соответствует TRZ и ADR-017, тесты адекватны и зелёные. **APPROVED.** - -Ручная/визуальная приёмка (AC-03..AC-13, AC-19, AC-21) и сетевая -регрессия M-10 — зона этапов Тестирование/Деплой (см. `13-test-report.md`, -`14-deploy-log.md`), вне content-review кода.