Skip to content

Commit e422947

Browse files
committed
docs: AGENTS.md como instrucciones comunes a cualquier agente
Sigue la convención que usa el propio angular/angular, que tiene su AGENTS.md en la raíz con frontmatter `trigger: always_on` —lo que esperan Windsurf y Antigravity— y mantiene el archivo corto enlazando a la documentación en vez de duplicarla. CLAUDE.md y GEMINI.md son punteros de tres líneas para las herramientas que buscan un nombre propio. No duplican nada: cualquier cambio va en AGENTS.md, y un test comprueba que sigan siendo punteros y no copias. El contenido es lo que un agente necesita saber y no puede deducir del código: que adev-es es una capa de traducción sobre un overlay, que el respaldo .en.* es lo único que protege una traducción de la próxima sincronización, y las cuatro reglas que rompen cosas si se ignoran —entre ellas los prefijos de alerta, que son claves del tokenizer y no prosa. Con tests, porque un agente no duda del documento: si AGENTS.md nombra un comando que ya no existe o un ancla que se movió, actúa sobre información falsa sin que nada avise. Se verifica que los `npm run` existan, que los enlaces y anclas resuelvan, y que los prefijos de alerta sigan estando en el enum de adev — si upstream añade o quita uno, salta aquí.
1 parent c92acf8 commit e422947

4 files changed

