ADR 0087 — O UX Designer entra como agente conversacional
- Status: Aceito
- Data: 2026-08-17
- Contexto: decisão explícita do dono do produto, antecipando o
gatilho de separação que
docs/fluxo.ymljá declarava para o papel
Contexto
docs/fluxo.yml (ADR 0085) já registrava ux-designer como papel do
modelo-alvo do time, com status: proposto, hoje_absorvido_por: criativo (discovery) + design/ (design system como dado) e um critério de separação
objetivo:
Quando o projeto GERENCIADO tiver interface própria a desenhar — hoje o design system é insumo estático. Separa quando protótipo virar artefato recorrente.
Esse gatilho não disparou. O Brabo ainda não constrói projetos com UI
própria de verdade em produção; o design system (design/tokens.css,
design/COMPONENTS.md) continua sendo insumo estático que o Arquiteto e os
dev agents consultam, nunca um projeto vivo que precise de decisão de UX
recorrente.
O dono do produto decidiu, mesmo assim, construir o agente agora — decisão
CONSCIENTE de antecipar, registrada aqui para não ser confundida com um erro
de leitura do critério. O histórico do que o papel absorvia continua em
docs/fluxo.yml, como comentário: o texto anterior não é apagado, só deixa
de ser o estado vigente.
Decisão
O UX Designer entra como o quinto agente conversacional — Criativo, PO,
Arquiteto, Dev Lead e agora UX Designer —, SOLO (sem área, sem subagentes),
espelhando o desenho do Engine.Agents.DevLeadServer.
As peças
Engine.Agents.UxDesignerServer(apps/engine/lib/engine/agents/ux_designer_server.ex) — GenServer por sessão, rehydration do event log, streaming, laço bounded de tool use com teto 14 (mesmo calibre de Arquiteto/Dev Lead: agente de RACIOCÍNIO, não conversação leve como Criativo/PO, que têm teto 12). Ativado por handoffacceptedendereçado a "ux-designer" — o mecanismo é GENÉRICO (ActivateAgentUseCase/canActivateAgentna api já aceitam qualquer agente com handoff aceito; nenhuma linha mudou lá) — e o kickoff só roda num start FRESCO (restart não regera o protótipo).- O kickoff lê
artifact.product_brief, a MESMA "necessidade de negócio" que o Criativo produz — sem artefato novo, mesmo padrão de leitura queArquitetoServer.build_kickoff/1já faz. - O sistema de design é DESCRITO na identidade
(
Engine.Harness.Agents, entrada"ux-designer"), texto estático com os tokens dedesign/tokens.css(cores semânticas, tipografia, espaçamento, raio) e as convenções dedesign/COMPONENTS.md(variantes de botão, estilo de ícone). Os agentes conversacionais NÃO têm ferramenta de leitura de arquivo do repositório — não havia tool a reusar —, e a identidade é a única camada do prompt presente em TODO turno, não só no kickoff. propose_prototype(Engine.Agents.UxDesignerTools,apps/engine/lib/engine/agents/ux_designer_tools.ex) — a ÚNICA ferramenta:personas,jornadas,prototipo(telas+anotacoes) eresumo. Gravaartifact.prototipo_navegavele oferece handoff para "po" e para "dev-lead" sobre o MESMO artefato.Engine.Agents.UxDesignerSupervisor— cópia exata do padrão deDevLeadSupervisor; registrado emEngine.Applicationao lado dele.EngineWeb.AgentCommandControllerganhou as três cláusulas (start,message,via_for) que os outros quatro conversacionais já têm.apps/web/src/lib/agents.ts:'ux-designer'noAgentKey, entrada comcolor: 'var(--accent)'. Nenhum dos cinco tokens semânticos dedesign/tokens.cssestava livre de outro agente —--accenté o menos reusado (só o Arquiteto), e a regra do design system proíbe hex novo.icon: PencilIcon, o único ícone do catálogo semanticamente ligado a design/edição ainda sem dono.
artifact.prototipo_navegavel: sem tabela, e sem caso de uso dedicado na api
Esta é a decisão que precisou de investigação antes de codar, porque os dois
precedentes de "artefato sem tabela" (artifact.project_image, ADR 0065;
artifact.c4_diagram, RN-149) usam um caminho DIFERENTE do que
artifact.business_rule/artifact.product_brief usam, e os dois caminhos
parecem intercambiáveis até se olhar POR QUÊ.
choose_project_image/create_c4_diagram têm caso de uso PRÓPRIO na api
(DecidirImagemDoProjetoUseCase, CreateC4DiagramUseCase) porque cada um
tem um motivo estrutural para isso:
- o Container level do C4 é DERIVADO do
module_mapvigente — conteúdo que o modelo não pode redigitar sem arriscar divergir da fonte real; - a decisão de imagem tem recusa de domínio (tag explícita, teto de recursos) que mais de um consumidor precisa respeitar da mesma forma.
propose_prototype não tem nenhum dos dois. Personas, jornadas, telas e
anotações são conteúdo AUTOCONTIDO — só o próprio UX Designer escreve, só
ele lê de volta, nada é derivado de outro artefato e não há uma segunda
regra de domínio compartilhada esperando reuso. Por isso ele segue o
caminho do business_rule/product_brief: validação de FORMA no ENGINE
(Engine.Harness.ArtifactSchemas, tipo "prototipo_navegavel") e gravação
pelo caminho GENÉRICO que a api já expõe para qualquer session_event
(EngineApiClient.append_event_returning/3, sem rota nova). Abrir um
CreatePrototipoUseCase replicaria a forma de CreateC4DiagramUseCase sem
nenhum dos dois motivos que a justificam ali — complexidade sem argumento.
Um artefato, dois handoffs — nunca dois artefatos
docs/fluxo.yml lista duas saídas do papel: prototipo (para o PO) e
spec-visual (para o Dev Lead). A tentação óbvia era um segundo tool call
ou um segundo artefato para "spec-visual". A decisão foi NÃO duplicar: o
protótipo (telas + anotações de comportamento) É a spec visual — o PO lê
resumo/prototipo para desenhar o backlog, o Dev Lead lê as MESMAS
telas/anotacoes como referência de implementação. Duas cópias do mesmo
conteúdo divergiriam na primeira revisão feita de um lado só — o mesmo
argumento que já vale para o C4 não redigitar o module_map.
O turno para no primeiro sucesso — a lição do Dev Lead, sem a suspensão dele
UxDesignerServer reusa a metade do desenho do DevLeadServer que
sobrevive sem o ADR 0086: um propose_prototype BEM-SUCEDIDO encerra o
turno, para o modelo não propor de novo e produzir dois protótipos com o
mesmo total (o defeito real que motivou aquela guarda no Dev Lead). A OUTRA
metade do ADR 0086 — suspender esperando proposed_action — não se aplica
aqui: propose_prototype não tem efeito externo nenhum (é conteúdo, não
ação; não há paralelo do "gasto que o teto da RN-083 cobra"), então nasce
como evento simples, do jeito que execution.plan_proposed nascia antes do
0086.
Consequências
A favor
- O papel entra ativo com o MESMO rigor dos outros quatro conversacionais — teto de iterações, rehydration, falha narrada com origem (RN-059/163) —, em vez de crescer como funcionalidade ad-hoc dentro do Criativo.
- Zero rota nova na api: o mecanismo de ativação por handoff, o
append_event_returninggenérico e ocreate_handoffgenérico já bastavam. A única superfície nova na api é o campouxDesignerActiveno roster (RN-287), simétrico ao queinfraActivejá fazia. docs/fluxo.ymldeixa de descrever um papel que o código não tinha —status: active, entradas/saídas reais, sem o sufixo_alvo.
Contra
- Gatilho antecipado, por decisão explícita. O critério de separação original (interface própria em projeto gerenciado) não se sustenta sozinho como justificativa — é aceito porque o dono do produto pediu, ciente disso.
teste-de-usabilidadefica fora de alcance. Exige usuário humano real testando a interface; nenhum agente substitui isso. Não simulado.metricas-de-usosegue lacuna declarada. Depende do papelanalytics(métrica de PRODUTO), quedocs/fluxo.ymlmantémproposto— sem ele, a entrada correspondente do UX Designer não tem fonte real.- O card do dashboard e o painel do time calculam
uxDesignerActiveseparadamente (RN-090) — mesma duplicação queinfraActivejá tinha, aceita pelo mesmo motivo: a api responde FATOS, a apresentação é do web.
Alternativas consideradas
Esperar o gatilho de separação disparar. Era a leitura literal de
docs/fluxo.yml antes desta mudança. Recusada por decisão explícita do
dono do produto — ver Contexto.
artifact.prototipo_navegavel com caso de uso dedicado na api, no
padrão de CreateC4DiagramUseCase. Recusada: nenhum dos dois motivos que
justificam aquele padrão (conteúdo derivado, recusa de domínio
compartilhada) se aplica aqui. Copiar a forma sem o motivo é complexidade
que a próxima pessoa lendo o código teria de justificar sozinha.
Um segundo tool call/artefato para "spec-visual". Recusada: o protótipo já é a spec visual. Duas cópias do mesmo conteúdo (uma para o PO, outra para o Dev Lead) arriscariam divergir na primeira revisão feita de um lado só.
UX Designer como subagente de uma área nova. Recusada: nada no papel pede delegação interna nem múltiplos executores em paralelo — é raciocínio de UMA pessoa por sessão, como Criativo/PO/Arquiteto/Dev Lead já são.
Referências
docs/fluxo.yml— blocoid: ux-designer, o gatilho de separação original- ADR 0085 —
docs/fluxo.ymlcomo registro declarativo dos papéis - ADR 0053 — cria o Dev Lead, o molde que este ADR replica
- ADR 0086 — por que
propose_prototypeNÃO suspende (não tem efeito externo) - ADR 0065,
RN-149 — o padrão de artefato sem tabela
que
artifact.prototipo_navegavelsegue, e por que ele NÃO precisa do caso de uso dedicado que os outros dois têm apps/engine/lib/engine/agents/ux_designer_server.ex,ux_designer_tools.ex,ux_designer_supervisor.exapps/engine/lib/engine/harness/agents.ex,artifact_schemas.exapps/web/src/lib/agents.ts,agent-status.ts