Перейти к содержанию
Публикация AiManual

Миграция PHP-приложения на Java с Kiro: сканер моделей, восьмифазный workflow и parity harness

Kiro ведёт перенос зрелого PHP-приложения на Java и Spring Boot по восьмифазному workflow: сканер discover-models.php собирает манифест моделей, parity harness

Коротко

Что будет в материале

  1. 01

    Зачем переносить зрелое PHP-приложение на Java и Spring Boot

  2. 02

    Что такое Kiro и из чего состоит движок миграции

  3. 03

    Сканер discover-models.php: механическое обнаружение без запуска кода

  4. 04

    Parity harness: PHP как спецификация, Java проверяется запросами

Kiro — это AI-IDE, которая соединяет AI-агента с кодовой базой и ведёт многошаговые инженерные задачи с человеком в цикле. Применительно к миграции это меняет жанр работы: перенос перестаёт быть серией разрозненных сессий в чате и становится повторяемым процессом с проверяемым результатом. Оригинальное PHP-приложение получает роль спецификации, а Java-порт не объявляется корректным, пока его поведение не подтвердит parity harness. Инженерную схему такого движка разобрали в блоге AWS о повторяемой миграции PHP на Java с Kiro.

Движок состоит из трёх частей: общей методологии, механического сканера обнаружения и восьмифазного workflow. Всё это упаковано в skill-файлы — версионируемые Markdown-пакеты возможностей, поэтому методология не привязана к одной IDE и запускается двумя путями: интерактивно в Kiro по одному приложению с approval-гейтами и агентно в AWS Transform на масштабе портфеля.

Сама по себе смена языка редко бывает целью. Переход на Java даёт более сильную типовую безопасность, широкую поддержку библиотек и предсказуемое масштабирование. Цена тоже конкретна: зрелая кодовая база на Laravel, Symfony или Doctrine хранит бизнес-правила в неочевидных местах, поэтому структурно похожий порт может компилироваться без ошибок и вести себя иначе. Миграция оправдана, когда у команды есть компетенции в Java и Spring Boot с JPA и готовность строить parity-проверку, а не когда нужен «переводчик синтаксиса».

Зачем переносить зрелое PHP-приложение на Java и Spring Boot

Практический аргумент за Java/Spring Boot звучит так: типовая безопасность ловит часть ошибок на компиляции, экосистема библиотек шире, а масштабирование предсказуемее. Для сервисов, которые растут по нагрузке и по числу команд, это ощутимая разница в стоимости поддержки.

Обратная сторона проявляется на этапе, который обычно недооценивают. Приложение на Laravel или Symfony, прожившее несколько лет, накапливает поведение: скоупы моделей, аксессоры, наблюдатели событий, кастомные правила валидации, побочные эффекты в сервисах. Всё это не описано в README и не видно по структуре классов.

Kiro не обещает автоматического перевода. Он задаёт рамку, в которой перенос можно измерять: сначала инвентарь, потом правила перевода, потом арбитр в виде parity harness, и только затем генерация Java-кода. Именно порядок и делает процесс повторяемым на втором и третьем приложении.

Почему структурно похожий порт не гарантирует одинакового поведения

Бизнес-логика в зрелой PHP-кодовой базе живёт в Eloquent traits, в XML mapping-файлах Doctrine, в переопределённых методах репозиториев, в middleware и в конфигурации пакетов. Сканер видит классы и связи, но не видит смысла: почему поле помечено скрытым, почему связь имеет дополнительное условие, почему удаление модели на самом деле архивирует связанные записи.

Отсюда типичный сценарий провала ручного или полуавтоматического порта: приложение на Spring Boot собирается, тесты на отдельные методы проходят, а на проде расходятся суммы в отчётах или пропадает часть выборки из-за другого поведения ленивой загрузки. Компиляция и code review такие расхождения не ловят, потому что сравнивают код, а не наблюдаемое поведение. Ловит их только сравнение пар запрос/ответ на реальных сценариях, то есть parity harness.

Что такое Kiro и из чего состоит движок миграции

