26 KiB
26 KiB
type, work_item_id, title, version, status, created_at, authors
| type | work_item_id | title | version | status | created_at | authors | |
|---|---|---|---|---|---|---|---|
| tech-risks | ET-013 | Технические риски — ET-013: Zoom-aware paint для terrain-слоёв на z9-z11 | 1 | approved | 2026-06-04 |
|
Технические риски — ET-013
Технические риски этапа калибровки клиентского paint для растровых terrain-слоёв. Бизнес-риски — в BRD §5 (R-1..R-11). Шкала: вероятность (Н/С/В) × влияние (Н/С/В).
R-T-1 — Тайлы hillshade z9-z11 отсутствуют на test-среде
- Описание: BRD §2.1 утверждает, что PH-6 нарезала hillshade z8-z14. Если реальная нарезка на mva154 отличается (например, z10-z14), при включении hillshade на z9 пользователь увидит 404-шахматную доску, а в DevTools — череду failed requests.
- Вероятность / Влияние: Н / В.
- Митигация:
- Архитектурное решение (ADR-017 §U-A): pre-deploy smoke
curl -Iна 3 разных тайла (z9/z10/z11) над ЦФО — обязателен перед merge (07-infra-requirements.md§6.2 шаг 1, AC-19). - Эскалация: при 404 — задача останавливается, открывается PH-6 follow-up «hillshade-z9-z14 backfill». ET-013 не мержится.
- Acceptance гейт: AC-19 в
03-acceptance-criteria.md.
- Архитектурное решение (ADR-017 §U-A): pre-deploy smoke
R-T-2 — raster-contrast 0.40 даёт «пересвет» / черноту на тёмных тайлах
- Описание: На z9-z11 hillshade-тайлы из тёмных лесных зон
(низкая средняя яркость PNG) при
raster-contrast: 0.40могут «провалиться в черноту» — пиксели clipping'уются к 0, тени превращаются в чёрные кляксы, теряя информацию. - Вероятность / Влияние: С / С.
- Митигация:
- Архитектурное решение (ADR-017 §C-A): stops контраста подобраны консервативно (0.40 на z9 → быстрый спад к 0 на z14); значения калибруются по результатам визуальной приёмки.
- Acceptance гейт: TC-UI-04-Z10-Q (BRD R-1, AC-07..AC-09) — оператор смотрит скриншоты на холмистом районе. При «пересвете» — снижаем contrast в stops до 0.25-0.30 итеративно.
- Принцип: stops живут в коде, правка — одна строка, не ADR.
R-T-3 — 'nearest'-resampling на overzoom z12-z14 даёт пикселизацию
- Описание: При overzoom (когда MapLibre тянет тайл z14 для
z15-z18)
'nearest'-resampling показывает крупные квадраты вместо плавных теней. Это особенно заметно на hillshade. - Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение (ADR-017 §R-A): MapLibre не
поддерживает
interpolateдляraster-resampling, поэтому глобальное'nearest'— единственный простой путь. Альтернатива (два layer'а) отклонена как overkill. - Контекст использования: на z12+ пользователь обычно отключает hillshade в пользу подложки (для города нужны улицы, а не тени). Это вторичный сценарий.
- Acceptance гейт: AC-10 (TC-UI-06-Z14-Q) — оператор подтверждает «не темнее и не контрастнее, чем до ET-013» (т.к. opacity и contrast уже вернулись к baseline). Пикселизация допустима, если не нарушает читаемость.
- Fallback: если визуально неприемлемо — отдельным минорным
патчем вводится второй layer hillshade с
'linear'для z12+, переключаемый поgetZoom(). Это не часть ET-013.
- Архитектурное решение (ADR-017 §R-A): MapLibre не
поддерживает
R-T-4 — Сетевой трафик растёт > +35% при активной zoom-сессии
- Описание: Снижение UI-минзума hillshade с 10 до 9 добавляет +1 zoom-уровень. На активной сессии (пользователь крутит зум z8→z11→z8→z11 много раз) первая загрузка z9 тайлов даёт заметную дельту трафика. BRD M-10 = ≤ +35%.
- Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение:
Cache-Control: public, max-age=31536000, immutable(src/api/main.py:1252) + браузерный кэш + nginx-кэш. После первого визита повторные запросы дают 304 If-Modified-Since (или вовсе не доходят до сервера — browser hits memory cache). - Acceptance гейт: AC-21 в
03-acceptance-criteria.md— network-traffic ≤ 135% от baseline на сценарии zoom-петли z=8→9→10→11→10→9→8. - Мониторинг: см.
07-infra-requirements.md§7.1 — первая неделя оператор смотритnginx access.logна аномалии.
- Архитектурное решение:
R-T-5 — На тёмной теме (ET-007 theme-dark) hillshade с opacity 0.65 + contrast 0.40 сливается в кашу
- Описание: Тёмная подложка + полупрозрачный тёмный hillshade с усиленным контрастом → визуально неразличимая «грязь». BRD R-2.
- Вероятность / Влияние: С / С.
- Митигация:
- Архитектурное решение (ADR-017 §T-A): в MVP — один paint
для всех тем. Если AC-11 проваливается — открывается ADR-018
«theme-specific terrain paint» с отдельной таблицей stops для
theme-dark(через подписку наtheme-changeevent иsetPaintProperty). - Acceptance гейт: AC-11 (TC-UI-09-Z10-DARK-Q) — оператор
проверяет на dark + holmistom районе. Если провал — фиксируется
в
13-test-report.mdи открывается follow-up. - Принцип: не плодим сложность пока не доказана необходимость.
- Архитектурное решение (ADR-017 §T-A): в MVP — один paint
для всех тем. Если AC-11 проваливается — открывается ADR-018
«theme-specific terrain paint» с отдельной таблицей stops для
R-T-6 — На спутниковой подложке (ET-007) hillshade «глушит» снимок
- Описание: Esri World Imagery уже содержит визуальный рельеф (тени снимков). Поверх него полупрозрачный hillshade с opacity 0.65 → снимок превращается в «серую плёнку», пользователь теряет цвета поверхности. BRD R-3.
- Вероятность / Влияние: Н / С.
- Митигация:
- Архитектурное решение (ADR-017 §T-A): UX-нота: на спутнике
пользователь обычно отключает hillshade — снимок и так
«показывает» рельеф. Если AC-12 проваливается — open ADR-018
с правилом «на satellite layer'е opacity hillshade = старые
0.40» (через подписку на
applyBaseLayer). - Acceptance гейт: AC-12 (TC-UI-08-Z10-SAT-Q).
- Принцип: не плодим сложность пока не доказана необходимость.
- Архитектурное решение (ADR-017 §T-A): UX-нота: на спутнике
пользователь обычно отключает hillshade — снимок и так
«показывает» рельеф. Если AC-12 проваливается — open ADR-018
с правилом «на satellite layer'е opacity hillshade = старые
0.40» (через подписку на
R-T-7 — TRI с opacity 0.85 на z9-z11 перекрывает грунтовки/тропы
- Описание: Слой
trails-*(грунтовки, тропы) рисуется тонкими линиями. Если TRI поднять до opacity 0.85, цветные пятна категориальной палитры могут визуально «убить» линии трасс. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение: существующая логика в
applyTerrainLayer(src/web/app.js:3337-3339) вставляет terrain-слои перед первымtrails-*илиpoi-*слоем — z-order корректный. TRI рисуется ПОД линиями трасс, не НАД. - Тесты: AC-07..AC-09 (визуальная приёмка на холмистом районе с грунтовками).
- Архитектурное решение: существующая логика в
R-T-8 — MapLibre 4.7.0 не поддерживает interpolate для raster-contrast
- Описание: Если документация MapLibre врёт или версия 4.7.0
имеет regression на
raster-contrastс zoom-выражением, paint не применится, в DevTools будет warning, hillshade покажется с default contrast = 0. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение (NFR-04 в TRZ §4): MapLibre 4.7.0
официально поддерживает
interpolateдля всех raster paint properties, кромеraster-resampling. Проверка — публичная документация maplibre.org. - Smoke-проверка после деплоя: DevTools
window._map.getPaintProperty('terrain-hillshade', 'raster-contrast')должен вернуть массив['interpolate', ...](AC-04). - Fallback: если фактически не работает — заменить на
case-step выражение (грубое stepwise) или просто оставить числовую константу0.30для z9-z11 (одно значение, без zoom-плавности).
- Архитектурное решение (NFR-04 в TRZ §4): MapLibre 4.7.0
официально поддерживает
R-T-9 — Регрессия z8: после правки TRI_PAINT на z8 перепады выглядят иначе
- Описание: В новой
TRI_PAINTдля z=8 стоит0.70— точно как было. Но если при правке нечаянно поставить8, 0.75(или пропустить стоп для z8 — тогдаinterpolateмежду7→0.65и9→0.80даст на z8 значение ~0.72), регрессия z8 нарушится. - Вероятность / Влияние: С / С.
- Митигация:
- Архитектурное решение (ADR-017 §O-B): в
TRI_PAINTявно указан стоп8, 0.70(не полагаемся на интерполяцию между соседними стопами). - Acceptance гейт: AC-06 (TC-UI-02-Z8-REGR) — скриншот сравнивается с до-ET-013 baseline.
- Unit-тест: REQ-F-13 проверяет наличие
8, 0.70в исходникеTRI_PAINTчерез regex.
- Архитектурное решение (ADR-017 §O-B): в
R-T-10 — Регрессия z14: hillshade «не возвращается» к baseline
- Описание: Если stops
HILLSHADE_PAINTне закрываются явным стопом на z14 (например,14, 0.40, 14, 0.00), MapLibre экстраполирует за пределами последнего стопа, и на z14-z15 hillshade может остаться «перегретым» (opacity 0.55, contrast 0.20). - Вероятность / Влияние: Н / С.
- Митигация:
- Архитектурное решение (ADR-017 §O-B / §C-A):
interpolateу MapLibre clamp'ит значения за пределами крайних stops (clamping behavior). Явные стопы14, 0.40для opacity и14, 0.00для contrast обеспечивают регрессию z14. - Acceptance гейт: AC-10 (TC-UI-06-Z14-Q) — скриншот сравнивается с до-ET-013 baseline.
- Unit-тест: REQ-F-13 проверяет наличие
14, 0.40и14, 0в исходникеHILLSHADE_PAINT.
- Архитектурное решение (ADR-017 §O-B / §C-A):
R-T-11 — applyTerrainLayer ломает обратную совместимость
- Описание: При расширении сигнатуры
opacity → opacityOrPaint: number | objectсуществующая логика (если есть где-то ещё вsrc/web/) может сломаться при передаче числа. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение (ADR-017 §A-A): внутри функции —
нормализация
(typeof opacityOrPaint === 'number') ? {…linear…} : opacityOrPaint. Старый контракт работает без изменений. - Acceptance гейт: AC-22, UT-COMPAT-01 (REQ-F-14) — статический
grep по
src/web/*.js: подтверждает, что вызововapplyTerrainLayerтолько два (оба вonTerrainCheckbox), оба переведены на новые константы. - Принцип: unit-тест на нормализацию + явный комментарий
// ET-013: backwards-compat shimв коде.
- Архитектурное решение (ADR-017 §A-A): внутри функции —
нормализация
R-T-12 — Старый клиент (закэшированный в браузере) не подхватывает новый app.js
- Описание: Пользователь с открытой вкладкой неделю назад имеет
закэшированный старый
app.jsсо старымapplyTerrainLayerбез paint-нормализации. При reload браузер должен дёрнуть свежийapp.js. Service worker — не настроен в MVP (PH-9 не реализована). - Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение:
src/web/index.htmlзагружаетapp.jsнапрямую (без SW). nginx +Cache-Controlна*.js— стандартные (не immutable; If-Modified-Since работает). При reload браузер делает conditional GET → 200 (если файл изменился) или 304. - Backwards compat: старый клиент с
minzoom=10для hillshade продолжает работать; он просто не запрашивает hillshade z=9. Никаких 4xx-ответов нет (REQ-F-18 — контракт неизменен). - Митигация в долгую: PWA / SW (PH-9) введёт правильную inval-стратегию.
- Архитектурное решение:
R-T-13 — Hint «Зум 10+» забыт в HTML → расхождение с фактическим порогом
- Описание: В
src/web/index.htmlстрока<span id="terrain-hillshade-hint">Зум 10+</span>. Если правка REQ-F-10 потеряется (например, мердж-конфликт), у пользователя на z<9 будет hint «Зум 10+», который противоречит фактическому порогу 9. - Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение (REQ-F-10): в HTML текст явно меняется на «Зум 9+». Это атомарная правка, проверяется grep'ом.
- Acceptance гейт: AC-01 — проверяет
«Зум 9+»в исходникеindex.html. AC-03 — проверяетhint.style.display === 'none'на z=9. - Unit-тест: REQ-F-14 (UT-REG-02) — grep по строке
zoom < 9вapp.jsи«Зум 9+»вindex.html.
R-T-14 — nearest-resampling на TRI делает «зернистую» картинку, пользователю не нравится
- Описание: TRI — категориальная палитра (5 уровней). На
'nearest'ясно видны 30-метровые SRTM-клетки, картинка выглядит «зернистой». BRD R-10 классифицирует это как «желаемое поведение» (показ «реальных» границ перепадов), но возможен субъективный негативный отзыв. - Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение (ADR-017 §R-A): на TRI «зернистость»
— спецификация. Категориальные данные требуют резких границ,
'linear'их размывает. - Fallback: если AC-07..AC-09 проваливаются с пометкой
«зернисто» — откатывается F-09 (TRI →
'linear'), hillshade остаётся на'nearest'. Это одна строка кода вTRI_PAINT. - Acceptance гейт: AC-07..AC-09 — оператор подтверждает качественную приёмку.
- Архитектурное решение (ADR-017 §R-A): на TRI «зернистость»
— спецификация. Категориальные данные требуют резких границ,
R-T-15 — Performance деградация из-за interpolate в paint
- Описание: Если MapLibre на каждом zoom-tick пересчитывает
interpolate-выражение без кэширования, на слабых устройствах (mobile, low-end) может появиться jank при зуме. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение (NFR-01 в TRZ §4): MapLibre кэширует
скомпилированные
interpolate-выражения; вычисление при смене zoom — < 1 мс на frame. - Эмпирически: существующие слои
gps_tracks.js,trails-*уже используютinterpolateпо zoom без жалоб. - Тест: AC-13 (TC-UI-07-Z9-MOBILE) — Playwright mobile viewport, проверяет работоспособность; не measure'ит FPS, но регрессия проявится визуально.
- Архитектурное решение (NFR-01 в TRZ §4): MapLibre кэширует
скомпилированные
R-T-16 — Pre-deploy smoke не покрывает все регионы (тайлы z9 могут отсутствовать вне ЦФО)
- Описание: Pre-deploy
curlпроверяет 3 тайла над ЦФО. Если нарезка z9 ограничена только ЦФО, пользователь над Уралом / Алтаем увидит 404. По BRD §6 это OOS (MVP покрывает только ЦФО), но риск стоит явно зафиксировать. - Вероятность / Влияние: С / Н.
- Митигация:
- Архитектурное решение: в MVP test-среда обслуживает ЦФО
(
centralfederal.sqlite). Тайлы вне ЦФО — out of scope. - Принцип: если пользователь панорамирует за пределы ЦФО, на z9-z14 он увидит «шахматку» из 404 и для terrain, и для trails — это известная граница MVP, не баг ET-013.
- Документация: зафиксировать в
14-deploy-log.mdкак «known limitation».
- Архитектурное решение: в MVP test-среда обслуживает ЦФО
(
R-T-17 — eslint падает на новых interpolate-массивах
- Описание: Если в проекте настроен
eslintс правиламиno-magic-numbersили жёсткимmax-len, длинные массивы['interpolate', ['linear'], ['zoom'], 9, 0.65, …]могут завалить линтер. - Вероятность / Влияние: Н / Н.
- Митигация:
- Архитектурное решение: существующие JS-файлы
(
gps_tracks.js) уже используют похожие массивы — значит, eslint их пропускает. - Acceptance гейт: AC-18 (
make lintзелёный). При проблеме — добавить// eslint-disable-next-lineточечно.
- Архитектурное решение: существующие JS-файлы
(
R-T-18 — Калибровка stops «не угадывает» желаемую читаемость с первого раза
- Описание: Значения
9→0.65, 10→0.60, 11→0.55для hillshade выбраны архитектором по эстимейту из BRD. На реальных данных оператор может сказать «на z9 ещё мало, на z10 уже слишком темно». Это итеративный процесс, не «упало». - Вероятность / Влияние: В / Н.
- Митигация:
- Архитектурное решение: stops живут в JS-константах
HILLSHADE_PAINT/TRI_PAINT. Правка одной цифры — одна строка кода + новый коммит. Не требует архитектурного re-decide (ADR-017 §«Технический долг» TD-1). - Процесс: после первого деплоя — фикс stops по фидбеку оператора без новой задачи. Учитывать в bandwidth-плане до закрытия ET-013.
- Гейт: AC-07..AC-09 — качественные, оператор-driven. Они и есть «точка калибровки».
- Архитектурное решение: stops живут в JS-константах
Сводная таблица
| # | Риск | Вер | Влиян | Митигация (тип) |
|---|---|---|---|---|
| R-T-1 | Тайлы z9-z11 отсутствуют | Н | В | Pre-deploy smoke + AC-19; STOP на 404 |
| R-T-2 | raster-contrast 0.40 — пересвет/чернота |
С | С | Итеративная калибровка stops; AC-07..AC-09 |
| R-T-3 | 'nearest' пикселизация на z12+ |
С | Н | Принимается; fallback — двойной layer |
| R-T-4 | Трафик +35% превышает гейт M-10 | Н | Н | immutable кэш; AC-21 |
| R-T-5 | Hillshade на тёмной теме — каша | С | С | AC-11; follow-up ADR-018 при провале |
| R-T-6 | Hillshade «глушит» спутник | Н | С | AC-12; follow-up ADR-018 при провале |
| R-T-7 | TRI 0.85 перекрывает trails | Н | Н | Existing z-order (terrain ПОД trails) |
| R-T-8 | MapLibre 4.7.0 не поддерживает interpolate для raster-contrast | Н | Н | Документация подтверждает; fallback — case-step |
| R-T-9 | Регрессия z8 TRI | С | С | Явный стоп 8, 0.70; AC-06; unit-тест |
| R-T-10 | Регрессия z14 hillshade | Н | С | Явные стопы 14, 0.40 и 14, 0; AC-10 |
| R-T-11 | applyTerrainLayer обратная совместимость |
Н | Н | Нормализация внутри функции; UT-COMPAT-01 |
| R-T-12 | Старый клиент в кэше браузера | С | Н | Backwards-compat контракта |
| R-T-13 | Hint «Зум 10+» забыт | С | Н | grep-проверка + AC-01 |
| R-T-14 | TRI 'nearest' — зернисто |
С | Н | Specified behavior; fallback — откат F-09 |
| R-T-15 | interpolate deg performance |
Н | Н | MapLibre кэширует expr; NFR-01 |
| R-T-16 | Pre-deploy smoke ≠ покрытие региона | С | Н | Known MVP limitation; deploy-log |
| R-T-17 | eslint падает на длинных массивах | Н | Н | Существующий код уже использует такие массивы |
| R-T-18 | Stops не угадывают с первого раза | В | Н | Итеративная калибровка; AC-07..AC-09 — qualitative |
Связанные документы
01-brd.md§5 Бизнес-риски R-1..R-11 (часть пересекается)02-trz.md§3 REQ-F-04..REQ-F-15 (paint, тесты), §4 NFR-01..NFR-0706-adr/ADR-017-zoom-aware-terrain-paint.md§«Решение», §«Последствия», §«Технический долг»07-infra-requirements.md§3 (network), §6 (deploy procedure), §7 (мониторинг)08-data-requirements.md§3.3 (pre-deploy validation), §5 (API contracts)03-acceptance-criteria.mdAC-01..AC-22 (все гейты)