Skip to content

Anthropic built Scion for itself. Carbon Forge is yours →

Carbon Forge
Menu

Guide

Répondre à un conflit de lane dans Carbon Forge

Deux agents modifient la même page. L'un intègre le premier. Carbon Forge ne devine pas ce que voulait le second : il nomme le conflit, montre les deux côtés et attend une réponse liée au trunk que la personne qui répond a réellement lu.

Aussi en: English, Español, Português, 日本語, Deutsch, 한국어, 简体中文, Italiano, हिन्दी · Tous les guides en français

Transparence : nous développons Carbon Forge chez 100monkeys.ai ; lisez donc ceci comme le récit de son fabricant. Ce guide a été rédigé par l'un de nos agents d'IA à partir de la documentation publique (en anglais), principalement les étapes 6 à 8 de Working in lanes et la page Lanes du catalogue, et relu par l'entreprise ; cette édition française est une traduction du guide original en anglais. Chaque appel est l'exemple même de la documentation ; les citations restent en anglais, avec la traduction à côté. Là où la documentation laisse une question ouverte, la dernière section le dit.

Étape 1. Savoir ce qui compte comme conflit

Une lane est un ensemble de patchs posés sur le trunk, et chaque lecture sur elle compose le trunk tel qu'il est maintenant avec ces patchs. Un patch est en conflit "when it no longer applies to the trunk: its old text no longer matches or matches twice" (quand il ne s'applique plus au trunk : son ancien texte ne correspond plus, ou correspond deux fois), ou quand le trunk a changé une entrée d'arbre ou de bibliothèque que le patch remplaçait. Un patch qui s'applique encore n'est pas un conflit, même si le trunk a changé la même section ; la lecture le signale comme section déplacée, "worth a reviewer's look, not a conflict." (qui mérite un coup d'œil à la relecture, pas un conflit.) Deux agents qui changent des parties différentes d'un fichier intègrent tous les deux. Et la règle que suit tout le reste de ce guide : "Nothing merges by itself." (Rien ne fusionne tout seul.)

Étape 2. Remarquer qu'une lane est en conflit

lanes.get renvoie landable, vrai seulement pour une lane ouverte avec au moins un patch vivant et aucun conflit. Dans l'application, la page de la lane à /<workspace>/lanes/<label> a un onglet Conflicts. Sans interroger en boucle, un événement de webhook lane.conflict nomme la lane et les chemins de ses lignes en conflit quand une intégration sur le trunk la met en conflit pour la première fois.

Étape 3. Lire le conflit

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

Chaque ligne porte ce qu'il faut pour fusionner : le patch ; la section telle qu'elle était quand le patch a été pris ; la section du trunk maintenant ; la vue composée de la lane ; et les changesets qui l'ont déplacée, chacun avec son intent, son acteur et la lane qui l'a intégré. Pour un arbre de code, la ligne ajoute un diff unifié de chaque fichier en conflit et, pour un langage doté d'une grammaire, une liste indicative des définitions de premier niveau qui diffèrent, qui "decides nothing" (ne décide rien). L'outil est en lecture seule et ne demande que le rôle viewer. Dans l'application, l'onglet Conflicts montre le texte du trunk et celui de la lane avec l'appel exact pour répondre à chacun, "ready to copy, while the page itself decides nothing." (prêt à copier, tandis que la page elle-même ne décide rien.)

Étape 4. Répondre à un conflit de texte

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

La réponse est un nouveau patch, avec une note de 1 à 1 024 caractères qui dit pourquoi. Il est "matched against the trunk as it stands now and bound to the hash of that state." (comparé au trunk tel qu'il est maintenant et lié au hachage de cet état.) L'ancien patch est gardé comme historique, marqué superseded. Un conflit d'arbre se règle de la même façon avec upserts, removals ou patches, et une entrée de bibliothèque avec un sha256. Répondez dans l'ordre : un patch ultérieur sur la même entité attend que le précédent soit résolu.

Étape 5. Ou abandonner le patch

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

Quand le trunk a déjà fait ce que le patch voulait faire, ou que le patch n'est plus voulu, abandonnez-le plutôt. Là où l'entité sur laquelle le patch a été pris a disparu, le refus de la documentation dit d'abandonner le patch plutôt que de le résoudre.

Étape 6. Répondre à un conflit de déplacement

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

Une lane qui renomme une page entre en conflit quand le trunk a déplacé la même page depuis, quand le trunk tient maintenant le nouveau chemin, ou quand la page a disparu. Répondez avec to_path, et title là où le titre doit changer. La résolution est liée au chemin que le trunk tient maintenant ; un déplacement ultérieur sur le trunk la rend donc périmée elle aussi.

Étape 7. Répondre aux conflits d'un travail assemblé

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

Un agent principal rassemble les lanes de plusieurs agents en une seule avant d'intégrer. Un patch transporté ainsi entre en conflit là où la lane qui le reçoit a changé ce qu'il change, et lanes.conflicts nomme, sous moved_by, les patchs antérieurs de la lane réceptrice sur lesquels il repose désormais. Sa résolution répond à la vue de la lane réceptrice, pas au trunk seul.

Étape 8. Intégrer, avec un essai à blanc d'abord

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" }

L'intégration est vérifiée de nouveau dans sa propre transaction et refusée en bloc, chaque conflit nommé, si quelque chose a bougé. Une résolution répond à un état exact du trunk ; si le trunk déplace cette section avant l'intégration, la résolution devient périmée et l'intégration est refusée avec :

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

Relisez alors lanes.conflicts et répondez à l'état frais. Sur un trunk protégé avec des règles d'intégration, rappelez-vous que toute résolution après les approbations les fait "count for nothing" (ne plus compter pour rien) : l'approbation vient après la dernière réponse. Envoyez l'intégration avec une idempotency_key, et une nouvelle tentative après un délai dépassé renvoie le résultat de la première intégration au lieu d'intégrer deux fois.

Pour une lane qui porte ensemble une modification de code et sa documentation, lisez notre guide Intégrer une modification de code et sa documentation dans un seul changeset.

Ce que la documentation laisse sans réponse

Pas de fusion silencieuse. Chaque réponse a sa note.