1. Legacy — это зона неопределённости
Когда люди впервые слышат слово legacy, им почти всегда хочется представить древний монолит цвета говна мамонта, который компилируется только в полнолуние. На деле это не про возраст и не про язык: legacy начинается там, где поведение системы плохо зафиксировано, ownership размыт, а цена неудачного изменения неприятно высока.
CashFlow Dashboard отлично подходит под это определение — и подходит не из-за старого стека (Java 8, Spring Boot 2.7.18, PostgreSQL 12, Gradle 7.6.4). Сам по себе старый стек ещё не делает проект legacy. Legacy здесь делает другое: Commerce OS уже зависит от расчётов дашборда, MRR разъехался на 8%, часть правил живёт в коде, часть — в устаревшей документации, тесты покрывают проект неравномерно. Вы пока не знаете, какое изменение безопасно, а какое тихо уронит доверие к цифрам в отчётах.
На практике change risk растёт не сам по себе, а когда сходятся сразу три фактора:
- поток важен для бизнеса — деньги, подписки, отчёты, возвраты;
- поведение плохо зафиксировано — мало тестов, документация противоречива, допущения неясны;
- область изменения расползается по нескольким модулям, конфигам, интеграциям.
Сошлись все три — перед вами уже не «кусок старого кода», а потенциальная мина.
Хорошая аналогия здесь — старый дом. Если вы вошли в него, первая задача не в том, чтобы выбирать цвет стен: вы ищете несущие конструкции, смотрите, куда подведено электричество и почему одна дверь открывается только ногой и с молитвой. В legacy так же: прежде чем двигать мебель, найдите несущие стены.
В legacy-системе первый вопрос звучит не «как тут всё устроено?», а «что здесь опасно трогать без доказательств?».
2. От «объясни проект» к «что опасно трогать»
На ранних уровнях вы уже делали codebase discovery: строили карту проекта — языки, фреймворки, директории, entry points, команды запуска, модули. Для legacy этого уже мало: красивый обзор структуры не отвечает на главный практический вопрос — где менять код спокойно, а где сначала снять обувь, каску и, возможно, гордость. И разницу тут полезно увидеть не как теорию, а как смену угла зрения:
| Обычный codebase discovery | Legacy discovery |
|---|---|
| Главный вопрос: как устроен проект? | Главный вопрос: что опасно менять? |
| Полезный результат: карта модулей и entry points | Полезный результат: критические потоки, risky areas, test gaps, unknowns |
| Неясности считаются временным шумом | Неясности фиксируются как артефакт |
| После обзора можно быстро перейти к реализации | После обзора сначала строится картина рисков |
| Выход: CODEBASE_INVENTORY.md | Выход: discovery-note, черновик RISK_MAP.md, current-state notes |
Это важный сдвиг. Если раньше хороший ответ Claude звучал как «проект состоит из модулей subscriptions, billing, payments, reporting», то теперь хороший ответ должен звучать иначе: «mrr-engine влияет на деньги и отчёты, тестов мало, правила pause/resume неочевидны, расчёт даты использует разные timezone-ветки — область пока нельзя менять без дополнительной фиксации поведения».
Заметьте, структура проекта при этом никуда не делась — она всё ещё нужна: CODEBASE_INVENTORY.md остаётся базовой картой. Но в legacy поверх неё ложится второй слой — risky areas, unknowns, current-state observations, — и из него вырастает решение, что безопасно менять. Поэтому я прошу Claude не «объяснить репозиторий», а вернуть критические runtime-потоки, зоны change risk, существующие тесты и список непонятного.
3. Evidence anchor превращает слова в знание
На этом этапе у многих появляется очень человеческое желание: получить от Claude красивую, уверенную сводку, кивнуть и пойти дальше. Вот здесь и срабатывает классическая ловушка legacy. Уверенный тон ещё не знание. Знание начинается там, где у каждого важного вывода есть evidence anchor: привязка к коду, тесту, конфигу, логу или команде.
Представьте, что Claude говорит: «Paused subscriptions остаются в active MRR». Здесь вы не отвечаете «ага, убедительно». Вы спрашиваете: в каком файле, в какой функции, есть ли тест, что говорит job, запускающий расчёт, и нет ли документа, который этому противоречит. Главное — проверяемость без телепатии.
Вот так может выглядеть маленький фрагмент нормального discovery-отчёта:
## Подсистема: mrr-engine
**Назначение:** ежедневный расчёт MRR-снимка.
**Доказательства:**
- `mrr-engine/MrrCalculator.java:42` — входная точка `computeDailySnapshot`
- `jobs/MrrSnapshotJob.java:55` — плановый запуск по расписанию
- `tests/integration/MrrSnapshotIT.java` — всего 3 интеграционных сценария
**Неясно:**
- как учитывается pause/resume подписки
- везде ли используется UTC при расчёте даты снимка
Сила такого фрагмента не в красоте, а в честности: подтверждённое и непонятное стоят рядом, и непонятное не спрятано. В legacy неизвестное не позор, а результат работы — гораздо хуже, когда из желания «выглядеть уверенно» сомнения стирают.
Полезно держать в голове ещё одну фразу: README — хороший свидетель, но не судья. Source of truth — в коде, тестах, конфиге и поведении. Если BILLING_RULES.md говорит одно, а MrrFormulas.java делает другое — верьте не красивому файлу, а тому, что легче проверить.
4. Discovery-сессия без вреда проекту
Очень соблазнительно открыть legacy-репозиторий и через пять минут попросить Claude «заодно подчистить пару странных мест». Не надо. В discovery-сессии ваша задача — видеть, а не чинить. Поэтому она начинается в режиме только чтения — plan mode или его эквивалент, если в вашей версии Claude Code режим называется иначе. Команды меняются, навык остаётся: сначала исследование без правок.
Перед началом полезно сделать несколько очень скучных, но спасительных вещей:
git status # убеждаемся, что случайных правок нет
./gradlew tasks # смотрим, какие команды проект вообще умеет выполнять
git log --oneline -5 # быстро проверяем, чем проект жил в последних коммитах
Да, это не самый кинематографичный набор команд. Зато он заземляет. Для CashFlow Dashboard это особенно полезно: часть боли здесь не в бизнес-логике, а в том, что половина документации не совпадает с реальным способом запуска.
Если вы используете Workflow Kit, хороший помощник здесь — отдельный read-only subagent, например discovery-explorer. Его смысл не в том, чтобы «магически всё узнать», а в том, чтобы вынести тяжёлое чтение файлов в отдельное окно контекста и вернуть проверяемую сводку:
---
name: discovery-explorer
description: Read-only агент для legacy-discovery. Ищет подсистемы, потоки, тесты и неясные зоны. Для каждого вывода даёт доказательства.
tools: Read, Grep, Glob, Bash(git log:*), Bash(./gradlew tasks:*)
---
Обратите внимание на две вещи. Здесь нет Edit и Write. И даже Bash ограничен read-only сценариями. Это и есть правильная архитектура доверия: discovery-agent не «поможет» правкой кода. Его дело — искать, а не лечить. А смешивание исследования с реализацией чаще всего и заставляет людей чинить симптом до того, как понята система.
5. Запрос к Claude, который даёт карту риска
Качество discovery сильно зависит от формулировки запроса. Плохой запрос обычно звучит так: «Объясни этот проект» — Claude в ответ выдаст что-то гладкое, а вы потом долго выясняете, где там факты, а где просто стилистика. Запрос должен сразу требовать структуру, evidence и честное обращение с неизвестным.
Хорошая базовая формулировка может выглядеть так:
Проанализируй этот репозиторий как legacy-систему.
Верни:
1. ключевые подсистемы;
2. критические runtime-потоки;
3. зоны повышенного change risk;
4. существующие тесты;
5. неясные допущения;
6. доказательства для каждого вывода.
Изменения в код не предлагай и файлы не редактируй.
Такой запрос делает сразу несколько полезных вещей: задаёт контекст именно как legacy discovery, фиксирует формат, вынуждает выделить unclear assumptions и явно запрещает правки.
Если после этого ответа вы видите красивые фразы без опор, заходите вторым, более жёстким кругом: «Какие файлы это подтверждают?», «Где именно виден этот runtime flow?», «Есть ли тест, который покрывает это поведение?», «Что в твоём ответе — гипотеза, а не факт?». Звучит чуть менее дружелюбно — зато очень дружелюбно к вашему будущему времени и нервам.
Здесь полезно помнить ещё одну тонкую, но важную вещь: discovery-ответ не обязан быть длинным — он обязан быть структурированным. Короткая сводка с пятью сильными выводами и тремя честно зафиксированными unknowns почти всегда ценнее трёх страниц архитектурной прозы — если по каждому выводу можно открыть файл.
6. Первый discovery-отчёт по CashFlow Dashboard
Когда первичные ответы уже собраны, не нужно сразу прыгать в большую документацию. Полезнее небольшой discovery-note: сырой рабочий черновик с подтверждёнными находками, unknowns и первыми намёками на риск. Из него позже вырастут ARCHITECTURE_CURRENT.md, RISK_MAP.md и инвентарь поведения — и не придётся вытаскивать всё заново. Не идеально. Зато честно и проверяемо.
Наглядно это можно представить так:
flowchart TD
A[Legacy-репозиторий] --> B[Чтение кода, тестов, конфигов, логов]
B --> C[Подтвержденные факты]
B --> D[Неясные допущения]
C --> E[Discovery-note]
D --> E
E --> F[Черновик RISK_MAP.md]
Для CashFlow Dashboard разумный первый проход обычно начинается не со всех папок сразу, а с нескольких горячих зон:
- mrr-engine — там всплыло расхождение по MRR;
- payments и retry-логика — проблемы с платежом почти всегда бьют в active/churn состояние подписки;
- конфиги и feature flags — хрупкая конфигурация любит ломать систему тихо и по-будничному;
- папка legacy/, если она есть и выглядит как место, откуда проект давно хотел, но так и не смог съехать.
Небольшой стартовый шаблон discovery-note может быть таким:
# Заметка legacy-discovery
## Подсистема
mrr-engine
## Что подтверждено
...
## Какие тесты есть
...
## Что неясно
...
## Почему это риск
...
Здесь не нужно пытаться быть писателем — нужно быть человеком, которому завтра придётся объяснять команде, почему именно эта зона требует осторожности. Если для mrr-engine у вас уже есть входная точка, scheduled job, число тестов и честный список неясностей про pause/resume и timezone — вы уже не «смотрите в старый репозиторий». Вы проводите legacy discovery как инженер.
И вот в этот момент меняется оптика. Репозиторий перестаёт быть абстрактным набором папок — становится картой зон доверия и недоверия. Где-то опора: понятный flow, внятный test surface, согласованное поведение. Где-то туман: высокая бизнес-важность, мало проверок, странные правила, противоречия между кодом и документами. Из этого тумана и рождается настоящая работа с legacy — не «сделать красиво», а понять, что здесь вообще безопасно делать.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