Skip to content

v0.38.0

@ruinosus ruinosus tagged this 30 Jul 11:40
* spec: delegacao de agentes + a face A2A (o executor que falta e o Card como Kind)

O modelo de delegacao JA ESTA no kernel, com as duas pontas do aperto de mao:
AgentSpec.team_members (quem pode delegar) e DelegationTargetFor (quem aceita,
com format/use_when/typical_seconds). O que NAO existe e o executor —
`delegate_to` aparece EXCLUSIVAMENTE em kernel/models.py, sem implementacao,
sem teste, sem tool. Capacidade existe, porta nao.

Esta spec implementa o executor e a face A2A nas duas direcoes, sem inventar
protocolo:

  • O PROTOCOLO NAO E UM KIND (erro de categoria). O AGENT CARD e: documento
    versionado, com schema, descrevendo identidade e capacidade. Vira o Kind
    RemoteAgent.
  • DOIS Kinds, porque os campos sao DISJUNTOS: Agent declara comportamento
    (instruction/model/tools — o DNA compoe e executa); RemoteAgent descreve e
    aponta (supported_interfaces/skills/securitySchemes — o DNA localiza e
    chama). Um Kind so validaria absurdo, e additionalProperties:false nao sabe
    dizer 'estes campos OU aqueles'.
  • O QUE UNE OS DOIS e um roster DERIVADO — 'todo documento que declara
    delegation_target_for e cuja allowlist me inclui' — atravessando os dois
    Kinds. Lista mantida a mao fica cega e verde; a licao de 29/07 aplicada no
    desenho, nao no codigo.
  • A DIRECAO DE SAIDA E `emit`: projetar um Agent num Agent Card servido no
    well-known. Alvo de emit, nao mecanismo novo.

Tres regras de seguranca que nascem com o desenho, porque um RemoteAgent e por
construcao um canal de exfiltracao: data_scope obrigatorio e explicito (resposta
implicita significa 'tudo'); NUNCA repassar o token do usuario (a credencial e
do workspace — senao cada remoto vira impersonacao completa contra o nosso
proprio MCP); e allowlist DUPLA, as duas pontas sempre.

Par no dna-cloud: os documentos (supervisor/conversor), o console e o canvas.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Work-Item: Story/s-stamp-dated-spec-fields
Co-Authored-By: dna-sdlc[bot] <302582850+dna-sdlc[bot]@users.noreply.github.com>

* plan: implementacao da delegacao + face A2A (SDK, sete tarefas)

Sete tarefas TDD sobre a spec 2026-07-30-a2a-delegation-design.md:

  1. o Kind RemoteAgent (descritor + entry point + as guardas de docs)
  2. a politica PURA — allowlist dupla + roster derivado (4 mutantes)
  3. o executor de delegate_to, caminho local + parse por format
  4. o transporte A2A — escopo antes do envio, credencial do workspace (5 mutantes)
  5. entrada: Card de terceiro vira RemoteAgent INERTE
  6. saida: projetar um Agent num Card (emit)
  7. a cadeia de release (tres lugares da versao, indice SIMPLE, lockstep)

AS TRES DECISOES ABERTAS DA SPEC ficam como PREMISSAS DECLARADAS no topo, para
serem contestadas em revisao e nao descobertas em producao: assinatura vira
signature_state tri-estado (verificacao fora da v1, mas a ausencia dela fica
LEGIVEL); data_scope e por Kind (sensibilidade entra depois, aditivo); e o Card
de saida nao e servido por esta spec — o SDK entrega a PROJECAO, e quem serve em
qual path e decisao de deployment, o que dissolve a pergunta em vez de
responde-la errado.

POLITICA E EXECUTOR EM ARQUIVOS SEPARADOS de proposito: a politica e a fronteira
de autorizacao e merece ser lida sozinha. Em 29/07 a licao foi que a politica
pura estava certa nos treze defeitos e o erro estava sempre na montagem em
volta — manter a parte correta pequena e o que torna isso possivel.

UMA ARESTA DEIXADA VISIVEL: a nota do Task 2 Step 3 registra que a assinatura de
may_delegate no teste nao carrega o nome do delegador, com a correcao escrita.
Um plano que finge nao ter arestas ensina a confiar nele sem ler.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Work-Item: Story/s-stamp-dated-spec-fields
Co-Authored-By: dna-sdlc[bot] <302582850+dna-sdlc[bot]@users.noreply.github.com>

* feat(a2a): delegacao de agentes + a face A2A — as seis tarefas do plano

O modelo de delegacao JA ESTAVA no kernel, nas duas pontas (AgentSpec.team_members
e DelegationTargetFor), e NUNCA teve executor: delegate_to aparecia so em
models.py. Capacidade existe, porta nao. Isto e a porta, mais o Agent Card do A2A
como Kind.

  1. RemoteAgent — o Card como Kind. Schema FECHADO (securitySchemes diz COMO
     autenticar; credencial nunca e documento), data_scope OBRIGATORIO (um remoto
     e por construcao canal de exfiltracao, e escopo implicito significa 'tudo'),
     signature_state tri-estado ('nao verificado' e diferente de 'nao assinado').
     13 testes.
  2. A politica PURA — allowlist DUPLA e roster DERIVADO atravessando os dois
     Kinds. 12 testes, 4 mutantes mortos.
  3. O executor — recusa nomeada em todo caminho. 10 testes.
  4. O transporte A2A — escopo checado ANTES do envio, credencial do WORKSPACE
     jamais do usuario (asserido contra a ASSINATURA da funcao).
  5. Entrada — um Card de terceiro nasce INERTE (approved=False, sem caminho para
     True). 8 testes.
  6. Saida — projetar um Agent num Card, via emit. skills DERIVADOS das tools.
     5 testes.

