# El formato de AI-FIRST.md

> El frontmatter de AI-FIRST.md campo por campo, con su tipo, si es obligatorio y quién lo lee, más las reglas de los patrones de ruta.

`AI-FIRST.md` es el contrato entre el proyecto y el detector: dice qué gobierna al proyecto y dónde vive cada cosa, en una forma que `audit` puede verificar sin interpretar prosa. Vive en la raíz del repo, lo escribe `init` y lo mantiene el equipo a mano.

## La frontera con AGENTS.md

**`AGENTS.md` es para los agentes. `AI-FIRST.md` es para las herramientas.** El primero es normativo y está en presente: «no toques `migrations/`». El segundo es declarativo y no da órdenes: «`migrations/` es Zona Prohibida desde el 2026-03-12, por esta razón». No lo lee el agente para trabajar; lo lee el detector para medir. La única skill que lo lee al empezar es `protocolo-arranque`, que toma de ahí el perfil, la fase, el comando de verificación y las Zonas Prohibidas.

## Estructura

Markdown con un frontmatter YAML entre dos líneas `---`. **El frontmatter es el contrato**: lo lee el detector sin ambigüedad. **El cuerpo es para humanos** y el detector no lo interpreta: van ahí las notas que ninguna máquina puede verificar, como por qué cada zona es prohibida, o la tabla de permisos del repositorio. El cuerpo no repite el frontmatter: si un dato está en los dos lados, uno de los dos va a mentir.

Una clave que el detector no conoce se ignora, no es error.

## Campos

