reviewer(ET): auto-commit from reviewer run_id=240
All checks were successful
CI / lint (push) Successful in 4s
CI / test (push) Successful in 9s
CI / build (push) Successful in 2s

This commit is contained in:
2026-06-06 23:55:18 +00:00
parent ea00b7e3ff
commit f82bb8cc0e

View File

@@ -2,7 +2,7 @@
type: review
work_item_id: ET-013
verdict: APPROVED
version: 16
version: 17
created_at: 2026-06-04
updated_at: 2026-06-06
authors:
@@ -14,44 +14,21 @@ related:
- "ET-013:test-report"
---
# Review ET-013 — Перепады высот на z9-z11 (re-run #16)
# Review ET-013 — Перепады высот на z9-z11 (re-run #17)
> **Re-run #16 (independent).** Перечитаны TRZ (`02-trz.md`),
> **Re-run #17 (независимая сверка.)** Перечитаны TRZ (`02-trz.md`),
> AC (`03-acceptance-criteria.md`), ADR-017, CLAUDE.md. Построчно сверена
> реализация в рабочем дереве с REQ-F-01..F-19 и решениями ADR-017.
>
> Состояние ветки: фича 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**.
> Состояние ветки: фича ET-013 уже смержена в `main` и задеплоена.
> `git diff main...HEAD` затрагивает только docs (`12-review.md`,
> `13-test-report.md`) — кодовая часть в рабочем дереве идентична
> merged/deployed-состоянию. Нового кода для ревью нет; повторно
> подтверждаю корректность merged-кода непосредственным чтением файлов.
## TL;DR
- **Branch:** `feature/ET-013-z9-z11-z8` (фича уже в `main`; в ветке — docs).
- **Содержательные коммиты:** feat zoom-aware paint + fix whitelist `tri`.
- **Branch:** `feature/ET-013-z9-z11-z8` (фича в `main`; в ветке — docs).
- **Scope:** zoom-aware paint hillshade/TRI на z9-z11, понижение
UI-минзума hillshade z10→z9, обратно-совместимое расширение
`applyTerrainLayer`, расширение backend-whitelist на `tri`.
@@ -64,34 +41,34 @@ 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-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-03 | TRI minzoom=5/maxzoom=15, paint=TRI_PAINT (app.js:2826) | ✅ minzoom не тронут |
| F-04 | `applyTerrainLayer(opacityOrPaint)` (app.js:3371-3414) | ✅ number→legacy(linear) / object as-is, `paint: paint` в addLayer |
| F-05/06/07 | HILLSHADE_PAINT 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; `nearest` (app.js:2734-2752) | ✅ stops точно по TRZ/ADR |
| F-08/09 | TRI_PAINT opacity z5:0.55,z7:0.65,**z8:0.70 (регрессия)**,z9:0.80,пик z10-z11:0.85,z12:0.75,z15:0.70; `nearest` (app.js:2755-2768) | ✅ 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` | ✅ сохранён |
| F-19 | style.json/style-dark.json/app.css/config не тронуты | ✅ diff чист |
| F-12 | контракт `onTerrainCheckbox`, persistence `localStorage`, `.active` | ✅ без изменений сигнатуры/логики |
| F-13/14 | unit-тесты (Вариант B, Python-парсер) + регрессии | ✅ 17 тестов, **17/17 PASS локально (0.03 s)** |
| F-15 | integration smoke z9 (`test_terrain_z9_tiles.py`) с `skipif` | ✅ присутствует, whitelist/404-регрессии работают без данных |
| F-18 | API контракт `/terrain/{layer}/{z}/{x}/{y}.png`, `Cache-Control: public, max-age=31536000, immutable` (main.py:1252-1264) | ✅ сохранён |
| F-19 | style.json/style-dark.json/app.css/config не тронуты | ✅ |
## Соответствие ADR-017
- Реализация точно следует **P-A** (frontend paint-калибровка): paint
zoom-aware через `interpolate ['linear'] ['zoom']`, 0 перегенерации
тайлов, 0 новых слоёв/источников. ✅
- Реализация точно следует **P-A** (frontend paint-калибровка):
zoom-aware paint через `interpolate ['linear'] ['zoom']`, 0 перегенерации
тайлов, 0 новых слоёв/источников/endpoint'ов. ✅
- O-B (linear-stops), C-A (contrast только hillshade), R-A (`nearest`
глобально), U-A (UI-порог z9), A-A (обратно-совместимая сигнатура),
M-A (константы в `app.js`) — все соблюдены. ✅
глобально), U-A (UI-порог z9 + source.minzoom=9), A-A (обратно-совместимая
сигнатура), M-A (константы рядом с `TERRAIN_BASE_URL` в `app.js`) — все
соблюдены. ✅
- Отклонённые «жирные» альтернативы (z-factor 2.5, raster-dem,
theme-specific paint) корректно вынесены в follow-up. ✅
theme-specific paint) корректно вынесены в follow-up (TD-1..TD-5). ✅
## Findings
| # | Severity | Файл | Описание | Статус |
|---|---|---|---|---|
| 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 соблюдён. Не дефект. | Принято. |
| N-1 | P3 (info) | `src/api/main.py:1252` | TRZ §2 декларировал backend «без изменений», но в whitelist добавлен `tri` (`("hypso","hillshade","tri")`). Это необходимый багфикс: в dev-режиме (FastAPI без nginx) запросы `/terrain/tri/...` иначе возвращали бы 404. Контракт endpoint'а (URL-шаблон, коды ответа, `Cache-Control: immutable`, новых query/headers нет) не нарушен → REQ-F-18 соблюдён. Покрыто integration-регрессией `test_known_terrain_layer_accepted_by_whitelist`. Не дефект. | Принято. |
## Качество кода
@@ -100,7 +77,7 @@ related:
(`raster-opacity` + `linear`) либо пробрасывает object as-is. JSDoc на месте.
- `HILLSHADE_PAINT`/`TRI_PAINT` вынесены рядом с `TERRAIN_BASE_URL` с
пояснением логики stops; конфигурируемость через env/config справедливо
отвергнута (калибровка живёт в коде).
отвергнута (калибровка живёт в коде, ADR-017 M-A).
- Дублирования, необработанных ошибок, мёртвого кода не выявлено.
## Качество тестов
@@ -108,19 +85,23 @@ 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 локально.**
- **Integration:** TestClient против `src.api.main:app`; тайло-зависимые
кейсы `skipped` при отсутствии PH-6 данных, whitelist/404-регрессии
работают всегда.
кейсы параметризованы по слоям (hillshade/tri) и зумам (9/10/11),
`skipped` при отсутствии PH-6 данных; whitelist/404/Cache-Control —
регрессии работают всегда. Сбой коллекции в окружении ревью вызван
отсутствием `shapely` (зависимость API) — это инфра-вопрос окружения,
не дефект тестов/кода; в CI с установленными зависимостями импорт
проходит.
## Замечание по статусу тестирования (вне 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 не порождает.
Test Report фиксирует blocker на 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 не порождает.
## Вердикт