Lines changed: 155 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
trigger: always_on
3+
---
4+
5+
Este repositorio es la traducción al español de la documentación de Angular
6+
(angular.dev → angular.lat). Esta guía es para agentes de IA que trabajen aquí.
7+
8+
**Escribe siempre en español**: commits, PRs, issues, comentarios de código y
9+
respuestas. El proyecto entero está en español.
10+
11+
## Cómo está montado
12+
13+
No es una copia del sitio, es una **capa de traducción**:
14+
15+
- `origin/` — submódulo con el `angular/angular` en inglés, fijado a un SHA.
16+
- `adev-es/` — solo lo traducido. El build copia `origin` entero y superpone
17+
`adev-es` encima, así que lo que no esté traducido sale en inglés y no rompe.
18+
- `xxx.md` es la traducción; `xxx.en.md` es el inglés del que se partió.
19+
20+
Ese respaldo `.en.*` **no es opcional**: es lo único que le dice a
21+
`update-origin` que el archivo ya está traducido. Sin él, la siguiente
22+
sincronización le escribe el inglés encima sin aviso. Vale para cualquier
23+
extensión, no solo `.md` — la navegación y el pie de página son `.ts` y `.html`.
24+
25+
## Comandos
26+
27+
```shell
28+
npm run check-translations # qué falta traducir y qué se desactualizó
29+
npm run lint-glossary # terminología contra glosario.yml
30+
npm run plan-translation # qué bloques tocar en una traducción desactualizada
31+
npm run verify-translation # comprueba que solo se tocó lo previsto
32+
npm test # tests de las herramientas
33+
npm run build # compila el sitio
34+
```
35+
36+
## Documentación
37+
38+
- [CONTRIBUTING.md](CONTRIBUTING.md) — flujo completo. Anclas útiles:
39+
[`#respaldo`](CONTRIBUTING.md#respaldo),
40+
[`#actualizar`](CONTRIBUTING.md#actualizar),
41+
[`#antes-del-pr`](CONTRIBUTING.md#antes-del-pr).
42+
- [UPDATE-ORIGIN.md](UPDATE-ORIGIN.md) — sincronizar con una versión nueva.
43+
- [glosario.yml](glosario.yml) — reglas de terminología, cada una con su motivo.
44+
45+
## Reglas que rompen cosas si se ignoran
46+
47+
- **`.md` y `.en.md` van en el mismo commit.** Separarlos deja el archivo
48+
marcado como desactualizado de forma permanente: la detección busca el commit
49+
que tocó ambos.
50+
- **No repitas `cp archivo.md archivo.en.md`** si el `.en.md` ya existe.
51+
Escribirías español sobre el respaldo y se perdería el registro del original.
52+
- **Los prefijos de alerta se quedan en inglés**: `NOTE:`, `TIP:`, `IMPORTANT:`,
53+
`HELPFUL:`, `CRITICAL:`, `SUMMARY:`, `QUESTION:`. Son claves del tokenizer de
54+
adev, no prosa; traducirlas hace que el aviso se renderice como párrafo plano.
55+
Traduce solo el texto que sigue.
56+
- **No traduzcas código, rutas, URLs ni nombres de API.** Sí los comentarios
57+
dentro del código y los atributos con prosa visible (`title=`, `header=`).
58+
- **Mantén el número de líneas** entre el original y la traducción cuando se
59+
pueda: es lo que hace legibles los diffs futuros.
60+
61+
## Al actualizar una traducción desactualizada
62+
63+
No se retraduce: se aplica solo el cambio que ocurrió en inglés. Lee el
64+
documento completo en ambos idiomas —la traducción existente es la mejor
65+
referencia de terminología y registro— pero edita únicamente los bloques que
66+
indique `plan-translation`.
67+
68+
## Issues y PRs
69+
70+
- Usa la CLI `gh`.
71+
- Los issues de traducción se agrupan **por sección**, no uno por archivo, y
72+
siguen la convención del repo: `Traducir - Guías de X`, `Actualizar - X`,
73+
con prefijo de versión cuando aplica: `[Angular 22.1] Traducir …`.
74+
- Etiqueta siempre con `docs-translation`.
75+
- Antes de crear issues, comprueba con `gh issue list` qué existe ya: el repo
76+
los mantiene a mano y duplicarlos es peor que no crearlos.

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Las instrucciones de este repositorio están en [AGENTS.md](AGENTS.md), que es la
2+
convención común a todas las herramientas de agente.
3+
4+
Este archivo existe solo para que las que buscan un nombre propio lo encuentren.
5+
No dupliques contenido aquí: cualquier cambio va en `AGENTS.md`.

GEMINI.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Las instrucciones de este repositorio están en [AGENTS.md](AGENTS.md), que es la
2+
convención común a todas las herramientas de agente.
3+
4+
Este archivo existe solo para que las que buscan un nombre propio lo encuentren.
5+
No dupliques contenido aquí: cualquier cambio va en `AGENTS.md`.

tools/agents-md.test.mjs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { test } from 'node:test';
2+
import assert from 'node:assert/strict';
3+
import { existsSync, readFileSync } from 'node:fs';
4+
import { resolve } from 'node:path';
5+
6+
/**
7+
* AGENTS.md le dice a un agente qué comandos existen y dónde está la
8+
* documentación. Si esas referencias se quedan atrás, el agente actúa sobre
9+
* información falsa sin que nada avise — y a diferencia de una persona, no va a
10+
* dudar del documento.
11+
*/
12+
13+
const ROOT = resolve(import.meta.dirname, '..');
14+
const doc = readFileSync(resolve(ROOT, 'AGENTS.md'), 'utf8');
15+
const pkg = JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf8'));
16+
17+
test('existe y declara el trigger que esperan las herramientas', () => {
18+
assert.match(doc, /^---\ntrigger: always_on\n---/, 'falta el frontmatter');
19+
});
20+
21+
test('todos los `npm run` que menciona existen', () => {
22+
const usados = [...doc.matchAll(/npm run ([a-z-]+)/g)].map((m) => m[1]);
23+
assert.ok(usados.length >= 5, 'apenas menciona comandos');
24+
for (const c of new Set(usados)) {
25+
assert.ok(pkg.scripts[c], `AGENTS.md menciona "npm run ${c}" y no existe`);
26+
}
27+
});
28+
29+
test('los archivos que enlaza existen', () => {
30+
const enlaces = [...doc.matchAll(/\]\(([^)#]+\.(?:md|yml))(?:#[\w-]+)?\)/g)].map((m) => m[1]);
31+
assert.ok(enlaces.length, 'no enlaza nada');
32+
for (const f of new Set(enlaces)) {
33+
assert.ok(existsSync(resolve(ROOT, f)), `enlaza ${f}, que no existe`);
34+
}
35+
});
36+
37+
test('las anclas de CONTRIBUTING que cita existen', () => {
38+
const contributing = readFileSync(resolve(ROOT, 'CONTRIBUTING.md'), 'utf8');
39+
const anclas = [...doc.matchAll(/CONTRIBUTING\.md#([\w-]+)/g)].map((m) => m[1]);
40+
assert.ok(anclas.length, 'no cita ninguna ancla');
41+
for (const a of new Set(anclas)) {
42+
assert.ok(contributing.includes(`{#${a}}`), `cita #${a} y CONTRIBUTING no la define`);
43+
}
44+
});
45+
46+
// Traducir un prefijo que no está en el enum rompe el renderizado del aviso.
47+
// Si upstream añade o quita uno, este test lo detecta antes que un lector.
48+
test('los prefijos de alerta que nombra existen en el tokenizer de adev', () => {
49+
const src = resolve(ROOT, 'origin/adev/shared-docs/pipeline/shared/marked/extensions/docs-alert.mts');
50+
if (!existsSync(src)) return; // submódulo sin inicializar
51+
52+
const claves = [...readFileSync(src, 'utf8').matchAll(/^\s+([A-Z]+)\s*=/gm)].map((m) => m[1]);
53+
const nombrados = [...doc.matchAll(/`([A-Z]+):`/g)].map((m) => m[1]);
54+
55+
assert.ok(nombrados.length >= 5, 'apenas nombra prefijos');
56+
for (const p of new Set(nombrados)) {
57+
assert.ok(claves.includes(p), `nombra "${p}:" y no está en AlertSeverityLevel`);
58+
}
59+
});
60+
61+
test('los punteros por herramienta apuntan a AGENTS.md y no duplican', () => {
62+
for (const f of ['CLAUDE.md', 'GEMINI.md']) {
63+
const p = resolve(ROOT, f);
64+
assert.ok(existsSync(p), `falta ${f}`);
65+
const c = readFileSync(p, 'utf8');
66+
assert.match(c, /AGENTS\.md/, `${f} no apunta a AGENTS.md`);
67+
assert.ok(c.length < 600, `${f} parece duplicar contenido en vez de apuntar`);
68+
}
69+
});

0 commit comments

Comments
 (0)