| Campo                                                 | Tipo             | Obligatorio | Lo escribe `init`                     | Quién lo lee                                |
| ----------------------------------------------------- | ---------------- | ----------- | ------------------------------------- | ------------------------------------------- |
| [`formato`](#formato)                                 | número           | **Sí**      | Sí                                    | `audit`, antes que nada                     |
| [`proyecto`](#proyecto)                               | cadena           | No          | Sí                                    | El reporte de `audit`                       |
| [`fase`](#fase)                                       | cadena           | No          | Sí                                    | Quien abre el archivo; `protocolo-arranque` |
| [`actualizado`](#actualizado)                         | fecha            | No          | Sí                                    | Quien abre el archivo                       |
| [`verificacion`](#verificacion)                       | cadena           | No          | Si lo deduce; si no, comentado        | El humano; `protocolo-arranque`             |
| [`perfil`](#perfil)                                   | mapa             | No          | Sólo con entrevista                   | `protocolo-arranque`                        |
| [`zonas_prohibidas`](#zonas_prohibidas)               | lista            | No          | Sí                                    | Verificación 1; `protocolo-arranque`        |
| [`superficies_de_decision`](#superficies_de_decision) | lista de cadenas | No          | Si encuentra alguna; si no, comentado | Verificación 2                              |
| [`alcance`](#alcance)                                 | mapa             | No          | Sí, con `spec`                        | Verificación 3                              |
| [`artefactos`](#artefactos)                           | mapa             | No          | Sí                                    | Verificaciones 2, 3, 4 y 5                  |
| [`auditoria`](#auditoria)                             | mapa             | No          | No: lo escribe `audit --registrar`    | El humano, en el diff del PR                |

Sin un campo opcional, la verificación que lo necesita se omite y el reporte dice por qué. Nunca se aprueba.

### `formato`

La versión **del formato de este archivo**, no del proyecto. Hoy la única que existe es `1`. Cualquier otro valor, o su ausencia, detiene `audit` con un mensaje y sale con 2: un formato desconocido no se interpreta a medias.

```yaml
formato: 1
```

### `proyecto`

El nombre que encabeza el reporte y el campo `proyecto` del JSON. Sin él, el reporte dice `(sin nombre)` y el JSON, `null`. `init` lo toma del `name` de `package.json`, sin el scope, o del nombre de la carpeta.

### `fase`

`exploracion`, `mvp` o `produccion`. No cambia ninguna verificación: la lee quien abre el archivo, y `protocolo-arranque` para saber en qué punto está el proyecto. `init` escribe `exploracion` salvo que la entrevista diga otra cosa.

### `actualizado`

La fecha de la última revisión del archivo, en formato `AAAA-MM-DD`. `init` pone la del día. Ninguna verificación la lee.

### `verificacion`

El comando que decide si el proyecto está sano, como `pnpm build && pnpm test`. **Lo corre el humano, no el detector**: `audit` mide documentación, no compila nada. `init` lo arma con los scripts `build` y `test` de `package.json`; si no los hay, deja la línea comentada.

### `perfil`

Qué clase de producto es y en qué forma de repositorio vive. Decide qué skills instala `init` con entrevista y qué artefactos escribe `protocolo-arranque`.

```yaml
perfil:
  producto: saas        # saas | landing | api | cli | movil
  repositorio: unico    # unico | monorepo | multiple
```

Las dos claves son obligatorias si el campo está. Un valor fuera de la lista es error de formato y sale con 2, no se reemplaza por uno por defecto: adivinar mal el perfil es peor que no tenerlo. Sin `perfil`, el archivo funciona igual; `protocolo-arranque` lo pregunta.

### `zonas_prohibidas`

Las rutas que el agente no modifica sin aprobación explícita. El criterio es el costo de revertir un error ahí, no la importancia del archivo. Pocas, o se vuelven ruido.

```yaml
zonas_prohibidas:
  - ruta: "migrations/"
    razon: "esquema vivo en producción"
    desde: 2026-03-12
  - ".env*"
```

| Clave   | Tipo   | Obligatoria | Qué es                                                     |
| ------- | ------ | ----------- | ---------------------------------------------------------- |
| `ruta`  | patrón | **Sí**      | Qué se protege. Ver [Patrones de ruta](#patrones-de-ruta). |
| `razon` | cadena | No          | Por qué. Aparece en el mensaje del hallazgo.               |
| `desde` | fecha  | No          | Desde cuándo rige.                                         |

Cada entrada puede ser un mapa o, si sólo lleva ruta, una cadena suelta. Un mapa sin `ruta` es error de formato.

### `superficies_de_decision`

Los archivos donde un cambio se presume decisión arquitectónica: el esquema, los puntos de entrada de los paquetes, las configuraciones. Si uno se toca y el ADR no gana una fila, la verificación 2 emite un P1. Las dependencias de producción se vigilan solas, sin declararlas.

```yaml
superficies_de_decision:
  - "**/*.config.*"
  - "packages/*/src/index.ts"
  - "src/lib/queue.ts"
```

Tiene que ser una lista de cadenas.

### `alcance`

De dónde sale el alcance declarado del cambio en curso.

```yaml
alcance:
  spec: docs/changes/pending/
  tolerancia: 3
```

| Clave        | Tipo   | Por defecto | Qué es                                                                                                      |
| ------------ | ------ | ----------- | ----------------------------------------------------------------------------------------------------------- |
| `spec`       | ruta   | —           | Un archivo, o una carpeta cuyos `.md` y `.mdx` son las specs activas. Sin ella, la verificación 3 se omite. |
| `tolerancia` | número | `0`         | Cuántos archivos fuera del alcance se aceptan antes de emitir el P1.                                        |

Cómo lista archivos una spec está en [Alcance excedido](https://ai-first.falcux.com/docs/referencia/verificaciones/#alcance-excedido). Un valor del tipo equivocado, como `tolerancia: "3"` entre comillas, se ignora sin error.

### `artefactos`

Los documentos que hablan de **este** repo, como un mapa de nombre a ruta relativa a la raíz. La verificación 4 comprueba que existan y que lo que mencionan exista; la 3 nunca los cuenta fuera de alcance.

```yaml
artefactos:
  adr: docs/ADR.md
  agents: AGENTS.md
  arquitectura: docs/ARQUITECTURA.md
  guia_diseno: docs/GUIA_DISENO.md
  inventario_componentes: docs/COMPONENTES.md
  componentes_dir: src/components/
  tech_notes: docs/TECH_NOTES.md
```

| Clave                                                                              | La usa además                                              |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `adr`                                                                              | Verificación 2: es el archivo que tiene que ganar la fila. |
| `inventario_componentes`                                                           | Verificación 5, junto con `componentes_dir`.               |
| `componentes_dir`                                                                  | Verificación 5. Es una carpeta: sólo tiene que existir.    |
| `agents`, `arquitectura`, `guia_diseno`, `tech_notes`, `session_log`, `change_log` | Sólo la 4.                                                 |

Se admite cualquier otra clave: es un documento más que la verificación 4 recorre. Cada valor tiene que ser una cadena con la ruta; una clave con valor nulo se ignora.

Precaución

Declarar el registro de sesión o el de cambios es posible, pero `init` no lo hace a propósito: son cronología, nombran archivos que ya se retiraron, y la verificación 4 cobraría cada mención vieja para siempre.

### `auditoria`

El resultado de la última corrida registrada. Lo escribe `audit --registrar` y nadie más; ninguna verificación lo lee. Existe para que el diff del PR muestre si la entropía subió o bajó.

```yaml
auditoria:
  fecha: 2026-09-23
  entropia: 40
  hallazgos:
    p0: 1
    p1: 0
    p2: 0
```

Cómo se escribe está en [`--registrar`](https://ai-first.falcux.com/docs/referencia/audit/#--registrar).

## Patrones de ruta

`zonas_prohibidas`, `superficies_de_decision` y las rutas que declara una spec usan las mismas reglas, pocas y explícitas:

| Forma          | Ejemplo                   | Coincide con                                                                    |
| -------------- | ------------------------- | ------------------------------------------------------------------------------- |
| Termina en `/` | `migrations/`             | Todo lo que esté debajo de esa carpeta, a cualquier profundidad, desde la raíz. |
| Sin `/`        | `.env*`                   | El nombre del archivo, en cualquier carpeta: también `apps/web/.env.local`.     |
| Con `/`        | `packages/*/src/index.ts` | La ruta completa desde la raíz.                                                 |

Dentro de un patrón, `*` y `?` no cruzan carpetas; `**` sí, y puede valer cero carpetas. Las rutas son relativas a la raíz y se escriben con `/`, que es como las entrega git.

## Errores de formato

Cualquiera de estos detiene `audit` y sale con 2, con el mensaje en la salida de error:

| Mensaje                                                                | Causa                                         |
| ---------------------------------------------------------------------- | --------------------------------------------- |
| `No hay AI-FIRST.md en …`                                              | El archivo no existe en la raíz.              |
| `AI-FIRST.md no tiene frontmatter YAML entre dos líneas «---».`        | Falta el frontmatter, o no está al principio. |
| `El frontmatter no es un mapa YAML.`                                   | El YAML es una lista o un valor suelto.       |
| `«formato: …» no está soportado. Este detector entiende el formato 1.` | `formato` falta o no es `1`.                  |
| `«zonas_prohibidas» debe ser una lista.`                               | —                                             |
| `«zonas_prohibidas[n]» necesita al menos «ruta».`                      | Una entrada es un mapa sin `ruta`.            |
| `«superficies_de_decision» debe ser una lista de cadenas.`             | —                                             |
| `«alcance» debe ser un mapa.`                                          | —                                             |
| `«artefactos» debe ser un mapa de nombre → ruta.`                      | —                                             |
| `«artefactos.clave» debe ser una ruta.`                                | Un valor no es cadena.                        |
| `«perfil.producto» debe ser uno de: saas, landing, api, cli, movil.`   | También su equivalente para `repositorio`.    |

## Un ejemplo real

El `AI-FIRST.md` que deja `init --sin-entrevista` en una carpeta vacía llamada `demo`:

```md
---
# Versión del FORMATO de este archivo, no del proyecto.
formato: 1
proyecto: "demo"
fase: exploracion    # exploracion | mvp | produccion
actualizado: 2026-09-23


# El comando que decide si el proyecto está sano. Lo corre el humano, no el
# detector: audit mide documentación, no compila nada.
# verificacion: pnpm build && pnpm test


# Rutas que el agente no modifica sin aprobación explícita. El criterio es el
# costo de revertir un error ahí, no la importancia del archivo. Pocas, o se
# vuelven ruido. Revisa las sugeridas y completa la razón.
zonas_prohibidas:
  - ruta: ".env*"
    razon: "credenciales"
    desde: 2026-09-23


# Superficies donde un cambio se presume decisión arquitectónica. Si una se toca
# y el ADR no gana una fila, audit emite P1. Las dependencias de producción se
# vigilan solas, sin declararlas.
# superficies_de_decision:
#   - "**/*.config.*"
#   - src/lib/queue.ts


# Alcance de la sesión en curso: la spec del cambio abierto (CHG-XXX), que vive
# en la carpeta que init acaba de crear. Requiere que la spec liste archivos en
# una sección «Archivos» o «Alcance», con rutas entre acentos graves. Sin spec
# activa el check se omite, que es lo correcto: no hay alcance que exceder.
alcance:
  spec: docs/changes/pending/
#   tolerancia: 3


# Documentos que hablan de ESTE repo. audit verifica que lo que mencionan
# exista. Un check sin su artefacto se omite, nunca se aprueba.
artefactos:
  adr: "docs/ADR.md"
  agents: "AGENTS.md"
---


# AI-FIRST.md — demo


> Qué gobierna a este proyecto. Las reglas que el agente obedece están en
> `AGENTS.md`; acá está el mapa que las herramientas verifican.


## Notas


Por qué `.env*` es Zona Prohibida: _(completar: qué cuesta revertir un error ahí)_.
```

Con entrevista, el archivo lleva además el bloque `perfil` y la `fase` y la `verificacion` que se respondieron. En un repo con componentes, `init` agrega bajo `artefactos` las dos claves de la verificación 5, comentadas, para que las actives tú.

## Relacionado

[Las cinco verificaciones](https://ai-first.falcux.com/docs/referencia/verificaciones/)Qué hace cada una con estos campos.

[ai-first init](https://ai-first.falcux.com/docs/referencia/init/)Cómo se genera este archivo y qué deduce el escaneo.

[Gobierno del contexto](https://ai-first.falcux.com/docs/parte-2/gobierno-del-contexto/)Por qué existen las Zonas Prohibidas, el ADR y la medición de entropía.
