docs / Especificación 1.0Specification 1.0
Traducción informativa al español; el texto normativo es el original en inglés.
Especificación .mini#
Versión: 1.0 · Fecha: 2026-09-01 · Estado: Estable · Licencia: MIT Autores: Adrián E. J. Palma Obispo, Erick J. Palomino Santa Cruz (Universidad Peruana de Ciencias Aplicadas)
1. Resumen#
.mini es una notación de texto posicional, orientada a líneas y bifurcable para
salidas estructuradas producidas por modelos generativos de lenguaje en dominios
cerrados. Un documento .mini es una línea de cabecera que nombra un contrato
(un prefijo de familia) y declara el recuento de registros, seguida de exactamente
un registro por línea cuyos campos están separados por | y cuyo significado lo da
la posición. Como emisor y receptor comparten el contrato, el documento nunca repite
nombres de campo, llaves, corchetes, comillas ni indentación; su coste estructural es
el mínimo necesario para mantener cada registro independientemente validable y
convertible de forma determinista a un objeto JSON canónico.
.mini no es un formato único sino una familia de contratos gobernada por un
protocolo de bifurcación. Cualquier dominio orientado a registros — ítems de
evaluación, tarjetas, rúbricas, ítems de encuesta, casos de prueba, eventos de log,
anotaciones de entidades, filas de catálogo, salidas de clasificación, historias de
usuario — obtiene su propio contrato sin escribir un parser: la implementación de
referencia interpreta el contrato.
2. Conformidad#
Las palabras clave MUST, MUST NOT, SHOULD y MAY se interpretan como en RFC 2119. Un parser conforme acepta todo documento válido bajo un contrato, rechaza todo documento inválido con al menos uno de los códigos de error de §8, y produce el objeto canónico de §7. Un serializador conforme produce, para cada objeto canónico válido bajo un contrato, un documento que el parser devuelve a un objeto igual (§9, ida y vuelta). Una familia conforme satisface los invariantes de §10.
3. Estructura léxica#
3.1 Codificación y líneas#
Un documento es texto UTF-8. Los parsers MUST ignorar una marca de orden de bytes inicial y opcional. Las líneas se separan con LF (U+000A); los parsers MUST ignorar un CR (U+000D) inmediatamente anterior a un LF. Las líneas vacías o que solo contienen blancos no son significativas y MUST omitirse. La primera línea significativa es la cabecera; cada línea significativa siguiente es un registro.
3.2 Caracteres estructurales#
| Carácter | Papel | Alcance |
|---|---|---|
\| |
separador de campos | cabecera y registros |
separador de lista (, por defecto; un carácter fijado por el contrato) |
separa elementos de una lista, lista marcada o tupla | solo dentro de campos de tipo lista |
* |
marcador de selección | solo como último carácter de un elemento de lista |
\ |
carácter de escape | en todas partes |
" |
delimitador de elemento entrecomillado | solo como primer carácter de un elemento de lista |
= |
separador clave/valor | entradas de cabecera, primera ocurrencia no escapada |
Ningún otro carácter tiene significado estructural. Los dos puntos, corchetes, llaves, espacios y tabuladores son contenido literal; una comilla que no sea el primer carácter de un elemento de lista es literal.
3.3 Secuencias de escape#
| Secuencia | Denota |
|---|---|
\| |
una barra vertical literal |
\, (o \<sep> para el separador del contrato) |
un separador de lista literal |
\* |
un asterisco literal (necesario solo cuando un elemento terminaría en *) |
\" |
una comilla literal (necesaria solo cuando un elemento empezaría por ") |
\\ |
una barra invertida literal |
\n |
un salto de línea dentro de un valor |
Los parsers MUST reconocer las secuencias de escape en toda posición. Un generador MUST escapar
|, \ y los saltos de línea en cada valor, y MUST proteger el separador de lista
y un * final dentro de elementos de lista, ya sea con los escapes de arriba o con
comillas (§3.4). Escapar el separador de lista en un campo escalar es innecesario
pero inofensivo (el sobre-escape es idempotente). Una barra invertida seguida de
cualquier otro carácter, o una barra invertida al final, es un error (E09).
3.4 Elementos de lista entrecomillados#
Un elemento de lista MAY entrecomillarse con comillas dobles, estilo CSV: "impacto, justicia
y evidencia"*. Dentro de las comillas el separador de lista y * son literales y una
comilla doble "" denota una comilla; el marcador de selección, si lo hay, sigue a
la comilla de cierre ("…"*) o, equivalentemente, la precede inmediatamente
("…*"); un asterisco literal en esa posición se escribe \*. Los escapes de barra
invertida siguen activos dentro de las comillas (| y \ aún deben escaparse). Una
comilla sin cerrar, o texto entre la comilla de cierre y el siguiente separador, es
un error (E09). Entrecomillar y escapar son notaciones equivalentes del mismo valor;
el serializador canónico emite la forma escapada.
3.5 Blancos#
Los blancos iniciales y finales de un campo, de un elemento de lista y de un valor de cabecera no son significativos y MUST recortarse. Los blancos internos se preservan. Los campos escalares nunca van entrecomillados.
4. Gramática#
document ::= header ( LF record )* LF?
header ::= prefix ( "|" entry )*
entry ::= key "=" value
prefix ::= [A-Za-z] [A-Za-z0-9_-]*
key ::= [A-Za-z_] [A-Za-z0-9_]*
record ::= value ( "|" value )*
value ::= ( char | escape )* -- may be empty
list ::= ( element ( SEP element )* )? -- interpretation of a list-typed value
element ::= ( bare | quoted ) "*"?
bare ::= value -- must not start with an unescaped '"'
quoted ::= '"' ( qchar | '""' | escape )* '"'
qchar ::= any Unicode scalar except '"', "|", "\", LF
escape ::= "\" ( "|" | SEP | "*" | '"' | "\" | "n" )
char ::= any Unicode scalar except "|", "\", LF
SEP es el separador de lista del contrato. La gramática es regular a nivel de
línea: un registro se reconoce con una sola pasada de izquierda a derecha que
resuelve escapes y divide por | no escapados; un campo de tipo lista se divide
después por SEP no escapados. No se necesita anticipación más allá de un carácter,
así que el análisis es determinista y lineal en la longitud de la línea.
5. Cabecera#
La cabecera es prefix|key=value|key=value….
prefixnombra el contrato (familia). MUST coincidir con un contrato registrado.nMUST estar presente y MUST ser igual al número de líneas de registro (E03/E04).vMAY estar presente y nombra la versión del contrato (por defecto 1).- Las demás claves las tipifica el contrato (escalar, lista o tupla). Las claves desconocidas se aceptan y se conservan como strings, lo que permite a los productores adjuntar procedencia (modelo, fecha, idioma, tema) sin cambiar el contrato.
- Una clave de cabecera MAY actuar como clave de recuento: un campo de lista
cuya entrada de contrato declara
count_key: "k"MUST tener exactamentekelementos en cada registro (E07). Esto convierte una colisión de delimitador dentro de una lista en un error detectable.
6. Registros y tipos de campo#
Un contrato define una lista ordenada de campos nucleares seguida de una lista
ordenada de campos de extensión. Un registro MUST contener cada campo nuclear
(E05) y MAY contener un prefijo de los campos de extensión; las extensiones
ausentes son null. Si v de la cabecera es menor o igual que la versión del
contrato, el registro MUST NOT contener más campos que los declarados (E05). Si la
cabecera del mismo prefijo declara un v mayor, el parser MUST validar léxicamente
el registro completo, decodificar el prefijo de campos conocido e ignorar únicamente
los campos finales desconocidos.
| Tipo | Forma textual | JSON canónico | Notas |
|---|---|---|---|
str |
texto literal | string | |
int |
-?[0-9]+ |
integer | min/max opcionales (E13) |
float |
número JSON | number | los valores enteros MAY omitir .0 |
bool |
true / false |
boolean | 1/0 aceptados a la entrada |
enum |
uno de los valores declarados | string | E10 en caso contrario |
list<T> |
e1,e2,… |
array | aridad min/max/count_key (E07) |
mlist<T> |
e1*,e2,… |
array más una clave hermana selected |
regla del marcador: exactly_one (por defecto), at_least_one, at_most_one, any (E08) |
tuple(a:T,b:U,…) |
a,b,… |
objeto {a:…, b:…} |
aridad fija (E07); un nivel de anidamiento sin sintaxis de anidamiento |
Un campo vacío denota null y solo es válido para campos opcionales (E06). Un campo
declarado unique MUST NOT repetir su valor dentro de un documento (E11).
La lista marcada es el modismo que reemplaza a un campo "respuesta" separado: el
elemento seleccionado lleva un sufijo de un carácter, lo que mantiene la selección
pegada a su contenido. Para exactly_one/at_most_one el valor canónico de
selected es un índice (o null); para at_least_one/any es una lista ascendente
de índices.
7. Objeto canónico#
Un parser MUST producir:
{ "prefix": "<prefix>",
"header": { "n": <int>, "v": <int>, ...typed header entries... },
"<records_key>": [ { "<field>": <value>, ... }, ... ] }
records_key la declara el contrato (p. ej. items, cases). Una lista marcada
options con clave de selección correct produce dos claves hermanas
"options": [...] y "correct": <index>. Una tupla produce un objeto anidado.
Los números canónicos se comparan numéricamente (-1 ≡ -1.0).
8. Validación y códigos de error#
La validación es local (cada registro se comprueba en su propia línea) y global (recuento y unicidad). Un parser MUST reportar el número de línea 1-based de cada error. Los parsers estrictos recogen todos los errores y rechazan el documento; los parsers tolerantes devuelven los registros válidos junto con la lista de errores, lo que permite la recuperación parcial de salidas generadas largas.
| Código | Condición |
|---|---|
| E01 | falta la línea de cabecera |
| E02 | el prefijo de la cabecera no coincide con el contrato |
| E03 | la cabecera no trae n |
| E04 | número de líneas de registro ≠ n |
| E05 | el registro tiene menos campos que el núcleo, o tiene campos excedentes sin declarar una versión de documento posterior a la del contrato |
| E06 | el valor escalar no coincide con su tipo, o un valor requerido está vacío |
| E07 | aridad de lista / tupla fuera de min/max, o ≠ count_key, o ≠ tamaño de tupla |
| E08 | el recuento de marcadores viola la regla de la lista marcada |
| E09 | secuencia de escape inválida o barra invertida al final |
| E10 | valor fuera de la enumeración |
| E11 | valor duplicado en un campo unique |
| E12 | entrada de cabecera malformada o requerida ausente |
| E13 | valor numérico fuera de min/max |
| E20 | el contrato mismo es inválido |
| E21 | invariante de familia violado |
| ## 9. Ida y vuelta |
Para cada contrato C y cada objeto canónico o válido bajo C:
parse(dumps(o, C), C) = o y dumps(parse(t, C), C) = t para cada documento t
emitido por el serializador. Esta propiedad — no la compacidad — es el criterio de
aceptación de una familia .mini: una compresión que no hace ida y vuelta es una
abreviatura, no una serialización.
10. Protocolo de bifurcación#
Una familia es un contrato nuevo derivado de un padre. Conserva la analizabilidad
por construcción si satisface cinco invariantes, todos comprobables por máquina por
el registro de referencia (mini check-forks):
| # | Invariante | Regla |
|---|---|---|
| I1 | Línea local | una línea = un registro completo e independientemente válido |
| I2 | Cabecera | prefijo y n obligatorios; las claves de cabecera requeridas del padre siguen requeridas |
| I3 | Núcleo estable | la lista de campos de la hija empieza con la lista completa de campos del padre (núcleo + extensiones), mismos nombres, mismo orden, mismos tipos, mismo separador de lista |
| I4 | Extensión al final | los campos nuevos se añaden tras los heredados y son opcionales |
| I5 | Ida y vuelta | la hija incluye fixtures (valid.mini ↔ canonical.json, escaping.mini, casos negativos) que pasan §9 |
Consecuencias. Un parser de versión anterior lee documentos posteriores del
mismo prefijo cuando la cabecera declara un v mayor: valida la línea completa,
decodifica los campos que conoce e ignora la cola desconocida. Una bifurcación usa
otro prefijo: el registro se analiza primero con el contrato hijo elegido por el
despacho del registro y luego la aplicación MAY proyectar su prefijo heredado al
esquema del padre; esto no equivale a analizar directamente el documento hijo con
el contrato padre. El contrato hijo también admite registros sin sus extensiones
opcionales cuando se emiten bajo el prefijo hijo. Reordenar, retipificar o eliminar
un campo heredado es un cambio incompatible y MUST publicarse bajo un prefijo
nuevo, nunca como una versión nueva del mismo prefijo. El crecimiento compatible
(añadir extensiones o claves de cabecera opcionales) incrementa v.
Una familia se publica como una carpeta forks/<prefix>/ con contract.json,
README.md y fixtures/. El bloque de especificación que un modelo generativo
necesita para producir la familia se deriva mecánicamente del contrato
(mini prompt <prefix>); una familia, por tanto, consiste en datos, no código.
11. Fundamento del diseño#
- Posición en vez de nombres. En un dominio cerrado ambos lados conocen el
esquema; repetir
"statement","options","correct"en cada registro es sobrecarga pura. Llevar el esquema al contrato, declarado una vez, es lo que hace que el coste por registro se acerque al contenido mismo. - Un byte, un papel.
|nunca aparece dentro de listas, el separador nunca aparece a nivel de campo, y*es solo un sufijo. Esta estricta separación de niveles es lo que mantiene la gramática regular y el parser de una pasada. - Dos protecciones equivalentes para el separador de lista. La versión 0 (2026-06) usaba solo comillas estilo CSV; la validación generativa mostró que un modelo más débil a veces omitía las comillas y producía colisiones silenciosas de delimitador. Un borrador de la versión 1 reemplazó las comillas solo por escapes de barra invertida; una segunda ronda de validación mostró que la misma clase de modelo ignora un escape desconocido pero aplica con fiabilidad las comillas CSV, que ha visto en enormes cantidades de datos de entrenamiento. La versión 1.0, por tanto, acepta ambas notaciones (§3.3, §3.4), emite canónicamente la forma escapada, y añade la clave de recuento de §5, que convierte cualquier colisión residual en un error de aridad detectable en vez de una corrupción silenciosa.
- Marcador como sufijo. La selección viaja con su contenido, lo que evita desalineaciones índice/contenido durante la generación y permite la verificación local.
- Evolución solo por añadido. La misma disciplina de los protocolos binarios y los
esquemas evolucionables (campos nuevos solo al final; los lectores anteriores
ignoran la cola únicamente si el mismo prefijo declara un
vposterior) da compatibilidad hacia adelante y hacia atrás sin negociación adicional.
12. Limitaciones (por diseño)#
.mini no representa jerarquías profundas, relaciones muchos-a-muchos dentro de un
registro, registros heterogéneos en un documento, o esquemas que evolucionan durante
una conversación. Las relaciones se expresan con el patrón relacional (una segunda
familia cuyos registros referencian identificadores de la primera, p. ej. registros
card que apuntan a ítems a) o con campos tuple de un nivel. Los estándares
formales de interoperabilidad (p. ej. QTI para evaluación) siguen siendo el destino
del objeto canónico, no del formato de transporte. Los ahorros de tokens dependen del
tokenizador y del idioma; el benchmark de referencia reporta el tokenizador, el corpus,
los serializadores y la línea base de cada figura.
Normative text; the Spanish version is an informative translation.
.mini Specification#
Version: 1.0 · Date: 2026-09-01 · Status: Stable · License: MIT Authors: Adrián E. J. Palma Obispo, Erick J. Palomino Santa Cruz (Universidad Peruana de Ciencias Aplicadas)
1. Abstract#
.mini is a line-oriented, positional, forkable text notation for structured
outputs produced by generative language models in closed domains. A
.mini document is a header line that names a contract (a family prefix)
and declares the record count, followed by exactly one record per line whose
fields are separated by | and whose meaning is given by position. Because
sender and receiver share the contract, the document never repeats field
names, braces, brackets, quotation marks or indentation; its structural cost is
the minimum needed to keep every record independently validatable and
deterministically convertible to a canonical JSON object.
.mini is not a single format but a family of contracts governed by a
forking protocol. Any record-oriented domain — assessment items, flashcards,
rubrics, survey items, test cases, log events, entity annotations, catalogue
rows, classification outputs, user stories — obtains its own contract without
writing a parser: the reference implementation interprets the contract.
2. Conformance#
The key words MUST, MUST NOT, SHOULD and MAY are to be interpreted as in RFC 2119. A conforming parser accepts every document valid under a contract, rejects every invalid document with at least one of the error codes of §8, and produces the canonical object of §7. A conforming serializer produces, for every canonical object valid under a contract, a document that the parser maps back to an equal object (§9, round-trip). A conforming fork satisfies the invariants of §10.
3. Lexical structure#
3.1 Encoding and lines#
A document is UTF-8 text. An optional leading byte-order mark MUST be ignored. Lines are separated by LF (U+000A); a CR (U+000D) immediately preceding an LF MUST be ignored. Lines that are empty or contain only whitespace are not significant and MUST be skipped. The first significant line is the header; every following significant line is a record.
3.2 Structural characters#
| Character | Role | Scope |
|---|---|---|
\| |
field separator | header and records |
list separator (, by default; one character fixed by the contract) |
separates elements of a list, marked list or tuple | inside list-typed fields only |
* |
selection marker | only as the last character of a list element |
\ |
escape character | everywhere |
" |
quoted-element delimiter | only as the first character of a list element |
= |
key/value separator | header entries, first unescaped occurrence |
No other character has structural meaning. Colons, brackets, braces, spaces and tabs are literal content; a quotation mark that is not the first character of a list element is literal.
3.3 Escape sequences#
| Sequence | Denotes |
|---|---|
\| |
a literal vertical bar |
\, (or \<sep> for the contract's separator) |
a literal list separator |
\* |
a literal asterisk (needed only when an element would otherwise end in *) |
\" |
a literal quotation mark (needed only when an element would otherwise start with ") |
\\ |
a literal backslash |
\n |
a line break inside a value |
Escape sequences MUST be recognised in every position. A generator MUST escape
|, \ and line breaks in every value, and MUST protect the list separator
and a trailing * inside list elements, either with the escapes above or with
quoting (§3.4). Escaping the list separator in a scalar field is unnecessary
but harmless (over-escaping is idempotent-safe). A backslash followed by any
other character, or a trailing backslash, is an error (E09).
3.4 Quoted list elements#
A list element MAY be enclosed in double quotes, CSV style: "impacto, justicia
y evidencia"*. Inside the quotes the list separator and * are literal and a
doubled quote "" denotes one quotation mark; the selection marker, if any,
follows the closing quote ("…"*) or, equivalently, immediately precedes it
("…*"); a literal asterisk in that position is written \*. Backslash escapes remain active inside quotes (|
and \ must still be escaped). An unbalanced quote, or text between the
closing quote and the next separator, is an error (E09). Quoting and escaping
are equivalent notations for the same value; the canonical serializer emits
the escaped form.
3.5 Whitespace#
Leading and trailing whitespace of a field, of a list element and of a header value is not significant and MUST be trimmed. Internal whitespace is preserved. Scalar fields are never quoted.
4. Grammar#
document ::= header ( LF record )* LF?
header ::= prefix ( "|" entry )*
entry ::= key "=" value
prefix ::= [A-Za-z] [A-Za-z0-9_-]*
key ::= [A-Za-z_] [A-Za-z0-9_]*
record ::= value ( "|" value )*
value ::= ( char | escape )* -- may be empty
list ::= ( element ( SEP element )* )? -- interpretation of a list-typed value
element ::= ( bare | quoted ) "*"?
bare ::= value -- must not start with an unescaped '"'
quoted ::= '"' ( qchar | '""' | escape )* '"'
qchar ::= any Unicode scalar except '"', "|", "\", LF
escape ::= "\" ( "|" | SEP | "*" | '"' | "\" | "n" )
char ::= any Unicode scalar except "|", "\", LF
SEP is the contract's list separator. The grammar is regular at the line
level: a record is recognised by a single left-to-right pass that resolves
escapes and splits on unescaped |; a list-typed field is then split on
unescaped SEP. No look-ahead beyond one character is required, so parsing is
deterministic and linear in the length of the line.
5. Header#
The header is prefix|key=value|key=value….
prefixnames the contract (family). It MUST match a registered contract.nMUST be present and MUST equal the number of record lines (E03/E04).vMAY be present and names the contract version (default 1).- Other keys are typed by the contract (scalar, list or tuple). Unknown keys are accepted and kept as strings, which lets producers attach provenance (model, date, language, topic) without changing the contract.
- A header key MAY act as a count key: a list field whose contract entry
declares
count_key: "k"MUST have exactlykelements in every record (E07). This turns a delimiter collision inside a list into a detectable error.
6. Records and field types#
A contract defines an ordered list of core fields followed by an ordered
list of extension fields. A record MUST contain every core field (E05) and
MAY contain a prefix of the extension fields; missing extensions are null. If
the header v is less than or equal to the contract version, a record MUST NOT
contain more fields than the contract declares (E05). If the same-prefix header
declares a higher v, the parser MUST lexically validate the complete record,
decode the known field prefix, and ignore only unknown trailing fields.
| Type | Text form | Canonical JSON | Notes |
|---|---|---|---|
str |
literal text | string | |
int |
-?[0-9]+ |
integer | optional min/max (E13) |
float |
JSON number | number | integral values may omit .0 |
bool |
true / false |
boolean | 1/0 accepted on input |
enum |
one of the declared values | string | E10 otherwise |
list<T> |
e1,e2,… |
array | min/max/count_key arity (E07) |
mlist<T> |
e1*,e2,… |
array plus a sibling selected key |
marker rule: exactly_one (default), at_least_one, at_most_one, any (E08) |
tuple(a:T,b:U,…) |
a,b,… |
object {a:…, b:…} |
fixed arity (E07); one level of nesting without nesting syntax |
An empty field denotes null and is valid only for optional fields (E06). A
field declared unique MUST NOT repeat its value within a document (E11).
The marked list is the idiom that replaces a separate "answer" field: the
selected element carries a one-character suffix, keeping the selection attached
to its content. For exactly_one/at_most_one the canonical selected value
is an index (or null); for at_least_one/any it is an ascending list of
indices.
7. Canonical object#
A parser MUST produce:
{ "prefix": "<prefix>",
"header": { "n": <int>, "v": <int>, ...typed header entries... },
"<records_key>": [ { "<field>": <value>, ... }, ... ] }
records_key is declared by the contract (e.g. items, cases). A marked
list options with selection key correct yields two sibling keys
"options": [...] and "correct": <index>. A tuple yields a nested object.
Canonical numbers compare numerically (-1 ≡ -1.0).
8. Validation and error codes#
Validation is local (each record is checked on its own line) and global (count and uniqueness). A parser MUST report the 1-based line number of every error. Strict parsers collect all errors and reject the document; lenient parsers return the valid records together with the error list, which enables partial recovery of long generated outputs.
| Code | Condition |
|---|---|
| E01 | no header line |
| E02 | header prefix does not match the contract |
| E03 | header lacks n |
| E04 | number of record lines ≠ n |
| E05 | record has fewer fields than the core, or has excess fields without declaring a document version newer than the contract |
| E06 | scalar value does not match its type, or a required value is empty |
| E07 | list / tuple arity outside min/max, or ≠ count_key, or ≠ tuple size |
| E08 | marker count violates the marked-list rule |
| E09 | invalid escape sequence or trailing backslash |
| E10 | value not in the enumeration |
| E11 | duplicate value in a unique field |
| E12 | malformed or missing required header entry |
| E13 | numeric value outside min/max |
| E20 | the contract itself is invalid |
| E21 | fork invariant violated |
9. Round-trip#
For every contract C and every canonical object o valid under C:
parse(dumps(o, C), C) = o and dumps(parse(t, C), C) = t for every document
t emitted by the serializer. This property — not compactness — is the
acceptance criterion of a .mini family: a compression that does not round-trip
is an abbreviation, not a serialization.
10. Forking protocol#
A fork is a new contract derived from a parent. It keeps parsability by
construction if it satisfies five invariants, all machine-checkable by the
reference registry (mini check-forks):
| # | Invariant | Rule |
|---|---|---|
| I1 | Local line | one line = one complete, independently valid record |
| I2 | Header | prefix and n are mandatory; required header keys of the parent stay required |
| I3 | Stable core | the child's field list starts with the parent's full field list (core + extensions), same names, same order, same types, same list separator |
| I4 | Tail extension | new fields are appended after the inherited ones and are optional |
| I5 | Round-trip | the child ships fixtures (valid.mini ↔ canonical.json, escaping.mini, negative cases) that pass §9 |
Consequences. An older parser reads later documents of the same prefix when
the header declares a higher v: it validates the complete line, decodes the
fields it knows, and ignores the unknown tail. A fork uses a different prefix:
the record is first parsed with the child contract chosen by record dispatch,
after which the application MAY project its inherited prefix to the parent
schema; this is not direct parsing of the child document with the parent
contract. The child contract also accepts records without its optional
extensions when they are emitted under the child prefix. Reordering, retyping
or removing an inherited field is a breaking change and MUST be published under
a new prefix, never as a new version of the same prefix. Compatible growth
(appending extensions or optional header keys) increments v.
A fork is published as a folder forks/<prefix>/ containing contract.json,
README.md and fixtures/. The specification block that a generative model
needs to produce the fork is derived mechanically from the contract
(mini prompt <prefix>); a fork therefore consists of data, not code.
11. Design rationale#
- Position instead of names. In a closed domain both sides know the
schema; repeating
"statement","options","correct"in every record is pure overhead. Moving the schema to the contract, declared once, is what makes the per-record cost approach the content itself. - One byte, one role.
|never appears inside lists, the separator never appears at field level, and*is only a suffix. This strict separation of levels is what keeps the grammar regular and the parser one-pass. - Two equivalent protections for the list separator. Version 0 (2026-06) used CSV-style quoting only; generative validation showed that a weaker model sometimes omitted the quotes and produced silent delimiter collisions. A draft of version 1 replaced quoting by backslash escaping only; a second round of validation showed that the same class of model ignores an unfamiliar escape but reliably applies CSV quoting, which it has seen in vast amounts of training data. Version 1.0 therefore accepts both notations (§3.3, §3.4), emits the escaped form canonically, and adds the count key of §5, which turns any residual collision into a detectable arity error instead of a silent corruption.
- Marker as suffix. The selection travels with its content, which avoids index/content misalignment during generation and allows local verification.
- Append-only evolution. The same discipline used by binary protocols and
evolvable schemas (new fields only at the end; older readers ignore the tail
only when the same prefix declares a later
v) gives forward and backward compatibility without additional negotiation.
12. Limitations (by design)#
.mini does not represent deep hierarchies, many-to-many relations inside a
record, heterogeneous records in one document, or schemas that evolve during a
conversation. Relations are expressed with the relational pattern (a second
family whose records reference identifiers of the first, e.g. card records
pointing to a items) or with one-level tuple fields. Formal interoperability
standards (e.g. QTI for assessment) remain the target of the canonical object,
not of the wire format. Token savings are tokenizer- and language-dependent;
the reference benchmark reports the tokenizer, corpus, serializers and baseline
of every figure.