Imported from EspacioKoop/expediente-legado (
AGENTS.md). Install upstream withnpx skills add EspacioKoop/expediente-legado. Copyright stays with the author.
AGENTS.md — instrucciones para agentes
Este repositorio adopta las Normas Platino: cooperación autónoma entre agentes, sin colisiones ni pérdida de trabajo. Autonomía no significa permiso ilimitado ni integración sin autorización.
El flujo humano sigue en CONTRIBUTING.md, el contexto en README.md y las fases en ROADMAP.md. Si dos instrucciones se contradicen, no improvises: detén solo el alcance afectado y coordina con @eGurucharri.
Fuentes de verdad, antes de tocar nada
| Qué | Dónde |
|---|---|
| Prioridad y punto de control | Plan maestro #181 |
| Reservas activas | Registro central #1713 |
| Fases y versiones | ROADMAP.md |
| Flujo de ramas y gates | CONTRIBUTING.md |
| Estado general | README.md |
| Paridad legado → Godot | docs/paridad-expedientes.md |
| Reparto entre agentes | docs/agents/doctrina.md |
Lee también el issue concreto, sus comentarios, PRs relacionadas, reviews y CI. En este proyecto una decisión que evita duplicar trabajo suele estar en un comentario posterior al cuerpo original.
#182 queda como registro histórico. Mientras dure el rollover, consúltalo para detectar reservas heredadas aún vivas; todo CLAIM, HEARTBEAT, PR_READY, CI_FIX y RELEASE nuevo se publica en #1713.
Ciclo obligatorio
-
Comprueba
main, PR abiertos, issue, comentarios, plan maestro y reservas. -
Elige un pendiente prioritario libre. No abras un segundo corte si ya hay una PR activa que cubre el mismo hueco. Un issue con
agent:auto,agent:pool,agent:qwen,agent:geminiojulesno está libre: está delegado al nivel 3 (ver «Niveles de trabajo»). -
Antes de modificar archivos publica en #1713:
CLAIM issue=#N agent=<nombre> branch=<rama> files=<rutas> goal=<objetivo> lease=48h -
Relee inmediatamente #1713. Gana la reserva activa anterior por fecha de GitHub; en empate, el comentario con ID menor. Si hay solape, no edites esos archivos. Una reserva protege archivos, no bloquea la cooperación: puedes revisar, proponer, entregar parches o commits al titular y trabajar rutas no reservadas del mismo issue con tu propio CLAIM. Editar lo reservado exige acuerdo del titular registrado en #1713 (guía de cooperación de las Normas Platino, EspacioKoop/normas_platino#16).
-
La lease dura 48 horas mientras no exista una PR abierta. Para renovar trabajo sin PR publica:
HEARTBEAT issue=#N branch=<rama>Una
PR_READYasociada a una PR abierta mantiene la reserva sin depender del reloj..github/workflows/reservas.ymlpublicaRELEASEautomáticamente al fusionar/cerrar la PR y barre leases vencidas cada 6 horas. -
Trabaja en rama propia desde
mainactualizado:feature/NN-slug,fix/NN-slugodocs/NN-slug. -
Mantén el corte pequeño. Un paraguas como #279/#282/#283 se ejecuta por verticales, no con una reescritura total.
-
Añade regresión ejecutable cuando cambie comportamiento. La inspección textual puede complementar, no sustituir, una prueba del contrato real cuando Godot pueda ejecutarlo.
-
Ejecuta las pruebas canónicas cuando el entorno local disponga de la toolchain necesaria y revisa el diff final. Si no puede ejecutarse el preflight local, documenta la limitación y deja que CI valide el SHA del PR antes de marcarlo
PR_READY. -
Abre PR a
mainy registra en #1713:
PR_READY issue=#N pr=#M sha=<sha> pruebas=<qué pasó> limites=<qué no cubre>
PR_READYmantiene la reserva y no autoriza merge. Integra solo con autorización explícita de @eGurucharri y los gates exigidos en verde.- Si abandonas antes de abrir PR, publica
RELEASE issue=#N motivo=abandonado. Tras cerrar o fusionar una PR no publiques unRELEASEduplicado: el workflow de reservas lo hace de forma idempotente.
Las reservas legacy anteriores al corte de migración del 15 de septiembre de 2026 se liberan automáticamente porque se confirmó que no había otros agentes trabajando durante la migración. A partir de ahí, todo CLAIM nuevo debe llevar lease=48h.
Usa Closes #N solo si el PR satisface el issue entero. Para entregas parciales, Refs #N y explica lo que queda.
Disciplina de backlog
Un issue no es un recordatorio: representa trabajo ejecutable o un bloqueo verificable. Antes de abrir uno nuevo, intenta primero cerrar, reconciliar o ampliar un issue existente sin mezclar responsabilidades.
Reglas obligatorias:
- No crear subissues “para luego”. Un agente solo abre un subissue si va a ejecutarlo en esa misma sesión o si existe un bloqueo externo concreto que necesita seguimiento independiente.
- Cerrar features técnicamente terminadas. Si implementación, persistencia y regresiones del alcance acordado ya están integradas, la feature se cierra aunque quede un pase humano transversal. La validación se concentra en sus gates canónicos (#9 recorrido completo, #113 mando/foco, #398 identidad visual, #399 materiales y #431 profundidad SIGA) o en un gate especializado explícito. Si el pase falla, se abre un bug reproducible.
estado:validacion-humanano convierte una feature en backlog técnico. Solo los issues cuyo propósito principal sea el propio pase humano deben permanecer abiertos por ese motivo.estado:parcialexige un siguiente corte ejecutable. El cuerpo o el último comentario debe decir exactamente qué falta, qué archivos/contrato afecta y por qué puede trabajarse ahora. Si no existe ese corte, reconciliar o cerrar.estado:bloqueadoexige condición de desbloqueo. Debe citar qué evento, PR, asset, credencial, decisión o dependencia lo desbloquea. “Más adelante” no es un bloqueo válido.- Las épicas extensibles tienen alcance v1. Catálogos, assets, deformaciones, expedientes y contenido no permanecen abiertos porque “siempre se puede añadir más”. Al cumplir los criterios v1 se cierran; cualquier ampliación futura nace de una necesidad observable.
- Después de cada merge, primero reducir backlog. Antes de abrir otro issue, revisar el padre y 1–2 issues relacionados para cerrarlos, actualizar su estado o eliminar pendientes que ya entraron indirectamente.
- WIP técnico limitado. Mantener como referencia un máximo de 15 issues realmente ejecutables entre P0/P1,
estado:parcialy colas de agentes. Si la cola ya está llena, priorizar/terminar/reconciliar antes de preparar más trabajo. duplicado-o-sustituidoimplica cierre. La etiqueta documenta por qué se cerró; no es un estado abierto.- No abrir expansión mientras exista un gate humano sin evidencia nueva. Un fallo observado sí justifica un issue nuevo; una posibilidad hipotética no.
La pregunta operativa antes de crear cualquier issue es: “¿alguien puede empezar este trabajo hoy con un resultado verificable?” Si la respuesta es no, documenta la idea en el padre/ROADMAP y no aumentes el backlog.
Niveles de trabajo
- Nivel 1: @eGurucharri decide prioridad, integra y valida en playtest.
- Nivel 2: agentes asistidos desde chat (Claude, ChatGPT, Codex, Odiseo…). Investigan, planifican, implementan cortes y delegan al pool.
- Nivel 3: el pool autónomo (
agent-pool.yml) y Jules (labeljules,agent-jules.yml). Ejecutan issues delegados de un solo fichero, con el contexto dentro del issue; no sustituyen al nivel 2.
El reparto detallado (dónde se ejecuta cada agente, qué capa de modelos usa, quién revisa los drafts del pool y qué pasa al agotarse una cuota) está en la doctrina de agentes. Si esa página contradice este archivo, manda este.
Para delegar, el nivel 2 crea o prepara el issue con el plan (AGENT_PLAN_BEGIN … AGENT_PLAN_END, ver docs/agents/parallel-pool.md) y le pone la label de cola en el mismo momento: un issue sin label parece libre y otro agente lo toma.
El nivel 2 no toma un issue con label de cola. Solo interviene en estos casos:
- el pool lo deja en
agent:needs-human; - rescata trabajo que el pool completó pero no pudo publicar (rama subida sin PR). En ese caso quita antes la label de cola, cita el run de origen y conserva el código producido;
- @eGurucharri lo pide.
Revisar y comentar un issue delegado sigue siendo cooperación normal.
Archivos compartidos
Reserva expresamente los archivos compartidos enumerados en #1713. Entre ellos están:
README.md,AGENTS.md,CONTRIBUTING.md,ROADMAP.md;godot/datos/textos.csv,godot/datos/casos.json;godot/pruebas/pruebas.gd, los módulos que invoca ygodot/pruebas/minimo.txt;scripts/verificar_godot.py.
Una reserva de un issue no concede automáticamente todos los archivos que ese issue podría necesitar. Declara las rutas reales del corte.
Prohibido
- push directo a
main; - force-push o reescritura de historia compartida;
- merge sin autorización de @eGurucharri;
- rebajar pruebas para poner verde un cambio;
- publicar tokens, contraseñas, datos personales, partidas personales o rutas privadas;
- inventar procedencia, licencias, hashes, hechos de expedientes o resultados de playtest;
- decir que algo está validado visualmente o con mando si solo pasó CI headless.
Si una herramienta escribe por error en main, revierte inmediatamente sin force-push, deja constancia en #1713 y continúa únicamente desde una rama propia.
GDScript: preflight local y CI
Si modificas cualquier archivo *.gd, ejecuta preferentemente antes de abrir el PR:
bash scripts/check_gdscript.sh
En local el script aplica gdformat primero, después ejecuta gdlint, la suite Python y un gdformat --check --diff final. En CI usa el mismo script, pero no modifica el checkout: exige que el GDScript ya llegue formateado. La versión canónica es gdtoolkit==4.3.4, y el propio script la instala en un venv si no la encuentra en el PATH.
Si el entorno local no dispone de Godot, gdtoolkit o las dependencias necesarias y no puede prepararlas, eso no bloquea la apertura del PR. En ese caso deja constancia de la limitación y usa el workflow del PR como preflight autoritativo. Lo que sí sigue bloqueado es declarar PR_READY o fusionar mientras los gates requeridos no estén verdes.
La suite necesita la GDExtension GB/GBC y las ROMs propias compiladas; sin ellas, las pruebas que arrancan Godot se saltan diciéndolo. bash scripts/preparar_entorno.sh deja ambas listas y es idempotente. Con SIGA98_EXIGIR_EXTENSION=1 esos saltos pasan a ser fallos: CI lo define siempre, y conviene usarlo en local antes de dar un verde por bueno.
Reglas para evitar falsos fallos:
- no escribas tests que dependan de espacios, saltos de línea o encadenamientos exactos que
gdformatpueda reescribir; - si un test Python inspecciona una llamada GDScript, usa una regex tolerante a whitespace o, mejor, una prueba del comportamiento/contrato;
- si el preflight local modifica un
.gd, revisa y conserva ese formato antes de ejecutar el resto de validaciones o crear el commit; - no declares
PR_READYsin un preflight válido: puede ser local o el workflow equivalente del PR; si solo CI puede ejecutarlo, espera a su resultado y corrige allí cualquier fallo.
Pruebas canónicas
Desde la raíz:
bash scripts/check_gdscript.sh
python3 scripts/verificar_godot.py
bash scripts/escanear_secretos.sh
escanear_secretos.sh pasa gitleaks por los commits de la rama (origin/main..HEAD) con la salida redactada; el workflow secretos.yml hace lo mismo con cada PR y cada push a main. Un falso positivo se silencia con su huella en .gitleaksignore, nunca desactivando el gate. Un secreto real que ya se empujó no se arregla con otro commit: hay que rotarlo y avisar a @eGurucharri.
Desde backend/:
mvn test
mvn checkstyle:check pmd:check spotbugs:check
npm test
Usa la línea de Godot declarada en .godot-version. La referencia final es el workflow sobre el SHA del PR, no una ejecución local anterior.
godot/pruebas/minimo.txt protege el mínimo de la suite principal. Reducirlo exige explicar qué comprobaciones desaparecen y por qué.
Trampas conocidas
Estas ya han provocado fallos reales.
- Nombres de fase:
Jornadausaarchivo,trayecto,casa,sueño. La calle del recorrido estrayecto; comprobarfase == "calle"deja el hook muerto aunque el código visual exista. - Cadena
dia_*: muchas capacidades se integran por herencia. No escribas tests que exijan que una clase herede directamente de una base si el contrato solo necesita herencia transitiva. PackedVector*Arrayyconst: Godot 4.7 no acepta todas las construcciones dinámicas dePackedVector2Array(...)dentro de expresionesconst. Usa estado estático de solo lectura por API cuando corresponda.- GDScript lint: una variable
static varno es una constante;gdlintexige nombre de variable, no MAYÚSCULAS de constante. - GDScript formato:
gdformatpuede partir expresiones comoObjeto.metodo(...)en varias líneas. No fijes tests al texto exacto cuando el contrato no dependa del layout. .uid: el repo versiona el.uidde cada guion. Si creas un.gd, incluye su.uidcuando Godot lo genere/requiera.godot/datos/textos.csv: el bloqueARCHIVO_*no debe perderse por una reordenación ingenua. Inserta sin asumir que todo el fichero está ordenado.- Texto visible: interfaz y guion usan claves de traducción; no hardcodees cadenas visibles en GDScript salvo contratos deliberadamente literales, como frases que deben coincidir con el documento.
- Partidas:
Partida.guardar()devuelve éxito/fallo. Compruébalo. El disco persiste estado; no lo uses como bus entre pantallas. - Cinemáticas: guarda el estado antes de una cinemática saltables si el hallazgo debe persistir. Usa el reproductor/contrato común, no un ritmo paralelo.
- Interacción: usa acciones semánticas (
interactuar,cancelar, etc.) yPreferenciasSiga; no hardcodeesE, Escape o botones de mando en sistemas nuevos. - Audio:
Sonido= efectos puntuales;Musica= momentos dramáticos; ambiente continuo = #119. No mezcles responsabilidades para resolver un sonido concreto. - Foley: solo síntesis, nada grabado (orden de Varo, 29-09-2026). Los efectos no se graban del objeto real: se sintetizan con carácter de chip NES/PSX y evocan la acción con sonido de videojuego (el archivador suena a «bombeo», no a chapa). No se graban tomas con micro ni móvil ni se añaden grabaciones como fuente de foley. Los OGG de Kenney actuales solo son respaldo provisional hasta que la síntesis los sustituya. Ver
docs/audio/biblia-sonora-1475.md§2 y #1813. - Sueño: la progresión normal desde #281 es por objetivos oníricos. No reintroduzcas una salida física invisible como requisito de terminación.
- Investigación: combinar, anotar, examinar anexos o recompensar un puzzle no puede inventar hechos. Consume únicamente datos catalogados y conocidos por el jugador.
- Assets: los binarios se rigen por
.gitattributes, Git LFS ygodot/assets/procedencia.json. No crees un puntero LFS si no puedes subir también el objeto al almacén LFS.
Convenciones de código
- Comentarios y nombres en español, coherentes con el código existente.
- Explica por qué cuando el motivo no sea obvio; evita narrar literalmente la línea siguiente.
- GDScript con tabuladores y orden de definiciones aceptado por
gdlint. - Java sin Mockito en las pruebas existentes: los dobles usan
java.lang.reflect.Proxy. - Checkstyle, PMD y SpotBugs son gates, no sugerencias.
- Prefiere contratos puros/standalone antes de tocar rutas compartidas; integra después en un segundo corte si eso reduce conflictos.
Puntos delicados del dominio
- Acceso a casos: valida acceso al caso y pertenencia de entidades hijas; un
casoIdde ruta no basta. - Sembrado: cada caso debe fijar todos sus campos requeridos; compara con casos hermanos.
- Progreso: no dupliques una fuente de verdad para pistas, historias, economía o sueño porque una UI necesite mostrarla.
- Investigación SIGA: la auditoría versionada está en
docs/paridad-expedientes.md; actualízala cuando un corte cambie realmente la clasificación legado → Godot. - Playtest: #271/#272/#273/#280/#281/#113 contienen gates humanos. No abras más código sobre ellos sin un fallo reproducible nuevo cuando el plan maestro los marque como validación.
Archivos que no se versionan
CLAUDE.mdes local y está ignorado..env,target/,node_modules/,dist/.cache/,dist/salida/no se comitean.- Trabaja con
.env.exampley datos sintéticos; nunca con secretos o partidas personales.