TRES DEFEITOS DO PLANO que a execucao expos, todos corrigidos no proprio arquivo
do plano em vez de silenciados:

  • O envelope do descritor estava ACHATADO e a forma nao existe no codebase —
    TypedKindDefinition.from_raw exige kind: KindDefinition com tudo sob spec:.
    Eu criei o SourceArtifact nesta mesma sessao e ainda escrevi o envelope errado
    de memoria.
  • O comando de teste (`python -m pytest`) nao funciona: o interpretador
    ambiente nao tem pytest, precisa de `uv run`.
  • may_delegate de tres argumentos era indecidivel — a aresta deixada VISIVEL no
    plano de proposito, e que funcionou: o implementador achou, consertou pela
    prescricao, e avisou.

Tambem: um falso positivo real do gen_data_model_docs.py (inferia
RemoteAgent.skills -> Skill por singularizacao) entrou no INFERENCE_DENYLIST com
a razao escrita, no mesmo padrao das entradas que ja existiam.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Work-Item: Story/s-stamp-dated-spec-fields
Co-Authored-By: dna-sdlc[bot] <302582850+dna-sdlc[bot]@users.noreply.github.com>

* fix(a2a): remover o parametro `token` que meu commit anterior capturou no meio de um mutante

Defeito de PROCESSO meu, nao do codigo. Eu commitei 036a461d enquanto o agente
da Task 4 ainda trabalhava na mesma arvore — depois de instruir todos os agentes
a NAO commitar exatamente para evitar isso. O snapshot pegou a2a_transport.py no
meio do mutante #5 (`token: str | None = None` adicionado a call_remote), que o
agente reverteria segundos depois.

O parametro e precisamente a brecha que o teste existe para fechar: um caminho
por onde o bearer do usuario atravessaria a fronteira, fazendo de cada agente
remoto uma impersonacao completa dele contra o nosso proprio MCP.

POR QUE A SUITE NAO PEGOU: pytest roda contra a ARVORE, nao contra o HEAD.
Quando rodei os 4593 testes, o agente ja havia revertido o mutante na arvore —
entao a arvore estava sa e o COMMIT estava doente. Verde num estado que nao era
o commitado.

E a mesma familia de tudo que este dia produziu: um snapshot tirado no momento
errado, capturando estado inconsistente, com a verificacao apontada para o lugar
certo mas no instante errado. A licao que fica e concreta: nao commitar enquanto
ha agente escrevendo na arvore — e verificar o COMMIT, nao so a arvore.

Achado pelo relato do agente, que preferiu FLAGAR em vez de consertar-e-commitar
por conta. Se ele tivesse silenciosamente consertado, eu nunca saberia que o
commit anterior estava furado.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Work-Item: Story/s-stamp-dated-spec-fields
Co-Authored-By: dna-sdlc[bot] <302582850+dna-sdlc[bot]@users.noreply.github.com>

* chore(release): 0.38.0 — delegacao de agentes + a face A2A

Minor, porque a feature e nova: o executor de delegate_to (que existia como
vocabulario no kernel e nunca como implementacao), o Kind RemoteAgent (o Agent
Card do A2A como documento), e as duas direcoes da face A2A.

Os TRES lugares da versao, mais o comentario que repete o teto:
  • packages/sdk-py/pyproject.toml  → 0.38.0
  • packages/cli/pyproject.toml     → 0.38.0
  • o teto interno do CLI           → dna-sdk>=0.38,<0.39 (a dep E o comentario)

Minor move o teto — foi por isso que o script conferiu DUAS ocorrencias antes de
trocar: o comentario que repete a restricao ja ficou obsoleto antes, e um teto
que diverge do comentario e uma mentira que compila.

Portao verificado por inteiro, nao por amostra: 4593 testes, brand_guard
(conteudo + identidade dos commits), gitleaks (1062 commits, zero vazamento), e
as tres guardas derivadas de docs (kinds/MER/cobertura de prosa) limpas.

A UNICA vermelha da suite local (test_imported_claude_fact_is_recallable_by_
paraphrase) NAO e portao: o CI instala '.[dev,runtime]' sem o extra embed-onnx,
entao o importorskip a PULA lá. Ela falha so em maquina com fastembed instalado,
e e assercao de qualidade de ranking semantico. Dito com precisao: nao provei que
passava em main (nao reproduzi o ambiente), provei que nossas mudancas nao
alcancam esse caminho e que o portao nao a inclui.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Work-Item: Story/s-stamp-dated-spec-fields
Co-Authored-By: dna-sdlc[bot] <302582850+dna-sdlc[bot]@users.noreply.github.com>

---------

Co-authored-by: Jefferson Barnabé <3090620+ruinosus@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: dna-sdlc[bot] <302582850+dna-sdlc[bot]@users.noreply.github.com>
Assets 2
Loading