Kiro работает как агент с доступом к репозиторию: он читает файлы, планирует шаги и выполняет их, останавливаясь в точках, где нужно человеческое решение. Для миграции важна предсказуемость этих остановок, иначе сессия превращается в управление потоком случайных правок.

Движок фиксирует три опоры. Общая методология описывает, что и в каком порядке делать. Механический сканер собирает инвентарь исходного приложения. Восьмифазный workflow разбивает работу на этапы с явными гейтами. Знание живёт в файлах, а не в настройках конкретной IDE, поэтому его можно версионировать, ревьюить в пул-реквестах и переносить между инструментами.

Skill-файлы: php-to-java-migration и php-model-discovery

Skill-файл здесь — версионируемый Markdown-пакет возможностей. Роли разделены: php-to-java-migration кодирует методологию переноса, php-model-discovery описывает workflow сканера обнаружения моделей. Читая такой файл, агент получает не общие советы, а последовательность операций и критерии готовности каждого шага.

Практическая ценность в том, что правила пересматриваются в одном месте. Если на втором приложении выяснилось, что связи типа belongsTo через промежуточную таблицу распознаются неверно, правка идёт в skill-файл, и следующая миграция её учитывает. Похожий принцип, где структура директорий и markdown-инструкции заменяют оркестрацию фреймворком, разобран в материале про Interpretable Context Methodology.

Отдельно про генерацию кода: движок выдаёт идиоматичный Java, переписывать приложение вручную не требуется. Знание Spring Boot и JPA нужно для ревью результата, а не для самого процесса переноса.

Сканер discover-models.php: механическое обнаружение без запуска кода

Сканер discover-models.php проходит по исходникам механически, без запуска приложения и без подключения к базе. На выходе получается JSON-манифест: модели, поля, связи и флаги. Для запуска нужен PHP 8.0 или новее на машине, где работает сканер.

Отсутствие запуска принципиально. Не нужно поднимать окружение, восстанавливать дамп базы и разбираться, почему проект падает на старом расширении. Инвентарь собирается по статическим артефактам, а значит его можно получить на любом этапе, в том числе для приложения, которое уже сложно собрать.

{
  "models": [
    {
      "name": "...",
      "table": "...",
      "fields": [
        {"name": "...", "type": "...", "nullable": true}
      ],
      "relations": [
        {"type": "hasMany", "target": "..."}
      ],
      "flags": ["..."]
    }
  ]
}

Это схема структуры, а не реальный вывод конкретного проекта. Назначение манифеста: дать полный список того, что предстоит перенести, и стать предметом обсуждения до первых строк Java-кода.

Почему манифест нужно ревьюить руками

Сканер механический, он не понимает бизнес-смысл. Ручное ревью манифеста — это отдельный approval-гейт в workflow, и он существует не для формальности. Человек проверяет, все ли модели попали в список, верно ли определены типы связей, не потеряны ли флаги вроде мягкого удаления, временных меток и областей видимости.

Второй слой проверки — неочевидные связи и правила, спрятанные в traits и XML mapping-файлах. Механический проход их видит как код, но не как поведение. Ревью манифеста как раз то место, где такие правила попадают в план миграции, а не обнаруживаются на этапе parity-проверки через неделю после начала трансляции.

Parity harness: PHP как спецификация, Java проверяется запросами

Ключевая идея движка: сначала строится parity harness, потом пишется Java. Harness прогоняет пары запрос/ответ против оригинального PHP-приложения и против Java-порта, а результат сравнивается. Расхождение означает, что порт неверен, независимо от того, насколько аккуратно выглядит код.

Такой порядок инвертирует привычную последовательность. Обычно сначала пишут реализацию, затем покрывают её тестами, которые описывают уже написанный код. Здесь тесты фиксируют поведение оригинала, то есть внешний контракт, и становятся независимым арбитром для любого сгенерированного варианта. Подробнее о том, как работает сам движок, в публикации AWS.

Почему harness строится до Java-кода

