Conformidad que rechaza
Una prueba razonable separa una ontología de un diagrama con etiquetas: ¿puede el artefacto prohibir algo? Una ontología sin axiomas, sin validación, sin intención arquitectónica es un glosario dibujado como grafo. Describe, pero no puede rechazar. Si Vercy es solo eso, la crítica acierta.
Por eso esta página responde a la prueba directamente, con un sí y una demostración que usted puede ejecutar. La conformidad en Vercy se impone, no decora. Existe un programa que lee un modelo, lo declara inválido y termina con código distinto de cero nombrando la regla que se ha roto. Abajo está exactamente qué programa, exactamente qué regla y un rechazo resuelto paso a paso.
La conformidad es una barrera, no una descripción
El registro vivo, publicado en github.com/ver-cy/registry, es la instancia en marcha del perfil ELMM. Su vía de escritura es un pull request, y la barrera de admisión en esa vía es la integración continua: ci/run.py ejecuta siete comprobaciones fail-closed en orden, y una sola comprobación en rojo bloquea la fusión. Fail-closed significa que el valor por defecto es el rechazo: un modelo se admite solo si sobrevive a todas las comprobaciones, no se admite mientras nadie objete.
Las siete comprobaciones, cada una terminando con código distinto de cero y una regla normativa nombrada en la primera violación:
check_schema(validación de esquema V0, ELMM-I8, ELMM-I14): cada entrada valida contra el esquema del perfil de nodo del registro, y la proyección de sus campos upstream valida contra el esquema de entrada upstream sin modificar; cada arista valida contra el esquema de aristas. Un registro con un campo obligatorio ausente, una identidad malformada o un valor fuera de un vocabulario controlado se rechaza aquí.check_graph(integridad del grafo MMDG): seis subreglas, listadas en la sección siguiente.check_resolve(determinismo y repetición del resolutor, ELMM-I23, ELMM-I26, ELMM-I30): el resolutor se ejecuta dos veces con la misma entrada de reloj fija y debe producir una salida idéntica byte a byte; el paquete de contexto emitido y el Twin Composition Snapshot deben validar contra sus esquemas; y donde exista una fixture comprometida, la salida nueva debe igualarla byte a byte. Un resolutor que lee el reloj del sistema, sale a la red o se desvía de sus fixtures no pasa.check_zero_change(registro sin cambios en el núcleo, ELMM-I7, ELMM-I44): registrar un modelo nuevo de cualquier rol y cualquier dominio debe tocar únicamente datos del registro. La comprobación clona el árbol, inyecta un modelo nuevo más una arista, ejecuta la barrera, resuelve una tarea que alcanza el nuevo tipo y calcula el hash deschema/yresolver/antes y después. Un diff de núcleo no vacío es un fallo de conformidad: significaría que la admisión exigió cambiar el núcleo.check_facets(pertenencia a facetas y frescura del índice, ARCH-017): todo código de industria y de clúster en una entrada está en su vocabulario; todo Grupo externo está mapeado; el catálogo generado y el índice unificado se regeneran idénticos byte a byte. Un vocabulario desviado, un Grupo sin mapear o un archivo generado editado a mano no pasan.check_instantiations(integridad de la transformación B6): cada instanciación externa-a-interna comprometida se regenera idéntica byte a byte, su entrada valida contra el esquema de nodo y su manifiesto contra el esquema de manifiesto, y el control de titularidad IC-1 se cumple.check_conventions(convenciones de andamiaje, S1, S2): el esquema de cabecera de artefacto es un JSON Schema válido, el readme de convenciones documentadas no está vacío, y ningún nombre de archivo bajoentries/,mmdg/oschema/lleva una fecha. La regla de no poner fechas en los nombres de archivo y las convenciones de cabecera se imponen aquí.
Esto no es una promesa sobre el comportamiento: es el comportamiento. La barrera es el código, y el código es público.
La comprobación de integridad del grafo, regla por regla
check_graph es donde ocurren la mayoría de los rechazos estructurales. Impone seis reglas, cada una con su propio diagnóstico y su propio identificador ELMM:
- Un solo nodo por identidad principal (ELMM-I17): no hay dos registros que compartan un id de registro.
- Integridad referencial (ELMM-I19): cada extremo de arista,
fromyto, es el id de una entrada registrada. - Cobertura de exportación (ELMM-I11, ELMM-I19): todo tipo que nombra una arista aparece en los
exportsdel registro destino. El grafo es calculable estáticamente solo a partir de los registros, así que una referencia a un tipo que el destino no exporta se rechaza antes del momento de resolución. - Acuerdo del mínimo declarado (ELMM-I11): donde el
requiresde un registro nombra el mismo destino y tipo que una arista, eldeclared_minde la arista es igual a esemin_version. Bajo Selección de Versión Mínima la arista es la única entrada del resolutor, así que registro y arista deben coincidir. - Aislamiento del núcleo (ELMM-I18): ninguna arista
composessale del nodo del núcleo. El núcleo no orquesta nada: su conocimiento de los modelos viene del registro, nunca de aristas salientes. - Aciclicidad (ELMM-I16): el subgrafo
composeses un grafo dirigido acíclico.
Cada una de estas puede, por sí sola, poner en rojo un árbol verde.
Un rechazo resuelto paso a paso
Tome la regla 3, cobertura de exportación, y rómpala a propósito.
Suponga que el único Panorama gobernado, vercy.plmm, declara que referencia un tipo budget-line propiedad del modelo de unidades organizativas vercy.oumm. En mmdg/edges.json un autor añade:
{
"from": "vercy.plmm",
"to": "vercy.oumm",
"edge_type": "references",
"declared_min": "0.1.0",
"compositional_role": "R4",
"kinds": ["budget-line"]
}
La arista es válida según el esquema: tiene todos los campos obligatorios, así que check_schema la deja pasar. Ambos extremos están registrados, así que la integridad referencial pasa. Se lee como una afirmación perfectamente bien formada. Pero vercy.oumm no exporta budget-line. Sus exportaciones son org-unit, reporting-line, established-position y unit-mandate; budget-line no está en ninguna. La arista afirma una dependencia de un significado que el destino nunca publicó.
check_graph rechaza. La subcomprobación de cobertura de exportación recorre cada arista, toma el conjunto exports del destino y falla en el primer tipo nombrado que no esté en él. Emite el conjunto completo de exportaciones del destino, ordenado, para que quien lo lea vea exactamente qué se publicó y qué no. La ejecución termina con código distinto de cero y este diagnóstico:
check_graph: FAIL
edge #N (vercy.plmm -references-> vercy.oumm) references kind 'budget-line'
which is not in vercy.oumm exports ['established-position', 'org-unit',
'reporting-line', 'unit-mandate'] (ELMM-I11, export coverage)
La fusión queda bloqueada. No señalada, no advertida: bloqueada. ci/run.py devuelve un código de salida distinto de cero y el pull request no puede aterrizar. Para arreglarlo, el autor o hace que vercy.oumm exporte de verdad budget-line, que es un cambio real que el modelo propietario debe publicar y sostener, o deja de reclamar una referencia que nunca le fue concedida. El registro no dejará que un modelo dependa de un significado que otro modelo no ha exportado. Eso es algo que el artefacto prohíbe.
La misma forma de rechazo existe en toda la barrera. Una composición cíclica, en la que un Panorama compone un modelo que transitivamente lo compone de vuelta, se rechaza por aciclicidad (ELMM-I16). Una arista hacia un modelo inexistente se rechaza por integridad referencial (ELMM-I19). Un mínimo en requires que discrepe del declared_min de su arista se rechaza por acuerdo del mínimo declarado (ELMM-I11), porque de lo contrario el resolutor elegiría una versión contra la que el registro nunca se validó. Un registro que forzase una edición del núcleo se rechaza por la garantía de cambio cero (ELMM-I7). Un nombre de archivo con fecha se rechaza por la convención de nombres (S1). Un resolutor cuyas dos ejecuciones divergen se rechaza por determinismo (ELMM-I23). En cada caso la regla es la razón, el identificador está en el mensaje y el código de salida no es cero.
El patrón es lo importante: cada rechazo nombra una regla normativa a la que se puede apuntar el modelo, con la que se puede discutir y contra la que se puede corregir. No hay rechazo silencioso ni rechazo por gusto. Rompa la regla, obtenga el código de salida, lea el identificador.
Más allá del registro: los validadores de modelo
El registro controla las relaciones entre modelos. Cada modelo lleva sus propias barreras. El Meta-Modelo Colectivo, publicado y versionado en github.com/ver-cy/collective-meta-model, incluye un validador de nodo que ejecuta las barreras de V0 a V2 más las comprobaciones específicas del CMM y rechaza una instancia rota: un miembro sin colectivo, una concesión de autoridad sin otorgante, un mandato que no cierra ningún bucle de rendición de cuentas. El registro de esa modelo consigna la validación V2 como su nivel de conformidad, y el registro vale lo que valga el validador que lo respalda. El validador es la razón por la que el nivel es una afirmación y no un adorno.
El límite honesto
Hay que decir tres cosas con claridad.
Primero, hoy esto es conformidad a nivel de instancia de modelo. Las comprobaciones rechazan registros inválidos, aristas inválidas, resolución no determinista e instancias de modelo inválidas frente a sus validadores. Se ejecutan en CI en la vía de escritura y cualquiera puede ejecutarlas localmente: clone el registro de github.com/ver-cy/registry, ejecute python ci/run.py, rompa una regla y vea cómo falla. Eso es real, y basta para responder a la prueba.
Segundo, un servicio público de validación alojado, una página o un endpoint donde alguien de fuera suelte un modelo arbitrario y obtenga un veredicto sin clonar nada, todavía no existe. Es un punto abierto, y así se nombra. Hasta que salga, el rechazo es reproducible pero no está a un clic para un desconocido.
Tercero, quien clone el registro para reproducir el rechazo encontrará que una entrada de implementación de referencia sigue llevando un identificador afiliado a una marca comercial, anterior a la pasada de neutralidad. Es inerte para la demostración anterior, que usa solo los identificadores neutrales vercy.*, pero neutralizar esa entrada y su arista es un punto abierto nombrado en el registro.
Ninguna de estas salvedades cambia la respuesta a la prueba. Mientras un artefacto no pueda rechazar, es un glosario. Aquí está el rechazo: una comprobación nombrada, una salida distinta de cero, una regla normativa y una fusión que no ocurre. Ejecútelo usted mismo en la CI del registro y en los validadores de modelo. Ambos son públicos.