Skip to content

Anthropic built Scion for itself. Carbon Forge is yours →

Carbon Forge
Menu

Guía

Integra un cambio de código y su documentación en un solo changeset

Un cambio de código y la página que lo documenta se integran en el mismo changeset, juntos o no se integran. Esta guía lleva un cambio así desde una lane abierta hasta una sola integración.

También en: English, Português, 日本語 · Todas las guías en español

Aviso: construimos Carbon Forge en 100monkeys.ai, así que lee esto como el relato de quien lo fabrica. Esta guía la redactó uno de nuestros agentes de IA a partir de la documentación pública, sobre todo Working in lanes y Code and files on the substrate, y la revisó la empresa; esta versión en español es una traducción de la guía original en inglés. Cada llamada es el ejemplo de la propia documentación, y las citas van en inglés con la traducción al lado. Donde la documentación deja una pregunta abierta, la última sección lo dice.

Por qué un solo changeset

La portada de la documentación define la unidad: "A changeset is many writes landed as one: every page, atom, code tree and library entry it names is written in one transaction under one intent, the changeset's intent, or nothing is written" (un changeset son muchas escrituras integradas como una: cada página, átomo, árbol de código y entrada de biblioteca que nombra se escribe en una transacción bajo una intención, la del changeset, o no se escribe nada; Welcome to Carbon). El código y la prosa son entidades de un mismo registro, así que quien lee nunca encuentra el código nuevo junto a la página vieja, y una reversión deshace ambos a la vez.

Necesitas un token que pueda escribir lanes y árboles; el preset SCM agent es el que la documentación nombra para ese trabajo.

Paso 1. Averigua si el trunk está protegido

workspaces.get_settings {}
→ { "workspaceId": "…", "trunkProtected": true, "trunkProtectedEntities": false }

"With trunkProtected, code trees, library entries and changesets go through a lane; with trunkProtectedEntities as well, page and atom edits do too." (Con trunkProtected, los árboles de código, las entradas de biblioteca y los changesets pasan por una lane; si además está trunkProtectedEntities, también las ediciones de páginas y átomos.) En cualquier caso, una lane es la forma correcta aquí: la documentación recurre a una cuando "a change should be seen whole before it lands" (un cambio debe verse completo antes de integrarse).

Paso 2. Abre una lane para el cambio

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

Una etiqueta son segmentos en minúsculas separados por barras, única entre las lanes abiertas. "A lane costs nothing to open and holds no copy, so one per task, or one per agent, is the expected use." (Abrir una lane no cuesta nada y no guarda ninguna copia, así que lo esperado es una por tarea o una por agente.) Pasa owner para que solo tú puedas escribir, resolver e integrar en la lane.

Paso 3. Cambia el código en la lane

trees.apply_patch { "path": "app", "operations": [ { "op": "patch", "entry_path": "src/login.ts", "old_string": "password", "new_string": "magicLink" } ], "intent": "fix: accept magic links", "lane": "agent/7/fix-login" }

Pasa la etiqueta como lane y "the write is held on the lane as a patch against the trunk" (la escritura queda en la lane como un parche contra el trunk): "the trunk is not written" (el trunk no se escribe). trees.apply_patch envía solo sus operaciones (una sustitución dentro de un archivo, una escritura, un borrado o un movimiento); trees.put envía la lista completa de entradas del árbol. En ambos casos "the lane keeps only what differs" (la lane guarda solo lo que difiere).

Paso 4. Cambia la página que lo documenta, en la misma lane

pages.apply_patch { "pathOrId": "guides/login", "old_string": "Sign in with a password.", "new_string": "Sign in with a magic link.", "lane": "agent/7/fix-login" }

Misma etiqueta, así que la edición de la página espera junto al código. Si el cambio también renombra una página, pages.move acepta lane igualmente, y "a rename belongs to the change that needs it" (un cambio de nombre pertenece al cambio que lo necesita). Una captura de pantalla entra igual, con library.put_at_path y la etiqueta.

Paso 5. Lee lo que produciría la lane

Pasa la misma lane a una lectura y "the answer is the trunk as it stands now with the lane's patches applied, composed on the call" (la respuesta es el trunk tal como está ahora con los parches de la lane aplicados, compuesto en la llamada): pages.read para la página, trees.get, trees.diff o trees.grep para el código. Después revisa el conjunto:

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

lanes.diff responde "entity by entity, the trunk's section and the lane's" (entidad por entidad, la sección del trunk y la de la lane); lanes.get responde los parches, los conflictos y landable: "open, at least one live patch, no conflict" (abierta, al menos un parche vivo, ningún conflicto). En la app, /<workspace>/lanes/<label> muestra lo mismo, con cada archivo de texto cambiado como un diff unificado. Quien revisa leyendo lanes.export y aprueba con su hash de composición "has approved exactly that change" (ha aprobado exactamente ese cambio).

Paso 6. Responde a cualquier conflicto

Si mientras tanto alguien editó en el trunk las mismas líneas de la página o del archivo, el parche está en conflicto, y "nothing merges by itself" (nada se fusiona por sí solo). lanes.conflicts da el parche, la sección como estaba, la sección actual del trunk y los changesets que la movieron. Responde con lanes.resolve o descarta el parche con lanes.drop_patch. Una sustitución dentro de un archivo "replays on the trunk's current file, so two agents changing different parts of one file both land" (se vuelve a aplicar sobre el archivo actual del trunk, así que dos agentes que cambian partes distintas de un archivo se integran los dos).

Paso 7. Integra una vez, con una intención

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

Ejecuta primero la prueba en seco y después la integración. "Every live patch is replayed as one changeset whose intent is lane agent/7/fix-login: fix: accept magic links" (cada parche vivo se vuelve a aplicar como un changeset cuya intención es lane agent/7/fix-login: fix: accept magic links), se comprueba de nuevo dentro de su propia transacción y se "refused whole, with every conflict named, if anything moved" (rechaza entero, con cada conflicto nombrado, si algo se movió). Empieza la intención con feat, fix, docs, chore o revert y las notas de versión la agruparán bajo esa palabra. Envía una idempotency_key y un reintento tras un timeout "answers the first landing's result instead of landing twice" (devuelve el resultado de la primera integración en lugar de integrar dos veces).

Paso 8. Lee la integración de vuelta

Abre /<workspace>/changes/<id>: muestra la intención completa, el actor, la lane de la que se integró, su sello y sus entradas, el archivo de código y la página juntos. El blame de la línea cambiada responde ahora con la intención que escribiste: trees.blame da "each line's revision, changeset, intent, actor and landing lane" (la revisión, el changeset, la intención, el actor y la lane de integración de cada línea; Code and files). Para deshacer ambos a la vez, changesets.revert escribe un changeset nuevo que restaura cada entidad que escribió la integración.

Lo que la documentación deja sin responder

Guías relacionadas

Integra el código y su documentación juntos.