ADR 0165 — O repositório nasce no aceite do handoff ao Arquiteto, e a execução não começa sem ele
Status
Accepted. Decidido pelo mantenedor em 2026-09-18 (AT-092). Revisa o
GATILHO da RN-522, que tinha nascido para
cumprir a promessa da RN-541 ("o bootstrap é
adiado até o handoff do Arquiteto"). Nenhuma das duas veio de um ADR — as duas
nasceram de pedido direto do dono do produto e moram só em
docs/business-rules.md —, então este é o primeiro registro estrutural do
momento em que o repositório nasce. O MECANISMO de provisionamento não muda: é
o mesmo ProvisionRepositoryUseCase, idempotente por desenho desde o
ADR 0005, chamado pelo mesmo
AcceptHandoffUseCase. A regra de alvo de handoff do
ADR 0038 (handoff externo endereça só lead de
área ou agente sem área) e a cadeia Arquiteto → Dev Lead do
ADR 0053 seguem intactas.
Context
Uma instalação real da v6.1.0, em 2026-09-14, produziu esta sequência no event log de um projeto novo:
- 02:40:54 — o Arquiteto propõe
open_adr_prtrês vezes. O repositório ainda não existe, e a ferramenta falha nas três. - 02:43:53 —
handoff.offeredparainfrae paradev-lead(a confirmação de arquitetura pronta oferece os dois,OfferInfraHandoffUseCase). - Só o de
infraé aceito. O dedev-leadficaoffered. - 03:02:34 —
POST /projects/:id/execution/activateresponde 201. project_repositories,project_git_connectionserepo_bootstrapsficam vazias. O projeto fica sem repositório para sempre.
Os dois defeitos são independentes, e a RN-522 carregava os dois:
- O gatilho estava depois de quem precisa do repositório. O Arquiteto é o
primeiro agente com ferramenta que ESCREVE no repositório (
open_adr_pr), e o Infra Lead, ativado pelo handoff Arquiteto → Infra, é o segundo (open_infra_pr). Os dois trabalham ANTES do aceite ao Dev Lead. A RN-541 dizia "o repositório nasce quando o desenvolvimento começa", e o desenvolvimento, medido pelo que os agentes fazem, começa no Arquiteto. - O único gatilho era PULÁVEL. Ativar a execução não exige handoff aceito
ao Dev Lead — exige
module_mapvigente, e mais nada. Quem ativa pela Visão Geral (ou pelo atalho "Ativar execução" do próprio card do handoff, RN-137) pula o aceite, e com ele o provisionamento. Nada no caminho recusava.
Quem entrega ao Arquiteto, medido. O Arquiteto só pode ser ativado com um
handoff accepted endereçado a ele (canActivateAgent,
domain/sessions/agent-activation.ts) — a exceção é só o Criativo. O handoff
nasce por duas portas, e as duas gravam pelo MESMO
CreateHandoffUseCase: o PO, ao terminar o backlog, com
offer_handoff(to_agent: "arquiteto") (a instrução de kickoff em
po_server.ex manda isso), ou o usuário, pelo handoff manual
(RequestManualHandoffUseCase, ADR 0109). E o aceite é um só:
AcceptHandoffUseCase, o mesmo que já hospedava o gatilho da RN-522. Não há
caminho em que o Arquiteto trabalhe sem ter passado por esse aceite.
Decision
1. O gatilho passa a ser o aceite do handoff endereçado ao arquiteto. Em
AcceptHandoffUseCase, o ramo que chama provisionarRepositorio passa a
disparar para toAgent === 'arquiteto', ANTES de activateAgent — a mesma
ordem que a RN-522 já usava, pelo mesmo motivo: o Arquiteto acorda num projeto
que já tem onde trabalhar, e o primeiro open_adr_pr encontra repositório.
Tudo o mais do ramo fica byte a byte: sempre local (o único provider sem
credencial), falha vira repository.provision_failed com origem e nunca
derruba o aceite, repositório ADOTADO sai antes sem ser falha.
2. O gatilho antigo FICA, como segunda porta idempotente. O aceite ao
dev-lead continua chamando o mesmo provisionamento. Três razões, em ordem de
peso:
- É a saída dos projetos já quebrados. Um projeto que passou do Arquiteto
ANTES desta mudança (o
exp001da AT-092 é exatamente isso: handoff ao Arquiteto aceito sob a regra velha, handoff ao Dev Lead aindaoffered) tem um handoff pendente cujo aceite provisiona. Sem esta porta, a única saída seria a página de provisionamento manual, que nenhuma tela oferece a partir da sessão. - É a retomada natural de uma falha. Se o provisionamento falhar no aceite ao Arquiteto, o evento fica no log, e o próximo passo que o usuário dá de qualquer jeito — aceitar o Dev Lead — tenta de novo, sem ninguém precisar saber que existe uma rota de provisionamento.
- O preço é zero por construção. Com o repositório
createdjá de pé,ProvisionRepositoryUseCasenão chamacreateRepo, não cria sessão nem bootstrap, e o runner reporta todos os passos como satisfeitos (ADR 0005). Isso já estava provado para três rodadas seguidas do caso de uso; o que este ADR acrescenta é a prova PELAS DUAS PORTAS: aceitar o Arquiteto e depois o Dev Lead, contra o Postgres e oLocalGitProviderde verdade, termina com UMcreateRepo, UMA linha emproject_repositories, UMA emrepo_bootstraps, e nenhumrepository.provision_failed.
Tirar a segunda porta foi considerado e recusado: ela não tem custo, e a
alternativa deixa o exp001 sem saída pela tela onde o usuário está.
3. execution/activate sem repositório é RECUSADO com 409. Em
ActivateExecutionUseCase, logo depois da checagem de module_map e ANTES de
qualquer efeito (persistir orçamento, semear permissions.json, criar sessão),
o caso de uso consulta ProvisionedRepositoryRepository.findByProjectId. Sem
linha, ConflictException com o motivo NOMEADO, escolhido pelo estado dos
handoffs do projeto (HandoffRepository.findByProject, leitura nova e só
leitura) por uma função pura de domínio:
- há handoff
offeredao Arquiteto → "aceite o handoff ao Arquiteto"; - senão, há handoff
offeredao Dev Lead → "aceite o handoff ao Dev Lead" (a segunda porta); - senão, algum dos dois já foi aceito → o provisionamento automático rodou e
não deixou repositório (o
repository.provision_faileddiz por quê), e o caminho é a página de provisionamento do projeto; - senão → nenhum handoff ao Arquiteto foi aceito, e o repositório nasce nele.
Repositório ADOTADO conta como repositório. 409 e não 400 porque o pedido está
certo: é o ESTADO do projeto que ainda não permite. Reativar uma execução que
já roda continua não sendo conflito QUANDO há repositório; o exp001, que
ativou sem ter um, passa a receber o 409 também na reativação — e é o que se
quer, porque os dev agents dele nunca tiveram onde trabalhar.
4. A tela não oferece ativar sem repositório, e diz por quê uma vez, em
texto. A seção de Execução da Visão Geral lê GET .../git/repository (a
mesma queryKey ['repository', projectId] que ProjectPage, CodeShell e
Configurações já usam — nenhuma requisição nova de verdade) e, com a resposta
null CONFIRMADA, deixa o botão inerte no lugar e escreve o motivo, com o link
para a página de provisionamento. Carregando ou com erro, o botão fica como
estava: "não sei" não vira "não tem", e o backend recusa de qualquer forma. No
card do handoff ao Dev Lead, dentro da sessão, o atalho "Ativar execução" some
enquanto o repositório não existe, e o card diz que aceitar o handoff o
provisiona — o botão de aceitar está ao lado. É a régua da RN-102 e do
ADR 0064: tira o controle, nunca a informação.
Consequences
- A RN-522 muda de gatilho, não de mecanismo. A RN-582 registra a regra nova; a RN-522 e a RN-541 ganham nota apontando para ela, e o comentário do assistente de criação deixa de dizer "Dev Lead".
- O caso Arquiteto → Infra antes do Dev Lead deixa de existir. O Infra Lead é ativado pelo handoff do Arquiteto, que por construção só existe depois do aceite ao Arquiteto — então o repositório já nasceu quando ele acorda.
- A recusa local de
open_adr_pr/open_infra_pr(AT-088) continua necessária, e complementar: ela cobre o provisionamento que FALHOU e o projeto legado, que este ADR não consegue impedir de existir. - Consequência medida no código e aceita: a sessão
git-bootstrappassa a nascer no MEIO da fase do Arquiteto.ProvisionRepositoryUseCaseabre uma sessão própria para o log do bootstrap, e a Visão Geral e o resumo do workspace escolhem a sessão "mais recente" porcreatedAt. Sob a RN-522 essa sessão nascia no aceite ao Dev Lead e logo era ultrapassada pela de execução; agora ela vira a "mais recente" do projeto durante toda a conversa com o Arquiteto, até a próxima sessão nascer. A sessão de chat não é afetada (a tela dela lê o próprio id). Corrigir exige decidir se o log do bootstrap merece sessão própria, ou se "a mais recente" deve ignorar sessões de sistema — as duas mexem em regra de outra frente (RN-139, ADR 0005), e não são decididas aqui. - Projeto sem handoff ao Arquiteto nenhum, com
module_mapgravado por fora do fluxo, cai no quarto motivo da recusa e sai pela página de provisionamento. Não há caminho automático para ele, e não precisa haver. - Recusado: provisionar na criação do projeto (desfaria a RN-541, que é
pedido do dono do produto); provisionar DENTRO de
execution/activate(a ativação passaria a ter efeito de git escondido, e os agentes anteriores a ela continuariam sem repositório — o defeito 1 inteiro); e mover o gatilho sem manter a porta antiga (deixaria oexp001sem saída pela sessão).