1. Назначение risk map как карты решений
Когда вы впервые заходите в legacy-сервис вроде CashFlow Dashboard, соблазн очень понятный: выписать длинный список всего неприятного и почувствовать, что работа проделана. Тут deprecated, тут мало тестов, тут конфиг как будто писал человек в лифте между этажами. Команде такой список почти бесполезен: он не подсказывает, куда идти, а куда лучше даже не совать отвёртку.
RISK_MAP.md нужен именно для этого: превращает хаос знания в управляемую карту «что опасно менять, насколько это важно для бизнеса и какое действие разумно следующим». Legacy не страдает от того, что код местами грустный. Legacy страдает от того, что кто-то говорит «да я тут одну строчку поправлю», — и к вечеру у финменеджера MRR съезжает на восемь процентов.
Полезно держать в голове три артефакта рядом, потому что они отвечают на разные вопросы:
| Артефакт | На какой вопрос отвечает |
|---|---|
|
Что вообще есть в проекте? |
/ current-state notes |
Как система реально работает сейчас? |
|
Где изменение наиболее опасно и что с этим делать? |
Если говорить совсем по-простому, inventory — карта улиц, current-state документ — описание дорожного движения, а risk map — пометки «здесь мост ремонтируют, сюда лучше не соваться без плана». И вот эта третья часть чаще всего оказывается самой практичной: спасает команду от героического, но очень дорогого хаоса.
Поэтому RISK_MAP.md — не Markdown-версия тревожного дневника, а способ перестать относиться ко всем зонам одинаково: mrr-engine, флаги в конфиге и старый класс из legacy/ не равны по риску, даже если просятся «срочно почистить».
2. Две оси: criticality и change risk
Самая полезная мысль в этой лекции очень простая: у risk map всегда минимум две оси. Первая — «насколько больно бизнесу, если область сломается», вторая — «насколько вероятно и дорого что-то сломать, если туда полезть». Пока вы их не разделили, карта врёт.
Business criticality, важность для бизнеса, измеряется не красотой кода, а последствиями. Сломалась логика MRR — это видит Commerce OS, финансовые отчёты, бухгалтерия, и через пару часов это денежная проблема. Сломался формат подписи в неключевом отчёте — мир не падает.
Change risk, риск изменения, смотрит совсем в другую сторону: здесь интересно не то, насколько область важна, а то, насколько она хрупка. Низкое покрытие, расхождение документации и кода, высокий churn в истории Git, неясный владелец, конфиг между yaml и переменными окружения — всё это делает зону опасной, даже если она не главный бизнес-флоу.
Хорошо работает такая упрощённая матрица:
| Важность для бизнеса \ Риск изменения | Низкий риск изменения | Высокий риск изменения |
|---|---|---|
| Низкая важность | Можно исследовать и менять достаточно свободно | Не стоит чинить «заодно»; сначала понять, почему зона такая хрупкая |
| Высокая важность | Менять можно только узко и с явной проверкой | Красная зона: сначала нужны дополнительные доказательства, владелец и ограничения |
Именно поэтому mrr-engine в CashFlow Dashboard почти автоматически падает в правый верхний угол: бизнес-критичен и рискован в изменении. А старый utility-класс из legacy/, даже уродливый, скорее попадёт в «высокий change risk, но не первый приоритет по бизнесу».
Очень важно не склеивать эти оси в одну оценку «опасно / не опасно». Иначе команда либо панически избегает всех изменений, либо беспечно трогает критичные флоу. Legacy такие иллюзии любит. Потом выставляет счёт.
3. Unknowns как полноценный сигнал риска
На legacy-проектах слово «unknowns» звучит менее торжественно, чем должно, — а на практике именно неизвестность часто и есть главный усилитель риска. Самое опасное здесь — притвориться, будто картина ясна. Claude Code тоже не прочь сделать умное лицо и продолжить — не поддавайтесь.
Неизвестность в risk map — не мусорный остаток после анализа, а полноценный сигнал. Не знаем, как система ведёт себя на границе месяца при смене таймзоны, — это не «пока без оценки», а повышенный риск. У PaymentRetryService логика вроде бы восстанавливает подписку после retry, но теста нет — и неизвестность сама поднимает change risk.
На CashFlow Dashboard хороший пример — тема паузы подписки. Документ говорит, что paused subscription не входит в активный MRR, а код в MrrFormulas.java считает её активной. Честная формулировка не «логика, наверное, исключает paused», а «документация и код расходятся; нужна ручная проверка».
Полезное правило здесь жёсткое: если Claude не показал evidence anchor, значит, он не знает, а предполагает. Тогда в артефакте появляется пометка assumption или manual verification needed, а не уверенный вывод. Проект и так страдает от накопленных полуправд — не добавляйте ещё одну, теперь с искусственным интеллектом.
И да, иногда самое профессиональное действие на этом этапе — честно написать: «владелец области неочевиден», «реальное поведение в проде не подтверждено», «конфиг собран из нескольких источников и требует ручной сверки». Не слабость аналитика, а инженерная гигиена.
4. Содержание одной записи в RISK_MAP.md
Когда risk map сделан хорошо, он читается быстро и помогает так же быстро принимать решения, поэтому структура записи простая и повторяемая, без литературных отступлений на полстраницы. Сам файл — артефакт проекта: Workflow Kit даст шаблон, skill или read-only агента, но RISK_MAP.md живёт рядом с CashFlow Dashboard.
На практике одна запись отвечает на семь вопросов, сводя наблюдения из signal log и current-state не в дубль, а в решение.
| Поле | Что оно должно прояснить |
|---|---|
|
О какой области проекта идёт речь |
|
Насколько больно бизнесу, если там что-то сломается |
|
Насколько опасно вносить туда изменения |
|
Какого типа это риск: данные, конфиг, неизвестное поведение, слабые тесты и так далее |
|
На чём основан вывод: файлы, строки, логи, отчёты, git log, coverage |
|
Чего нам не хватает для уверенного изменения |
|
Что разумно сделать сейчас, а не когда-нибудь в светлом будущем |
Запись не должна превращаться в мини-роман. Вот компактный рабочий фрагмент:
## Область
mrr-engine / pause-resume MRR
**Business criticality:** высокая
**Change risk:** высокий
**Risk categories:** business-critical, no-test, unknown behavior
**Evidence:** `MrrFormulas.java:88`, `SubscriptionService.java:154`, JaCoCo ~25%
**Missing checks:** нет сценария pause-resume
**Recommended action:** не менять формулы до фиксации текущего поведения и review владельцем
Обратите внимание на две ловушки. Missing checks — не Evidence: одно говорит, что мы знаем, другое — чего нет. А Recommended action — не «улучшить код», а исполнимое действие: заморозить изменение, уточнить владельца, зафиксировать поведение, ограничить scope, не трогать зону.
Если у записи нет последней строки, она почти всегда бесполезна: risk map существует ради выбора следующего хода, а не описания страха.
5. Использование Claude Code
На этом этапе Claude Code очень полезен, но строго в режиме «ускоряем сбор evidence», а не «пусть сам поставит диагноз». Держите сессию в read-only: агент читает, ищет по коду, смотрит git log, открывает отчёты, но не редактирует. Нам не нужен энтузиаст с редактором — нужен быстрый аккуратный исследователь.
Хороший запрос к Claude в этой задаче выглядит структурированно и скучно — и это комплимент:
Проанализируй область `mrr-engine` как элемент risk map.
Верни:
1. business criticality,
2. change risk,
3. categories,
4. evidence,
5. missing checks,
6. recommended action.
Код не меняй.
Формат возвращает данные в форме, из которой реально собрать RISK_MAP.md, и не даёт Claude соскочить в привычное «вот ещё три идеи рефакторинга, которые я придумал вам бесплатно». Бесплатное в legacy потом оплачивается дорого.
Если команда уже собрала Workflow Kit, там может жить read-only агент risk-mapper — с нарочно скучной и ограниченной конфигурацией:
---
name: risk-mapper
description: Собирает RISK_MAP.md только по evidence, без правок кода
tools: Read, Grep, Glob, Bash(git log:*)
---
Здесь важно именно ограничение. Выдай агенту Edit — он рано или поздно начнёт «помогать», а нужна дисциплина: прочитай, сравни, собери anchor, пометь неизвестное, остановись.
Ещё одна полезная привычка — требовать опору под каждым выводом. «Зона высокого риска из-за сложности» — красиво и бесполезно; пусть покажет файл, coverage, git log, расходящийся с кодом документ. Не может — значит, гипотеза, помеченная честно.
И ещё один технический нюанс, о котором часто забывают: держите файл рядом с кодом, иначе через две недели он станет «где-то там была полезная markdown-ка», которую никто не открывает.
6. CashFlow Dashboard: mrr-engine, retry и конфиги
Теперь давайте приземлим всё это на проект. В CashFlow Dashboard есть как минимум три очень показательные зоны — они хороши тем, что показывают: высокий риск рождается из комбинации бизнес-критичности и слабой проверяемости. Сначала посмотрим на компактную картину:
| Область | Business criticality | Change risk | Почему это опасно | Разумное действие |
|---|---|---|---|---|
|
Высокая | Высокий | Влияет на MRR, coverage низкий, код и документы расходятся | Не менять формулы без фиксации текущего поведения |
|
Высокая | Высокий | Задеты деньги, внешняя интеграция, неочевидные ветки retry | Сначала уточнить реальный поток и владельца области |
|
Средняя/высокая | Высокий | Конфиг размазан по yaml и env, таймзона ведёт себя неравномерно | Сначала собрать current-state конфигурации, не трогать «заодно» |
mrr-engine — почти учебный пример красной зоны. Есть реальная бизнес-боль: Commerce OS уже жалуется на расхождение MRR, а под капотом низкое покрытие и формулы в нескольких файлах. Даже простой сигнал из Git это подсвечивает:
git log --since="1 year ago" --name-only --pretty=format: \
| grep 'mrr-engine/MrrFormulas.java' | wc -l
# 11
Одиннадцать изменений сами по себе ещё ничего не доказывают. Но сложите их с coverage около 25% и расхождением документа с кодом — и получится уже не ощущение, а вполне приличный пакет доказательств. Запись для mrr-engine:
## Область
mrr-engine / pause-resume MRR
**Business criticality:** высокая
**Change risk:** высокий
**Risk categories:** business-critical, no-test, unknown behavior
**Evidence:** `MrrFormulas.java:88`, `SubscriptionService.java:154`, `git log`, JaCoCo ~25%
**Missing checks:** нет сценария pause-resume и проверки границы месяца
**Recommended action:** ограничить любые изменения, пока не подтверждено текущее поведение
Теперь возьмём payments / retry recovery — здесь risk map менее очевидна, потому что код иногда аккуратнее, чем в mrr-engine. Но даже при лучшем покрытии ошибка дорогая — особенно когда неясно, когда подписка восстановлена после retry, а когда должна попасть в churn.
Третья зона — конфиги и таймзона. Это тот случай, когда многие недооценивают риск, потому что «мы же не меняем бизнес-логику, только поправим конфиг». На legacy такая фраза звучит примерно как «я только чуть-чуть подвинул кирпич в несущей стене». Feature flags размазаны между application.yml, окружением и старыми overrides, даты местами идут через UTC, местами через local time — change risk высокий даже без алгебраических формул.
И есть ещё один коварный пример: legacy/OldBillingUtils.java. Важность для бизнеса у него может быть неочевидной, на первый взгляд — просто старый utility, который очень хочется переписать ради внутреннего мира и душевного здоровья. Но он используется в десятках мест и без покрытия — change risk высокий. Risk map позволяет сказать: «нет, это не первая цель» — не потому, что код хороший, а потому, что цена неосторожного улучшения выше ожидаемой пользы.
7. Чтение готовой risk map и принятие решений
Когда RISK_MAP.md начинает работать, он перестаёт быть документом «для галочки» и становится фильтром: каждый новый вопрос по legacy звучит немного иначе — не «можем ли мы это быстро поправить?», а «что карта говорит о цене исправления?».
Хорошая карта помогает принимать четыре практичных решения. Иногда она говорит: сюда можно идти, но узко и аккуратно. Иногда: сюда — только после уточнения владельца и поведения. Иногда: сюда вообще не надо лезть в рамках задачи, она раздуется и утащит ещё три подсистемы. И, что особенно ценно, иногда карта даёт право сказать «не сейчас» — не из страха, а из инженерной дисциплины.
При этом карта не обязана быть огромной, ей не нужно покрывать каждый файл: десять содержательных записей полезнее пятидесяти строк «что-то тут тревожно». Не помогает решить, как вести себя с областью, — значит, запись ещё сырая.
И да, risk map — живой артефакт: появился владелец, подтянули evidence, исчезло расхождение документа и кода — место зоны меняется. Но начинаем не с оптимизма, а с доказательств.
Когда вы смотрите на CashFlow Dashboard и вместо импульса «надо срочно всё почистить» спокойно говорите: «вот красная зона, вот почему она красная, и почему туда сейчас нельзя без дополнительного evidence», — RISK_MAP.md уже не декоративный. Он работает. Так и начинается взрослое отношение к legacy — даже если сам legacy всё ещё выглядит так, будто его писали в ночь перед релизом.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