spec 1.0 · normativo
Categorías de contenido
Leji define cinco categorías lógicas de contenido. Clasifican para qué sirve un documento, no dónde se encuentra: los nombres de categoría son identificadores estables que utilizan el manifiesto, el índice y el utillaje. El equipo decide cómo llamar a los directorios.
Las cinco categorías#
| Categoría | Qué le corresponde |
|---|---|
domain |
El lenguaje del negocio y la semántica del producto, en palabras del propio equipo: qué significan los sustantivos centrales, cómo se relacionan, qué términos tienen un sentido local. Los registros de estado del negocio (el estado de un encargo, una instantánea de mercado) también se clasifican aquí, como registros. |
system |
La arquitectura y sus invariantes: fronteras entre servicios, propiedad de los datos, contratos de integración, modelos de consistencia, contratos de fallo, las restricciones con las que vive cada cambio. Las evaluaciones técnicas y los informes de sistema se clasifican aquí, como registros. |
practice |
Convenciones y patrones que se aplican de forma automática: convenciones de código, patrones de prueba y los patrones de prompt y de flujo de trabajo que han demostrado su valor (véase más abajo la regla de captura). Los registros de haber aplicado un método (una retrospectiva, la bitácora de ejecución de un runbook) se clasifican aquí, como registros. |
governance |
Salvaguardas de agentes y reglas operativas: qué pueden hacer los agentes sin que se les pida, qué requiere aprobación humana, reglas de tratamiento de datos, disparadores de escalado, controles de cumplimiento. La evidencia de gobernanza (un registro de auditoría, un informe de revisión) se clasifica aquí, como registros. |
decisions |
Registros fechados de por qué las cosas son como son, según decisions.md. |
Intención y registros#
Todo documento gobernado es o bien intención o bien un registro, con independencia de su categoría:
- La intención es verdad presente mantenida: glosarios, invariantes, convenciones, salvaguardas. Los lectores confían en ella como vigente, así que cuando la realidad se mueve, el documento se corrige. La intención es la razón de ser de los horizontes de revisión y del mecanismo de vigencia (véase governance.md).
- Un registro preserva afirmaciones dentro de un límite temporal o de evento explícito: estados, evaluaciones, libros de asientos, informes, resultados de reuniones, archivos históricos. El estado posterior sustituye a un registro en vez de corregirlo; el original sigue siendo un relato válido de su momento. La superficie de actualidad de un registro es su fecha, nunca un horizonte de revisión.
La prueba de clasificación es una sola pregunta: si información posterior contradice este documento, ¿hay que corregirlo porque los lectores confían en él como vigente, o la nueva información lo sustituye mientras el original sigue siendo un relato válido de su momento? Corregir significa intención; sustituir significa registro.
Un registro se gobierna exactamente igual que la intención: se indexa, se revisa, tiene responsable y se enruta. Lo que cambia es qué puede hacer un lector con él: un lector MUST NOT tratar un registro como intención vigente; es evidencia fechada (véase context-layer.md, Cómo se lee un registro). Los registros de decisión son el subtipo formal de registro: son registros por naturaleza, con su propio esquema y ciclo de vida según decisions.md.
Algunas cuestiones sobre los registros quedan deliberadamente fuera de la 1.0 y se reconocen en lugar de ocultarse: no existe una noción para máquinas de serie de registros (por lo que el utillaje nunca certifica cuál es «el último»), no hay mecanismo de actualidad de flujo (si el siguiente registro esperado va con retraso) y no hay clases por sección para documentos que mezclan de forma sustancial contenido de intención y de registro. Un documento mixto SHOULD dividirse; donde dividirlo resulte desproporcionado, clasifíquelo por el contrato en el que se apoyan principalmente sus lectores. El contenido que honestamente no encaja en ninguna categoría se queda como referencia; no se promete que la clasificación esté libre de criterio.
Requisitos#
- El manifiesto MUST asignar cada categoría que declare a uno o más archivos de índice relativos a la raíz del repositorio (
categories.<id>.indexes); cada archivo de índice SHOULD quedar bajo la raíz del contexto declarada, según context-layer.md. Un archivo de índice declara inclusión, no reubica: el contenido se queda donde el equipo ya lo guarda (por ejemplobusiness/,technology/,architecture/), y un mismo directorio puede aportar documentos a más de una categoría sin renombrar nada. - Un archivo de índice es markdown curado que lleva uno o más bloques de código delimitados con el identificador
leji-index. Un bloque abre con una línea de tres o más comillas invertidas seguidas de la cadena de información del bloque y cierra con la siguiente línea de tres o más comillas invertidas; el número de comillas invertidas de la valla de cierre no tiene por qué coincidir con el de la de apertura. Solo tres cadenas de información son válidas:leji-index(un bloque de intención),leji-index intent(lo mismo, explícito) yleji-index record(un bloque de registros, cuyas entradas se resuelven como registros). Cualquier otro token trasleji-indexes un error de análisis, nunca se ignora en silencio: la gramática es finita por diseño. Cada bloque enumera contenido a razón de una entrada por línea con la forma- path: <repository-root-relative-path>, donde una ruta es un directorio (su markdown se incluye recursivamente) o un único archivo markdown. Una ruta MUST ser POSIX relativa a la raíz del repositorio: una/inicial, un segmento..o una barra invertida son inválidos y se rechazan. Las líneas en blanco y las líneas completas de comentario#se ignoran, y una entrada MAY llevar al final un# comentarioprecedido de espacio en blanco. En esta gramática el espacio en blanco es el espacio ASCII (U+0020) y el tabulador (U+0009) y nada más, en todos los sitios donde la gramática lo consulta: alrededor de las comillas invertidas de la valla y de la cadena de información, como relleno inicial y final de una línea de entrada, y antes del#que abre un comentario final. Una marca de orden de bytes UTF-8 inicial se elimina antes de analizar. Las líneas se separan por LF tolerando un CR final, y el archivo es UTF-8. Las implementaciones MUST NOT usar aquí una clase de espacio en blanco del entorno de ejecución: cualquier otro carácter que un entorno de ejecución clasifique como espacio en blanco, entre ellos U+0085 y U+00A0, es contenido normal de la ruta, de modo que una entrada cuya ruta lleve uno se informa como ausente en vez de recortarse en silencio. Los bloquesleji-mountsde boot-profile.md están congelados sobre el mismo alfabeto, así que un único escáner lee ambas gramáticas y tres implementaciones no pueden discrepar sobre si una valla existe siquiera. Varios bloques en un mismo archivo se concatenan en el orden del documento. Se permiten prosa y encabezados alrededor de los bloques, de modo que un archivo de índice sirve también como mapa legible de la categoría. El barrido va por líneas y no consulta la estructura markdown: una línea que lleve tres o más comillas invertidas y la etiqueta, tras un sangrado opcional de espacios o tabuladores, abre un bloque real esté donde esté en el documento, incluso dentro de una valla más larga de ejemplo o dentro de un elemento de lista. Un ejemplo destinado a ilustrar y no a declarar se delimita, por tanto, con una etiqueta distinta, nunca con un token de más trasleji-index: la etiqueta es lo que el escáner compara, de modo queleji-index exampleabre un bloque real e informa de un error de análisis, mientras que una valla etiquetadatextno abre nada. La ubicación RECOMMENDED escontext/<id>.mdbajo la raíz del contexto; la ubicación es configurable y el utillaje nunca la fija en el código. - Una capa de contexto MUST asignar al menos
domainosystem, másdecisions, para declarar cualquier nivel de conformidad (véase conformance.md), y el mínimo poblado dedomain/systemMUST incluir al menos un documento de intención: una capa de contexto hecha solo de registros preserva historia pero no aporta contexto operativo. Las demás categorías se acumulan a medida que el equipo se topa con preguntas reales; una categoría vacía (aquella cuyos archivos de índice no resuelven a ningún documento) MUST NOT asignarse para cumplir una lista de comprobación. - Un documento resuelve a exactamente una categoría y una clase. Las entradas de índice son selectores, y la resolución sigue la especificidad del selector: un selector directo de archivo gana a cualquier selector de directorio, y un selector de directorio más profundo gana a un selector de directorio ancestro. El selector más específico que cubre un documento determina su categoría y la clase de su bloque; un documento al que cubre un selector más amplio pero que gana uno más específico sencillamente no es contenido de ese selector más amplio (así es como se expresa, sin mover nada, un archivo que se mantiene al día dentro de un directorio de registros, o el registro de decisiones de un equipo dentro de un árbol asignado más amplio). Selectores de igual especificidad que discrepan en categoría o clase son un error, nunca se resuelven por el orden del índice; asignaciones idénticas de igual especificidad resuelven una sola vez, mientras que una entrada literalmente duplicada dentro de un mismo archivo de índice se rechaza. El utillaje SHOULD señalar un selector cuyos documentos cubiertos hayan sido ganados todos por selectores más específicos (un selector eclipsado): peso muerto en el mapa curado, nunca un error. Por lo demás la resolución es determinista: una entrada de directorio se expande a su markdown en orden lexicográfico POSIX (por punto de código Unicode; se RECOMMENDED que las rutas se mantengan en ASCII para que el orden no sea ambiguo entre implementaciones), y cualquier ruta cuya ubicación real (tras resolver los enlaces simbólicos) se escape de la raíz del repositorio se excluye en vez de seguirse. Las entradas de índice (véase machine-readable-surface.md) llevan el identificador de categoría y la clase.
- Un documento MAY declarar su clase en el frontmatter (
kind: intentokind: record); el frontmatter prevalece sobre la clase de bloque del selector ganador y nunca sobre la categoría. Cualquier otro valor dekindes un error. Los registros de decisión no llevan clavekind(su esquema es cerrado y son registros por naturaleza). Un registro MAY llevar unadateen el frontmatter (YYYY-MM-DD); el utillaje lee la fecha de un registro solo de ese campo, nunca de la prosa, de convenciones de encabezado o de nombres de archivo. Un registro MUST NOT llevarfreshness.reviewAfter(un horizonte de revisión es un mecanismo de intención; sobre un registro promete una actualidad que el documento no puede tener, y es un error). - El contenido de práctica que describe patrones de prompt o de flujo de trabajo SHOULD capturarse solo después de que el patrón haya funcionado al menos dos veces (la regla de probado dos veces). La captura prematura es la forma en que los directorios de práctica se llenan de aspiraciones.
Notas (no normativo)#
No todas las categorías tienen que estar presentes desde el primer día. La capa de contexto mínima viable es aquella en la que se apoya de verdad el trabajo del primer mes. Las categorías permiten que una persona o un agente se pregunten «¿qué clase de verdad es esta?» y carguen solo la porción pertinente para la tarea, en lugar del árbol completo.
Las dos clases existen porque la documentación de un repositorio real son dos corpus entrelazados con modelos de verdad distintos, y forzar la mitad operativa bajo la semántica de la intención falla por ambos lados: promesas de vigencia que no se pueden cumplir, o la mayoría del repositorio desterrada fuera de la gobernanza. Una forma desarrollada, con una excepción de intención dentro de un directorio de registros:
# Contexto de dominio
```leji-index
- path: docs/glossary.md
```
El estado operativo se gobierna como registros; la política de escalado se queda como intención.
```leji-index record
- path: docs/operations/
```
```leji-index intent
- path: docs/operations/escalation-policy.md
```