---
title: Contratos
description: Las reglas con las que se revisa cada escritura, el veredicto que entregan y el catálogo de reglas que activa una colección.
section: concepts
order: 1
---

# Contratos

Un contrato es una regla sobre una entrada. Hollware ejecuta los contratos de una colección en cada escritura, y de nuevo al publicar, y entrega un **veredicto**.

## El veredicto

```json
{
  "ok": false,
  "phase": "write",
  "errors": [
    {
      "contract": "schema",
      "severity": "error",
      "path": "/frontmatter/description",
      "message": "Too big: expected string to have <=160 characters",
      "fix": "Shorten the description to 160 characters or fewer."
    }
  ],
  "warnings": []
}
```

Cada infracción tiene un `path` (un JSON Pointer dentro de la entrada), un `message` y un `fix`: un agente puede actuar sobre ella sin leer tu código.

## Una escritura nunca falla por un contrato

Un borrador que no cumple un contrato se **guarda**, con el veredicto. El trabajo en curso nunca se pierde, y el agente lo corrige con `update_draft`. Lo que un contrato detiene es la publicación:

- un **error** bloquea `publish`, que responde `blocked`;
- una **advertencia** pide confirmación: `publish` responde `needs_acknowledgement` con las advertencias, y publica cuando se devuelven en `acknowledgeWarnings`.

`validate` ejecuta los contratos sobre un Markdown sin guardar nada.

## Incluidos

Estos se ejecutan siempre: el esquema del frontmatter, los componentes y sus props, la seguridad del contenido (nada de HTML crudo que ejecute scripts) y el límite de tamaño de una entrada.

## El catálogo

Una colección activa más reglas del catálogo, cada una con una severidad (un error bloquea la publicación; una advertencia hay que confirmarla) y sus parámetros. Agrégalas en el admin, en la página de la colección, o por MCP con `set_collection`; `get_structure` lista el catálogo con el JSON Schema de los parámetros de cada regla.

| Regla | Revisa | Parámetros |
| --- | --- | --- |
| `translation-pair` | que la entrada exista en cada locale de su grupo de traducción, para publicar | ninguno |
| `internal-links-resolve` | que los enlaces a otras entradas apunten a entradas publicadas, al publicar | ninguno |
| `images-have-alt` | que cada imagen tenga texto alternativo | ninguno |
| `field-length` | que un campo de texto tenga entre `min` y `max` caracteres, o una lista entre `min` y `max` elementos | `field`, `min`, `max`, `unless` |
| `field-pattern` | que un campo de texto calce completo con una expresión regular | `field`, `pattern`, `description` |
| `required-to-publish` | campos que un borrador puede dejar vacíos y que una entrada publicada debe llenar | `fields` |
| `banned-words` | palabras que no pueden aparecer ni en un campo de texto ni en el cuerpo | `words`, `reason` |
| `reference` | cada slug que nombra un campo es una entrada de otra colección, que debe estar publicada para publicar | `field`, `collection`, `locale` |

Un título de 60 caracteres como máximo, salvo que haya un `seoTitle`, es una sola regla:

```json
{
  "rule": "field-length",
  "severity": "warning",
  "params": { "field": "title", "max": 60, "unless": "seoTitle" },
  "id": "seo-title-length"
}
```

Una entrada puede nombrar otras por su slug, como el autor de un post, una serie o el evento de una charla. La regla `reference` revisa los slugs de un campo (uno, o una lista) contra una colección, en el locale de la entrada o en el `locale` que le des:

```json
{ "rule": "reference", "severity": "error", "params": { "field": "author", "collection": "authors" } }
```

Un sitio las lee junto con la entrada: `get_entry` con `references: true` (o `getEntry(…, { references: true })`, o `?references=true` por HTTP) responde `references`, las entradas publicadas que nombra cada campo, en su orden.

`id` nombra la regla en los veredictos; dale uno cuando una colección tenga la misma regla dos veces. Cada infracción trae un `fix` escrito para el agente que la lee: qué hacer, no qué salió mal.