Если сначала написать Java, а потом искать расхождения, ошибка обнаруживается поздно: часть кода уже выстроена вокруг неверно понятого правила, и правка тянет за собой цепочку изменений. Harness, построенный заранее, ловит расхождение в момент первой генерации, пока цена исправления минимальна.

Здесь же работает принцип «fix the loop, not the code». Когда harness показывает отличие, исправляют не отдельный фрагмент сгенерированного Java, а цикл: skill-файл, правило перевода, шаг workflow. Иначе та же ошибка воспроизведётся на следующем приложении, и повторяемость подхода исчезнет. Конкретные метрики покрытия harness в источниках не приводятся, поэтому оценивать его полноту стоит по собственным критичным сценариям.

Восьмифазный workflow и approval-гейты

Kiro проходит восемь фаз с явными точками контроля: ревью манифеста обнаружения, утверждение rulebook и подпись каждой фазы перед началом следующей. Гейты превращают миграцию в аудитную процедуру, где у каждого этапа есть ответственный и зафиксированный результат.

Детальное содержание всех восьми фаз в исходном описании не раскрыто, поэтому ниже обобщение по смыслу, а не цитата названий:

  • обнаружение: сбор манифеста моделей, полей, связей и флагов плюс ручная проверка;
  • правила: утверждение rulebook, то есть договорённостей о соответствии PHP-конструкций и Java/Spring Boot;
  • трансляция: генерация Java-кода по утверждённым правилам;
  • проверка: parity harness как арбитр корректности и возврат в предыдущие фазы при расхождениях.

Такая разбивка отвечает на главный вопрос заказчика миграции: где именно можно остановить процесс, если результат не устраивает. На каждом гейте есть артефакт, который можно отклонить, не откатывая всю работу.

Rulebook: что утверждает человек перед трансляцией

Rulebook — свод правил перевода, который утверждается до начала трансляции. На этом гейте фиксируются решения о том, как PHP-конструкции ложатся на Java и Spring Boot: как трактуются связи моделей, как переносятся области видимости и мягкое удаление, какие исключения считаются ожидаемыми.

Утверждение rulebook удобно тем, что спорные места обсуждаются один раз, до генерации. Дальше расхождение с правилами — это дефект процесса, а не повод для бесконечных правок в каждом отдельном классе. Содержимое rulebook в публичном описании не детализировано, его состав зависит от конкретной кодовой базы.

Два пути запуска: интерактивно в Kiro и агентно в AWS Transform

Поскольку знания живут в файлах, а не в конкретном инструменте, одну методологию запускают двумя способами. Интерактивный путь: открыть корень репозитория как workspace Kiro с доступом к Skills и Steering, попросить мигрировать PHP-приложение, дождаться автоматической активации skills и пройти восемь фаз с approval-гейтами.

Агентный путь — AWS Transform, агентный AI-сервис AWS для крупномасштабной миграции и модернизации, нативно интегрированный с Kiro. Ему передаются те же skill-файлы, что управляют интерактивной сессией, поэтому обнаружение до трансляции, parity harness как арбитр и «fix the loop, not the code» действуют и в автономном прогоне. Детали интеграции и ограничения сервиса стоит смотреть в описании движка.

Что меняется при переходе на масштаб портфеля

В интерактивном режиме человек подписывает каждую фазу по одному приложению. В агентном прогоне на портфеле такой плотности контроля нет: часть гейтов снимается, и это меняет профиль риска. Ошибка в rulebook или в skill-файле тиражируется на все приложения сразу, а не остаётся локальным инцидентом.

Требования к качеству skill-файлов и rulebook растут пропорционально масштабу. Parity harness остаётся арбитром, но его роль становится критичнее: именно он ограничивает ущерб от неверно понятого правила. Конкретных SLA и цифр производительности для автономного режима в источниках нет, поэтому планировать сроки портфеля по чужим обещаниям не стоит.

