ADR 0131 — Arquiteto направляет модули в инфраструктуру: он ВЫДВИГАЕТ кандидатов, Infra ВЫБИРАЕТ
Контекст
У Arquiteto уже шесть инструментов (create_module_map,
assign_story_modules, choose_project_image, create_c4_diagram,
propose_adr, emit_insight) и решение об образе — choose_project_image
(ADR 0065), — которое принимается на проект: один образ для контейнера
всего проекта. План выполнения в реальном контейнере (ADR 0128/0130) требует
большей гранулярности: проект с модулями разного стека (сервис
Node, worker на Python) не помещается в один образ, когда каждый модуль должен
подниматься отдельно.
Вопрос дизайна — не "какой образ", а "кто что решает". Arquiteto
уже видит архитектуру (именно он написал module_map), но не
видит парк уже используемых образов, стоимость поддержки ещё одного варианта и
операционные соглашения, которым следует Infra, — это компетенции
Infra, а не Архитектуры. Дать Arquiteto полномочие ФИКСИРОВАТЬ образ каждого
модуля (как choose_project_image фиксирует образ проекта) переложило бы операционное
решение на того, у кого есть лишь сторона дизайна.
Решение
Arquiteto выдвигает кандидатов; Infra выбирает. Эта поставка — лишь половина
Arquiteto: новый инструмент, route_modules_to_infra, который производит
СПИСОК — по элементу {modulo, imagemCandidata, porque} на каждый модуль
действующего module_map — и записывает его как artifact.module_routing, рядом с
artifact.module_map/artifact.project_image/artifact.c4_diagram (та же
конструкция без таблицы из ADR 0065, расширенная здесь: событие ЕСТЬ артефакт).
Половина, которая ВЫБИРАЕТ (Infra Lead читает этот список и решает, с
собственным proposed_action), — отдельный PR: маршрутизация существует и
проверяема до того, как у Infra появится инструмент для её потребления, — тот же тип
последовательности, что уже действовал, когда module_map пришёл раньше, чем
он понадобился create_c4_diagram.
:direct, вне глобального @registry — не proposed_action. Маршрутизация
не имеет внешнего эффекта: не поднимает контейнер, ничего не меняет вне event log.
Это ВНУТРЕННЕЕ архитектурное решение того же калибра, что
choose_project_image и create_c4_diagram, которые тоже :direct. Превращение этого
в proposed_action поставило бы черновое решение (которое Infra ещё будет
пересматривать) в ту же очередь, что одобряет git push.
Кандидатный образ проходит ТУ ЖЕ валидацию, что choose_project_image,
по каждому элементу. validarDecisaoDeImagem (domain/containers/project-container.ts)
уже умеет отклонять образ без tag/digest, latest и короткий rationale —
переписывание этого правила для модуля создало бы две его версии, которые
разойдутся. Новый домен (domain/architecture/module-routing.ts) лишь
добавляет то, что СВОЙСТВЕННО списку: он не может быть пустым (это не решение),
не может повторять модуль (неоднозначно — какой из двух образов действует?), и каждый
упомянутый modulo должен существовать в действующем module_map проекта (та же
проверка, что у assign_story_modules/missingModules, и по той же причине: отказ
перечисляет ВАЛИДНЫЕ имена, чтобы не вынуждать модель гадать).
Без module_map маршрутизировать нечего — отклоняется, а не выдумывается.
Инструмент имеет смысл лишь после create_module_map; build_kickoff/1
ArquitetoServer (единственное место, откуда модель узнаёт ПОРЯДОК
инструментов) начинает перечислять route_modules_to_infra как шаг 4, сразу
после module_map. Вызов без действующего module_map отклоняется тем же текстом,
что у create_c4_diagram, — "defina o module_map antes", — вместо маршрутизации
по пустой или выдуманной карте.
Последствия
Пока ничто не поднимает контейнер. Эта поставка не меняет ворота RN-105, не
трогает RegistrarTransicaoDeContainerUseCase, не вводит
нового proposed_action. Что существует после неё: проверяемый список
кандидатур, читаемый человеком в event log, — у Infra ещё нет инструмента,
чтобы действовать на его основе (следующий PR).
Кандидатный образ может расходиться с образом проекта
(choose_project_image). Намеренно: модуль может обосновать
образ, отличный от того, что Arquiteto зафиксировал для проекта в целом, — это
именно та гранулярность, которую эта поставка существует, чтобы открыть. Согласование
двух (или вывод choose_project_image из эксплуатации в пользу маршрутизации по модулям)
— отдельное продуктовое решение, здесь не принятое.
EstadoDoRoteamento/GetModuleRoutingUseCase следуют тому же образцу, что
GetC4DiagramUseCase — чтение без таблицы, действующий по наибольшему version с
разрешением ничьей по seq. Существование как отдельного use case (а не inline в
записывающем) — то, что даёт корректное версионирование без дублирования логики
"какой действующий", — та же причина, по которой DecidirImagemDoProjetoUseCase использует
ObterContainerDoProjetoUseCase.