Перейти к основному содержимому

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.