Что нужно для запуска: окружение и workspace

  • знакомство с PHP и одним из стеков: Laravel/Eloquent или Symfony/Doctrine;
  • workspace Kiro с доступом к Skills и Steering;
  • PHP 8.0 или новее на машине, где запускается сканер обнаружения;
  • Java 21 с Maven для сгенерированных проектов Spring Boot;
  • базовое понимание планирования миграции: обнаружение, трансляция, валидация.

Порядок действий для первого прогона выглядит так:

  1. открыть корень PHP-репозитория как workspace Kiro;
  2. запросить миграцию приложения, чтобы skills активировались автоматически;
  3. получить манифест от discover-models.php и проверить его руками;
  4. утвердить rulebook до начала трансляции;
  5. построить parity harness и только затем принимать сгенерированный Java-код.

Команды установки и конкретные версии зависимостей в исходном описании не приводятся, их нужно брать из документации Kiro и своего проекта.

Принцип «fix the loop, not the code» и типовые ошибки

При расхождении правится цикл: skill-файлы, rulebook, шаги workflow. Соблазн поправить один сгенерированный класс руками понятен, но он обнуляет повторяемость: следующее приложение получит ту же ошибку, а знание останется в голове разработчика, не в репозитории.

Категории ошибок, которые стоит ждать:

  • неверно распознанная связь в манифесте: тип или цель связи определены механически и неверно;
  • пропущенное бизнес-правило из Eloquent traits или XML mapping Doctrine;
  • расхождение поведения, пойманное parity harness: ответы отличаются по составу, порядку или типам полей;
  • неверная трактовка флагов модели, например мягкого удаления или временных меток.

Каждая такая ошибка — повод не для патча, а для изменения правила. Про то, как выстраивать такое ревью и что происходит с метриками разработки при работе с агентами, есть отдельный разбор пет-проекта на Java с Claude Code.

Честные ограничения: разбор laravel-eloquent-sample

Самый отрезвляющий фрагмент — публичный пример laravel-eloquent-sample. По описанию примера, в нём перенесены только 4 модели из 37, а parity harness не построен; авторы сами называют это главным пробелом. Детали примера в блоге AWS не раскрыты, поэтому цифры стоит сверять с репозиторием примера, а не принимать на веру.

Что это значит по критериям самого движка: без harness корректность порта не подтверждена. Перенос одной десятой части моделей не показывает, как подход ведёт себя на связях, составных ключах и неочевидных правилах зрелой кодовой базы. Процесс описан, критерий корректности сформулирован, но публичная демонстрация его не закрывает.

Что это говорит о готовности подхода к продакшену

Подход нельзя назвать провальным: методология, сканер и гейты дают структуру, которой у большинства «миграций с ИИ» нет. И нельзя считать доказанным на практике: пример неполный, а harness в нём отсутствует. Это типичная стадия, когда инструмент готов к пилоту, но не к переносу критичной системы по кнопке.

Разумный шаг — пилот на ограниченном домене с обязательным построением harness до трансляции. Домен выбирается так, чтобы расхождения было видно без интуиции: расчёты, отчёты, права доступа.

Кому подходит подход и как начать

Подход имеет смысл, если совпадают несколько условий:

  • в команде есть люди с опытом Java, Spring Boot и JPA, способные ревьюить сгенерированный код;
  • PHP-приложение зрелое, с бизнес-правилами в traits, mapping-файлах и сервисах;
  • команда готова строить parity harness до написания Java, а не после;
  • есть workspace Kiro с доступом к Skills и Steering, PHP 8.0+ и Java 21 с Maven.

Стартовать стоит с пилота: сканер discover-models.php, ручное ревью манифеста, утверждение rulebook, затем harness и только потом трансляция. Такой порядок даёт ранний ответ на вопрос, воспроизводится ли поведение, и не требует переносить всё приложение ради проверки гипотезы.

Подход не подходит, если ресурсов на harness нет или ожидается «кнопка мигрировать». В этих случаях получится Java-код, который компилируется и отличается поведением в непредсказуемых местах. Границы применимости ИИ-инструментов в разработке и то, как отличить ускорение от иллюзии, разобраны в статье про ИИ в разработке.

Подписаться на канал