Skip to content

Anthropic built Scion for itself. Carbon Forge is yours →

Carbon Forge
Menu

Guia

Responda a um conflito de lane no Carbon Forge

Dois agentes editam a mesma página. Um integra primeiro. O Carbon Forge não adivinha o que o segundo queria: ele nomeia o conflito, mostra os dois lados e espera uma resposta ligada ao trunk que quem responde realmente leu.

Também em: English, Español, 日本語, Deutsch, Français, 한국어, 简体中文, Italiano, हिन्दी · Todos os guias em português

Aviso: desenvolvemos o Carbon Forge na 100monkeys.ai, então leia isto como o relato de quem o fabrica. Este guia foi redigido por um dos nossos agentes de IA a partir da documentação pública, principalmente os passos 6 a 8 de Working in lanes e a página Lanes do catálogo, e revisado pela empresa; esta versão em português é uma tradução do guia original em inglês. Cada chamada é o próprio exemplo da documentação, e as citações ficam em inglês com a tradução ao lado. Onde a documentação deixa uma pergunta em aberto, a última seção diz isso.

Passo 1. Entenda o que conta como conflito

Uma lane é um conjunto de patches sobre o trunk, e cada leitura nela compõe o trunk como está agora com esses patches. Um patch está em conflito "when it no longer applies to the trunk: its old text no longer matches or matches twice" (quando não se aplica mais ao trunk: seu texto antigo não corresponde mais ou corresponde duas vezes), ou o trunk alterou uma entrada de árvore ou de biblioteca que o patch substituía. Um patch que ainda se aplica não é conflito mesmo que o trunk tenha mudado a mesma seção; a leitura o informa como seção movida, "worth a reviewer's look, not a conflict." (vale uma olhada de quem revisa, não é um conflito). Dois agentes que mudam partes diferentes de um mesmo arquivo integram os dois. E a regra que o resto deste guia segue: "Nothing merges by itself." (Nada se funde sozinho).

Passo 2. Perceba que uma lane está em conflito

lanes.get responde landable, que só é verdadeiro para uma lane aberta com pelo menos um patch vivo e nenhum conflito. No aplicativo, a página da lane em /<workspace>/lanes/<label> tem uma aba Conflicts. Sem consultar repetidamente, um evento de webhook lane.conflict nomeia a lane e os caminhos das linhas em conflito quando uma integração no trunk a coloca em conflito pela primeira vez.

Passo 3. Leia o conflito

lanes.conflicts { "label": "agent/7/fix-login" }

Cada linha traz o que quem funde precisa: o patch; a seção como estava quando o patch foi tirado; a seção do trunk agora; a visão composta da lane; e os changesets que a moveram, cada um com sua intenção, seu autor e a lane que o integrou. Para uma árvore de código a linha acrescenta um diff unificado de cada arquivo em conflito e, para uma linguagem com gramática, uma lista indicativa das definições de nível superior que diferem, que "decides nothing" (não decide nada). A ferramenta é só de leitura e só exige o papel de leitor. No aplicativo, a aba Conflicts mostra o texto do trunk e o da lane com a chamada exata para responder a cada um, "ready to copy, while the page itself decides nothing." (pronta para copiar, enquanto a própria página não decide nada).

Passo 4. Responda a um conflito de texto

lanes.resolve { "patch_id": "…", "note": "kept both sign-in options", "old_string": "…", "new_string": "…" }

A resposta é um patch novo com uma nota de 1 a 1.024 caracteres dizendo por quê. Ela é "matched against the trunk as it stands now and bound to the hash of that state." (comparada com o trunk como está agora e ligada ao hash desse estado). O patch antigo é mantido como histórico, marcado superseded. Um conflito de árvore é respondido da mesma forma com upserts, removals ou patches, e uma entrada de biblioteca com um sha256. Responda em ordem: um patch posterior na mesma entidade espera até o anterior ser resolvido.

Passo 5. Ou descarte o patch

lanes.drop_patch { "patch_id": "…" }

Quando o trunk já fez o que o patch pretendia, ou o patch não é mais desejado, descarte-o. Onde a entidade sobre a qual o patch foi tirado não existe mais, a recusa da documentação diz para descartar o patch em vez de resolvê-lo.

Passo 6. Responda a um conflito de movimento

lanes.resolve { "patch_id": "…", "note": "kept the trunk's rename and moved on from it", "to_path": "guides/sign-in" }

Uma lane que renomeia uma página entra em conflito quando o trunk moveu a mesma página desde então, quando o trunk já ocupa o novo caminho ou quando a página não existe mais. Responda com to_path, e title onde o título deva mudar. A resolução fica ligada ao caminho que o trunk tem agora, então um movimento posterior no trunk também a torna obsoleta.

Passo 7. Responda a conflitos em trabalho reunido

lanes.merge { "from": "agent/8/tests", "into": "agent/7/fix-login", "intent": "assemble the login fix" }

Um agente líder reúne as lanes de vários agentes numa só antes de integrar. Um patch trazido assim entra em conflito onde a lane receptora mudou o mesmo que ele, e lanes.conflicts nomeia, como moved_by, os patches anteriores da lane receptora sobre os quais ele agora se apoia. A resolução responde à visão da lane receptora, não só ao trunk.

Passo 8. Integre, com um teste a seco primeiro

lanes.land { "label": "agent/7/fix-login", "intent": "fix: accept magic links", "dry_run": true }
lanes.land { "label": "agent/7/fix-login", "intent": "fix: accept magic links" }

A integração é verificada de novo dentro da própria transação e recusada inteira, com cada conflito nomeado, se algo se moveu. Uma resolução responde a um estado exato do trunk; se o trunk mover essa seção antes da integração, a resolução fica obsoleta e a integração é recusada com:

resolution <id> was resolved against <hash>; the trunk's section is now <hash>

Então leia lanes.conflicts de novo e responda ao estado novo. Num trunk protegido com regras de integração, lembre que qualquer resolução depois das aprovações faz com que elas "count for nothing" (não valham nada), então a aprovação vem depois da última resposta. Envie a integração com uma idempotency_key e uma nova tentativa após um tempo esgotado responde o resultado da primeira integração em vez de integrar duas vezes.

Para uma lane que leva uma mudança de código e sua documentação juntas, leia o nosso guia Integre uma mudança de código e a sua documentação num único changeset.

O que a documentação deixa sem resposta

Nada de fusões silenciosas. Cada resposta tem uma nota.