From 89b83e3dfb7c7783d9fe1d2aa25c1a7ca609f168 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Sat, 6 Jun 2026 22:11:44 +0000 Subject: [PATCH] reviewer(ET): auto-commit from reviewer run_id=216 --- docs/work-items/ET-013/12-review.md | 172 +++++++++++++--------------- 1 file changed, 79 insertions(+), 93 deletions(-) diff --git a/docs/work-items/ET-013/12-review.md b/docs/work-items/ET-013/12-review.md index 90d57dd..0ad4f91 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: 5 +version: 6 created_at: 2026-06-04 updated_at: 2026-06-06 authors: @@ -13,149 +13,135 @@ related: - "ET-013:test-report" --- -# Review ET-013 — Перепады высот на z9-z11 (re-run #5) +# Review ET-013 — Перепады высот на z9-z11 (re-run #6) ## TL;DR - **Branch:** `feature/ET-013-z9-z11-z8` -- **HEAD:** `0ad44b5 reviewer(ET): auto-commit from reviewer run_id=211` -- **Scope:** калибровка клиентского paint (hillshade/TRI) на z9-z11, - понижение UI-минзума hillshade z10→z9, обратно-совместимое - расширение `applyTerrainLayer`, расширение whitelist backend-endpoint'а - на `tri` (фикс по review v1, F-1). -- **Что изменилось со времени review v4:** **в коде и тестах — ничего.** - `git diff c66d4fb..HEAD --name-only` → только `12-review.md` (этот файл). - Реализация (`src/`, `tests/`) бит-в-бит совпадает с одобренной в v2..v4. -- **Перепроверено в re-run #5:** перечитаны TRZ, AC, ADR-017, полный diff - фичи (`git diff 8da09e6..HEAD`), все исходники и тесты. Unit-тесты - перезапущены локально — **17/17 PASS** (0.03 s). Integration-модуль в этом - sandbox не собирается из-за отсутствия `shapely` (env-зависимость, не - дефект кода); Тестер в полном venv фиксировал 254 passed / 7 skipped. -- **Тесты:** `pytest tests/unit/test_terrain_paint.py` — **17/17 PASS** - (перезапущено локально, 0.03 s). Тестер в полном venv: **254 passed, - 7 skipped, 0 failed**; ET-013 unit 17/17, integration 6 PASS / 7 SKIP - (skip — отсутствие PNG-данных, штатно по AC-16). -- **Verdict кода: APPROVED.** P0/P1 в коде не найдено. Код соответствует - TRZ REQ-F-01..F-19, F-21 и всем решениям ADR-017. -- **⚠️ ВАЖНО — деплой не разблокирован.** Тестер (run_id=209) выставил +- **HEAD:** `fd0c7a4 tester(ET): auto-commit from tester run_id=215` +- **Scope:** zoom-aware paint (hillshade/TRI) на z9-z11, понижение + UI-минзума hillshade z10→z9, обратно-совместимое расширение + `applyTerrainLayer`, расширение backend-whitelist на `tri` (фикс F-1 из v1). +- **Что изменилось со времени review v5:** **в коде и тестах — ничего.** + `git diff 8da09e6..HEAD --name-only` по `src/`+`tests/` даёт ровно + 5 файлов, идентичных одобренным в v2..v5; новые коммиты (run 214/215) — + только docs (`12-review.md`, `13-test-report.md`). +- **Перепроверено в re-run #6 независимо:** перечитаны TRZ, AC, ADR-017, + полный diff фичи (`git diff 8da09e6...HEAD`), исходники и оба тест-файла. + Unit-тесты перезапущены локально — **17/17 PASS** (0.03 s). +- **Verdict кода: APPROVED.** P0/P1 в коде/ADR/тестах не найдено. Код + соответствует TRZ REQ-F-01..F-19, F-21 и всем семи решениям ADR-017. +- **⚠️ Деплой не разблокирован ревью.** Тестер (run_id=215) держит `verdict: BLOCKED` из-за **AC-19 (P1): на test-среде - `/terrain/hillshade/9/{x}/{y}.png` отдаёт 404** — тайлы z9 не нарезаны - на сервере. Это **не дефект PR** (см. §«AC-19»), а предусловие данных - PH-6; merge/деплой держит именно тест-гейт Тестера, а не этот ревью. + `/terrain/hillshade/9/{x}/{y}.png` → 404** (тайлы z9 не нарезаны). + Это предусловие данных PH-6, **не дефект PR** (см. §AC-19). Шиппинг + держит тест-гейт Тестера, а не этот code-review. ## Что прочитано - `docs/work-items/ET-013/02-trz.md` - `docs/work-items/ET-013/03-acceptance-criteria.md` - `docs/work-items/ET-013/06-adr/ADR-017-zoom-aware-terrain-paint.md` -- `docs/work-items/ET-013/12-review.md` (v3) -- `docs/work-items/ET-013/13-test-report.md` (run_id=209, verdict BLOCKED) -- `docs/architecture/README.md`, `CLAUDE.md` -- `git diff 8da09e6..HEAD` (полный diff фичи: `src/`, `tests/`, docs) -- `git diff 316bb0d..HEAD --name-only` (что изменилось со времени v3) -- `src/api/main.py:1239-1264` (`terrain_tile`) -- `src/web/app.js` (2725-2767, 2821-2826, 3356-3430) -- `src/web/index.html:57-65` +- `docs/work-items/ET-013/12-review.md` (v5), `13-test-report.md` (v3, BLOCKED) +- `CLAUDE.md` +- `git diff 8da09e6...HEAD` (полный diff фичи), `--stat` по `src/`+`tests/` +- `src/web/app.js` (2722-2827, 3356-3434) +- `src/web/index.html:60` +- `src/api/main.py:1240-1264` (`terrain_tile`) - `tests/unit/test_terrain_paint.py`, `tests/integration/test_terrain_z9_tiles.py` -- `grep applyTerrainLayer src/web/` → 1 декларация + ровно 2 вызова +- `grep applyTerrainLayer src/web/app.js` → 1 декларация + ровно 2 вызова ## Соответствие ТЗ | Требование | Реализация | Файл | OK | |---|---|---|---| -| REQ-F-01 / F-11 — порог `zoom < 9` в `updateHillshadeAvailability` | `if (zoom < 9)` + комментарий | `app.js:3425` | ✅ | +| REQ-F-01 / F-11 — порог `zoom < 9` | `if (zoom < 9)` + комментарий; `zoom < 10` удалён | `app.js:3425` | ✅ | | REQ-F-02 — hillshade `minzoom=9` | `applyTerrainLayer('terrain-hillshade', …, HILLSHADE_PAINT, 9, 15)` | `app.js:2825` | ✅ | | REQ-F-03 — TRI `minzoom=5` без изменений | `applyTerrainLayer('terrain-tri', …, TRI_PAINT, 5, 15)` | `app.js:2826` | ✅ | -| REQ-F-04 — обратно-совместимый `opacityOrPaint` | `typeof === 'number' ? legacy : obj` | `app.js:3382-3385` | ✅ | -| REQ-F-05/06/07 — HILLSHADE_PAINT (opacity/contrast interpolate + nearest) | stops 9/10/11/12/14 → 0.65/0.60/0.55/0.50/0.40; contrast 0.40→0.00; `nearest` | `app.js:2732-2750` | ✅ | -| REQ-F-08/09 — TRI_PAINT (interpolate, z8=0.70, пик 0.80-0.85, nearest) | точное совпадение со spec | `app.js:2753-2766` | ✅ | +| REQ-F-04 — back-compat `opacityOrPaint` | `typeof === 'number' ? legacy : obj`, `paint: paint` | `app.js:3371-3408` | ✅ | +| REQ-F-05/06/07 — HILLSHADE_PAINT | opacity 9/10/11/12/14 → 0.65/0.60/0.55/0.50/0.40; contrast 0.40→0.00; `nearest` | `app.js:2734-2752` | ✅ | +| REQ-F-08/09 — TRI_PAINT | z8=0.70, пик z10/z11=0.85, спад до 0.70; `nearest` | `app.js:2755-2768` | ✅ | | REQ-F-10 — hint «Зум 9+» | `Зум 9+` | `index.html:60` | ✅ | -| REQ-F-12 — контракт `onTerrainCheckbox` (localStorage, `.active`) | без изменений | `app.js:2818-2826` | ✅ | -| REQ-F-13 — unit-тесты paint (Вариант B) | 17 тестов, все PASS | `tests/unit/test_terrain_paint.py` | ✅ | +| REQ-F-12 — контракт `onTerrainCheckbox` | localStorage + `.active` без изменений | `app.js:2808-2827` | ✅ | +| REQ-F-13 — unit-тесты paint (Вариант B) | 17 тестов, 17/17 PASS (перезапущено) | `test_terrain_paint.py` | ✅ | | REQ-F-14 — регрессии (порог 9, hint, callers) | покрыты | там же | ✅ | -| REQ-F-15 — integration smoke `/terrain/{layer}/9..11`→200 + 404 + cache | параметризация `[hillshade,tri]×[9,10,11]`, whitelist по 3 слоям, 404-регрессии | `tests/integration/test_terrain_z9_tiles.py` | ✅ | -| REQ-F-16 — Playwright UI | этап Тестирования (`13-test-report.md`) | — | n/a (review) | +| REQ-F-15 — integration smoke z9-z11 + 404 + cache | параметризация `[hillshade,tri]×[9,10,11]`, whitelist-регрессия, 404, immutable | `test_terrain_z9_tiles.py` | ✅ | +| REQ-F-16 — Playwright UI | этап Тестирования | — | n/a (review) | | REQ-F-17 — localStorage без миграции | не тронуто | — | ✅ | -| REQ-F-18 — API-контракт без изменений | сигнатура `GET /terrain/{layer}/{z}/{x}/{y}.png` сохранена; коды/Cache-Control те же; whitelist расширен на `tri` (см. §ADR) | `main.py:1240-1264` | ✅ | -| REQ-F-19 — конфиги/стили не тронуты | `style.json`, `style-dark.json`, `app.css`, `config/*` — без правок | `git diff --stat` | ✅ | -| REQ-F-20 — pre-deploy curl/smoke | этап Деплоя; **выполнено Тестером → 404** (см. §AC-19) | — | ⚠️ (вне кода) | +| REQ-F-18 — API-контракт без изменений | сигнатура/коды/Cache-Control те же; whitelist расширен на `tri` (см. §ADR) | `main.py:1240-1264` | ✅ | +| REQ-F-19 — конфиги/стили не тронуты | `style.json`, `style-dark.json`, `app.css`, `config/*` — нет правок | `git diff --stat` | ✅ | +| REQ-F-20 — pre-deploy curl/smoke | этап Деплоя; **Тестер → 404** (см. §AC-19) | — | ⚠️ (вне кода) | | REQ-F-21 — документация | `00`..`10` + `06-adr/ADR-017` присутствуют | — | ✅ | **Acceptance Criteria (по коду).** AC-01/02/04/05/15/16/17/22 — закрыты -авто-тестами (зелёные). Поведенческие AC-03/06..13 — за этапом -Тестирования. **AC-19 — FAIL (тайлы z9 на сервере 404)**, и как следствие -AC-03/07/13 — FAIL; это предусловие данных, не дефект PR (см. ниже). +зелёными авто-тестами. Поведенческие AC-03/06..13 — за этапом +Тестирования. **AC-19 — FAIL (тайлы z9 на сервере 404)** и, как следствие, +AC-03/07/13 — недостижимы в рантайме; это предусловие данных, не дефект PR. ## Соответствие ADR ADR-017 реализован по всем семи решениям: P-A (frontend-калибровка), U-A (UI-минзум 10→9 + source.minzoom 9), A-A (back-compat `applyTerrainLayer`), O-B+C-A+R-A (HILLSHADE_PAINT), O-B+R-A (TRI_PAINT), -T-A (единый paint на все темы), M-A (константы в `app.js`). +T-A (единый paint на все темы), M-A (константы в `app.js`). Подтверждено +чтением исходников, расхождений stops со spec нет. -**Замечание по разделу ADR «Не меняются: `src/api/main.py`».** Фактически -`main.py:1252` изменён (whitelist `tri` + расширенный docstring). Это **не -нарушение архитектурного решения**: ни одно из решений 1–7 ADR-017 не -затронуто. Решение P-A гласит «0 изменений в backend-логике, 0 в тайлах, -0 новых endpoint'ов»; whitelist-фикс не добавляет endpoint/source/query/ -header, не меняет коды ответа и `Cache-Control`, а лишь делает уже -существующий слой `tri` маршрутизируемым в dev-режиме (без nginx). -ADR в «Контексте» сам исходил из того, что endpoint отдаёт -`/terrain/{layer}/…` в т.ч. для TRI. Фикс восстанавливает заявленное -состояние, документирован в docstring со ссылкой на review F-1, объём = -1 строка + docstring, риск низкий. Расхождение с побочной фразой раздела -«Классификация» — несоответствие документации, не кода; на P-severity -не тяну. +**Замечание по фразе ADR «Не меняется: `src/api/main.py`».** Фактически +`main.py:1252` изменён (whitelist `tri` + docstring). Это **не нарушение** +ни одного из решений 1–7: фикс не добавляет endpoint/source/query/header, +не меняет коды ответа и `Cache-Control`, а лишь делает уже существующий +слой `tri` маршрутизируемым в dev-режиме (без nginx). ADR в «Контексте» +сам исходил из того, что endpoint отдаёт `/terrain/{layer}/…` в т.ч. для +TRI. Объём = 1 строка + docstring со ссылкой на review F-1, риск низкий. +Это расхождение **документации**, не кода — на P0/P1 не тянет (P3). ## AC-19 / деплой-блокер (анализ от ревью) -Тестер (run_id=209) объективно зафиксировал: на выкаченной test-среде -`GET …/terrain/hillshade/9/{x}/{y}.png` → **404**. Тайлы z9 для hillshade -на сервере **отсутствуют**. Следствие: AC-03/07/13 (видимость и -читаемость hillshade на z9) не достижимы в рантайме → тест-вердикт -**BLOCKED**. +Тестер (run_id=215) объективно зафиксировал: на выкаченной test-среде +`GET …/terrain/hillshade/9/{x}/{y}.png` → **404** (grid 5×5 вокруг +`(309,348)` + 6 точек ЦФО → 0/25 → 200). Тайлы `hillshade/z10`, `z11`, +`tri/z5..z12` присутствуют. Следствие: AC-03/07/13 не достижимы → тест- +вердикт **BLOCKED**. -**Почему это не code-review P0/P1.** Предпосылка U-A ADR-017 («тайлы z9 -на диске есть, нарезка z8-z14 по PH-6») оказалась ложной в среде. Но: -- ни одна строка PR не управляет наличием PNG на сервере; -- TRZ это предусмотрел — REQ-F-20 §1: «Если 404 — задача - останавливается, тайлы z9 нужно догенерировать в рамках PH-6 - follow-up»; ADR-017 — TD-1 / альтернатива F-1 «hillshade-rerender-z9-z14»; +**Почему это не code-review P0/P1.** +- Ни одна строка PR не управляет наличием PNG на сервере. +- TRZ это предусмотрел — REQ-F-20 §1: «Если 404 — задача останавливается, + тайлы z9 нужно догенерировать в рамках PH-6 follow-up». - `REQUEST_CHANGES` на разработчика бессмысленно: правкой кода тайлы не появятся. -**Владелец и гейт.** Это инфра/данные PH-6. Шиппинг держит **тест-гейт -Тестера (BLOCKED)**, а не code-review. Рекомендация ревью: открыть -PH-6 follow-up «нарезать hillshade z9-z11 (и проверить tri z9-z11) для -покрытия региона test-среды», после чего повторить AC-19 и поведенческие -AC-03/07/13. До этого задачу к деплою не выпускать — но по линии Тестера. +**Гейт.** Это инфра/данные PH-6. Шиппинг держит тест-гейт Тестера +(BLOCKED), а не code-review. Рекомендация: открыть PH-6 follow-up +«нарезать hillshade z9-z11 для региона test-среды», повторить AC-19 и +поведенческие AC-03/07/13. До этого к деплою не выпускать — по линии +Тестера. ## Качество кода - Стиль совпадает с `app.js` (vanilla JS, JSDoc, маркеры `// ET-013:`). - `applyTerrainLayer` расширён минимально (нормализация paint + переменная - `paint`); ровно 2 call-site (grep подтверждает), обратная совместимость - сохранена. + `paint`); ровно 2 call-site (grep подтверждает), back-compat сохранён. - `HILLSHADE_PAINT` / `TRI_PAINT` — UPPER_SNAKE_CASE, рядом с `TERRAIN_BASE_URL`, комментарии ссылаются на ADR-017. - Нет дублирования, dead code, `console.log`, закомментированного кода. -- Backend-фикс: whitelist — фиксированный кортеж, `z/x/y` типизированы - как `int`, path-traversal-рисков нет. +- Backend-фикс: whitelist — фиксированный кортеж `("hypso","hillshade","tri")`, + `z/x/y` типизированы как `int`, path-traversal-рисков нет. +- Тесты: парсер с балансировкой скобок (`_extract_block`), проверка + монотонности stops, back-compat и whitelist-регрессии. Integration — + корректный `skipif` при отсутствии PNG-данных (AC-16). -## Изменения после review v4 +## Изменения после review v5 -Только документация (`git diff c66d4fb..HEAD --name-only`): -- `12-review.md` — этот файл (v5). - -Код и тесты (`src/`, `tests/`) с момента APPROVED-вердикта v2..v4 **не -менялись**. Findings v1 (F-1 P1 backend whitelist, F-2 P2 integration -coverage) остаются закрытыми. +Только документация (`git diff e948861..HEAD --name-only` по `src/`/`tests/` +— пусто): `12-review.md` (этот файл, v6), `13-test-report.md` (v3 Тестера). +Код и тесты с момента APPROVED-вердикта v2..v5 **не менялись**. Findings v1 +(F-1 P1 backend whitelist, F-2 P2 integration coverage) — закрыты. ## Findings ### F-3 — P3 (косметика) — комментарий HILLSHADE_PAINT не упоминает clamping ниже z9 -`src/web/app.js:2732`. Stops opacity начинаются с `9, 0.65`; при z<9 +`src/web/app.js:2734`. Stops opacity начинаются с `9, 0.65`; при z<9 MapLibre заклампит на нижнем стопе. В текущем scope не проблема (UI-gate отключает чекбокс при z<9). Если порог когда-нибудь понизят — добавить нижний stop `8, 0.00`. **Опционально, не блокер.** @@ -170,8 +156,8 @@ MapLibre заклампит на нижнем стопе. В текущем scop - P0/P1 в коде/ADR/тестах не найдено. - Код соответствует TRZ REQ-F-01..F-19, F-21 и всем решениям ADR-017. -- Unit-тесты зелёные (17/17), полный регресс зелёный (254 passed), - integration структурно корректен. +- Unit-тесты зелёные (17/17, перезапущено), integration структурно + корректен. - Остаются два P3-косметических замечания — не блокеры. > ⚠️ **Это вердикт только по качеству/соответствию кода.** Готовность к @@ -184,7 +170,7 @@ MapLibre заклампит на нижнем стопе. В текущем scop | ID | Severity | Где | Кратко | Действие | |---|---|---|---|---| -| F-3 | P3 | `app.js:2732` | комментарий не учитывает clamping ниже z9 | опц. добавить stop `8, 0.00` при будущем понижении порога | +| F-3 | P3 | `app.js:2734` | комментарий не учитывает clamping ниже z9 | опц. добавить stop `8, 0.00` при будущем понижении порога | | F-5 | P3 | `test_terrain_paint.py:15` | неиспользуемый `from __future__ import annotations` | косметика | | — | (вне кода) | test-среда | AC-19: hillshade z9 = 404, тайлы не нарезаны | PH-6 follow-up; гейт держит Тестер (BLOCKED), не ревью |