Esquema de resultados: cómo leer un *.result.json de Kshana
Cada ejecución escribe, junto al escenario, un artefacto JSON (JavaScript Object Notation) versionado y autodescriptivo. Esta página es la guía escrita a mano para quien lee la envoltura de intercambio y las estructuras de resultados de reloj y órbita: la unidad de cada campo, dónde se calcula en el código fuente y cómo leerlo. El tipo canónico es RunResult en src/report.rs; las figuras de mérito son FoMScores en src/fom.rs.
No es la referencia completa de campos. El motor despacha sobre muchos más tipos que estos dos, y cada uno emite su propio paquete. La referencia completa (unidad, clase de procedencia y definición de cada campo numérico de cada tipo integrado) se genera, no se escribe a mano: véase Unidades y procedencia, por campo, de cada tipo más abajo.
Envoltura de intercambio (KIF, el Formato de Intercambio de Kshana): reconocer un artefacto y comprobar su versión#
Los artefactos de Kshana pueden envolverse en una envoltura de intercambio neutra y autodescriptiva para que una herramienta de terceros reconozca el archivo y decida si puede leerlo antes de comprometerse con un esquema de carga útil. El tipo canónico es Envelope en src/interchange.rs.
| Clave | Tipo | Significado |
|---|---|---|
format |
cadena | Siempre "kshana-interchange" (FORMAT_TAG): cómo reconoce una herramienta ajena un artefacto de Kshana. |
schema_version |
cadena | La versión de esquema MAJOR.MINOR (SCHEMA_VERSION, la única fuente de verdad de todo el crate). |
kind |
cadena | Tipo de artefacto, p. ej. "scenario", "run-result", "trade-study": permite a un consumidor encaminarlo sin analizar el cuerpo. |
engine_version |
cadena | Versión del crate (Cargo.toml) que produjo la carga útil. |
payload |
objeto | El artefacto envuelto como JSON canónico (un Scenario, un RunResult, …). |
Contrato de compatibilidad. Las versiones son MAJOR.MINOR. Los campos nuevos se añaden con #[serde(default)] (la disciplina aditiva), de modo que un lector puede analizar cualquier artefacto de la misma versión mayor y de una menor igual o anterior (Compatible). Una versión menor estrictamente más reciente (ForwardIncompatible) puede contener campos que este lector no puede atender, y una versión mayor distinta (MajorIncompatible) es una ruptura estructural: Envelope::parse rechaza ambas, pues valida la etiqueta de formato y la versión en la frontera en lugar de analizar mal en silencio una entrada ajena.
Determinismo. La envoltura no lleva marca de tiempo: la promesa de reproducibilidad de Kshana (scenario + seed + engine_version reproduce una ejecución) lo exige. La procedencia reside en engine_version y en el propio scenario_hash de la carga útil.
Una lectura tipada (Envelope::payload_as::<T>()) funciona con cualquier carga útil que implemente Deserialize (p. ej. Scenario). Los artefactos de resultados son solo de serialización por diseño y se leen como el valor JSON en bruto de payload.
Nivel superior (paquetes de reloj y órbita)#
| Clave | Tipo / unidad | Significado | Fuente |
|---|---|---|---|
schema_version |
cadena | Versión del esquema de resultados (independiente de la versión del motor). | report.rs |
engine_version |
cadena | Versión del crate (Cargo.toml) que produjo el archivo. |
report.rs |
scenario_hash |
cadena hexadecimal | SHA-256 (SHA: Secure Hash Algorithm) del JSON canónico del escenario: la ejecución es reproducible a partir de scenario + seed + engine_version. |
report.rs:hash_scenario |
seed |
u64 | Semilla del RNG (generador de números aleatorios) de la ejecución cuántica (la clásica usa seed + 0x9e3779b97f4a7c15). |
run.rs |
threshold_ns |
nanosegundos | La especificación de temporización: un error dentro de ±threshold_ns está «dentro de especificación». |
escenario |
quantum |
objeto (ClockRun) |
La ejecución del sensor cuántico (véase más abajo). | report.rs |
classical |
objeto (ClockRun) |
La ejecución del sensor clásico, a efectos de comparación. | report.rs |
units |
objeto | Mapa de unidad y procedencia por campo de este documento, indexado por ruta de campo. Véase §Unidades y procedencia más abajo. | field_schema.rs:units_block |
evidence |
objeto | (0,40) La etiqueta de evidencia de la ejecución: tier (VALIDATED, MODELLED o PARTNER: el estado más débil entre las filas, de modo que nunca afirma más que su fila más débil), matrix (docs/VERIFICATION-MATRIX.md), id_rule y rows, una por cada fila de la matriz de verificación que ejercitó la ejecución (las filas que enumera su informe avanzado, de advanced_report::KIND_CAPABILITIES): id (VM- y los primeros 8 dígitos hexadecimales del SHA-256 del texto del requisito de la fila), requirement y status, todo leído de la matriz, nada escrito a mano. La añade api::run_toml al resultado de cada tipo de escenario, antes del bloque figure_tiers final cuando lo hay (ese bloque sigue siendo la última clave); evidence_label::strip_json la elimina byte por byte. El SVG del gráfico y la tabla CSV de la misma ejecución llevan la misma etiqueta (<metadata id="kshana-evidence"> y una línea visible bajo el gráfico; líneas de comentario # evidence: por delante del CSV). Los miembros de campaña incrustados en el resultado de otro tipo de escenario no llevan ninguna: la lleva el documento exterior. No lleva números. |
evidence_label.rs |
figure_tiers |
objeto | El nivel de verificación de cada figura de mérito informada, y siempre la última clave del documento. figures enumera una entrada por cada figura presente: path (p. ej. quantum.fom.timing_p95_ns), tier (VALIDATED = comprobada frente a una referencia externa independiente, MODELLED = de primeros principios, con pruebas internas), requirement (la fila de la matriz de verificación de la que se lee el nivel) y applicable. applicable es false, con un reason, para security en todo escenario sin ataque configurado: la cota permanece en fom.security, pero no responde a ninguna pregunta que plantee el escenario. untiered enumera toda figura que no pertenece a ninguna fila de la matriz (las figuras de posición de hybrid y fusion), en lugar de asignarle un nivel. Lo emiten los tipos clock (ejecución única y conjunto de Monte Carlo), orbit, hybrid y fusion, que lo construyen dentro de su ejecución, y (0,36, RM-04) todos los demás tipos para sus figuras principales, añadido tras la ejecución a partir de la tabla por tipo fom_label::kind_figures; api::without_figure_tiers lo retira y devuelve el documento sin niveles byte a byte. No lo emite lunar-station-coverage, cuyo resultado es una predicción congelada y preregistrada (docs/predictions/lunar-reference-station.md): ese tipo no tiene figure_tiers hasta que una nueva predicción fechada la sustituya. Tampoco lo emiten leo-ppp, solar-system, optical-atmosphere (0,37; matrices por emplazamiento), sweep y sweep-nd, que no tienen una figura principal escalar, ni lunar-attack-surface, cuyo documento es JSON compacto (fom_label::KINDS_EXCLUDED_FROM_FIGURE_TIERS da cada motivo), ni los documentos de miembros incrustados de una campaña. No lleva números. |
fom_label.rs:figure_tiers, fom_label.rs:kind_figure_tiers |
geometry |
objeto, opcional | Resumen de la geometría del paquete de órbita: samples_total, samples_with_fix, sigma_uere_m (m, el presupuesto de error de distancia por satélite modelado), best_pdop / median_pdop (adimensionales) y best_position_sigma_m / median_position_sigma_m (m, PDOP (dilución de la precisión de posición) × sigma_uere_m). Solo el paquete de órbita. |
orbit.rs |
eci_track |
matriz de [x, y, z] km, opcional |
Trayectoria inercial centrada en la Tierra, propagada, de la nave del usuario, una entrada por cada instante muestreado. Solo el paquete de órbita; se omite en los demás. Solo de salida: no se incluye en el hash. | report.rs |
meta |
objeto (StudyMeta), opcional |
Metadatos aditivos del informe (título del estudio, sello de generación, autor, aviso legal). Se omite cuando no existe, de modo que una ejecución sin metadatos es idéntica byte a byte a la salida anterior. Solo de salida: no se incluye en el hash. | report.rs |
ClockRun (cada uno de quantum / classical)#
| Clave | Tipo / unidad | Significado |
|---|---|---|
spec.id |
cadena | Identificador del sensor (p. ej. optical-sr-lattice). |
spec.kind |
cadena | Tipo de modelo (p. ej. clock). |
spec.provenance |
cadena | Cita o fuente de los parámetros del sensor. |
spec.params |
objeto | Los parámetros del modelo utilizados, en bruto. |
series |
matriz de {t, error_ns, gnss} |
Serie temporal por paso: t segundos, error_ns el error de temporización en nanosegundos, gnss uno de nominal/degraded/denied. |
fom |
objeto (FoMScores) |
Las figuras de mérito puntuadas (más abajo). |
adev_curve |
matriz de {tau_s, adev, n_samples, noise, edf, ci_lo, ci_hi} |
Desviación de Allan solapada: tau_s el tiempo de promediado (s), adev la estabilidad fraccionaria de frecuencia adimensional σ_y(τ), n_samples el recuento de solapamiento que hay tras ese punto, noise el tipo de ley de potencias identificado a partir de la pendiente de la MDEV (desviación de Allan modificada) (p. ej. WhiteFm), edf los grados de libertad efectivos específicos del tipo de ruido y ci_lo/ci_hi la banda de confianza del 95% basada en χ² de adev en ese τ. Calculado en allan.rs:overlapping_adev_curve. |
filter_health |
objeto, opcional | Evaluación de la consistencia del filtro de Kalman (NIS/NEES (NIS: innovación normalizada al cuadrado; NEES: error de estimación normalizado al cuadrado) frente a sus bandas χ²), calculada en filter_health.rs; se omite en las ejecuciones que no la evalúan. |
FoMScores (el objeto fom)#
| Campo | Unidad | Significado | Fuente | Salvedad |
|---|---|---|---|---|
timing_rms_ns |
ns | Error de fase del reloj (temporización) RMS (valor cuadrático medio) durante la interrupción. | fom.rs:score |
una métrica de temporización, no de posición |
timing_p95_ns |
ns | Error de temporización del percentil 95 durante la interrupción. | fom.rs:score |
|
holdover_s |
s | Peor caso (el más corto) de deriva dentro de especificación entre los segmentos de interrupción. | fom.rs:worst_case_holdover |
acotado por la malla: una cota inferior a la resolución del paso de tiempo |
resilience_slope_ns_per_s |
ns/s | Tasa de crecimiento de |error| por mínimos cuadrados durante la interrupción. | fom.rs:score |
|
availability |
fracción [0.1] | Fracción de toda la ejecución con una solución dentro de especificación. | fom.rs:score |
|
integrity |
fracción [0.1] o nulo | Autoconsistencia del filtro: fracción de las muestras de la interrupción cuyo error real permanece dentro de la cota k-σ de Kalman. | run.rs |
NO es integridad HPL/VPL/RAIM (HPL: nivel de protección horizontal; VPL: nivel de protección vertical; RAIM: monitorización autónoma de la integridad por el receptor): véase INTEGRITY.md |
security |
fracción [0.1] o nulo | Cota analítica de detectabilidad de spoofing a partir de la estabilidad del reloj. | run.rs + security.rs |
solo tiene sentido con un ataque configurado, por lo que los paquetes de reloj y órbita (que no configuran ninguno) la marcan como applicable: false en figure_tiers y la imprimen como n/a (no attack) en el resumen; no es un detector RAIM multisatélite |
Qué aspecto tiene un buen resultado#
- Un reloj más silencioso (
adev_curvemenor) da unholdover_smás largo y una cota de detectabilidadsecuritymás alta: ese es el contraste entre cuántico y clásico. availabilitycercano a 1,0 significa que el sistema se mantuvo dentro de especificación casi toda la ejecución; durante una interrupción larga disminuye para el reloj más ruidoso.integritycercano a 1,0 significa que la propia cota de incertidumbre del filtro era honesta respecto de su error: una afirmación de autoconsistencia, no una garantía de seguridad de la vida humana.
Otros tipos de escenario#
Cada uno de los demás tipos emite su propia estructura de resultados. Algunas de las más habituales:
- inertial: figuras de mérito en el dominio de la posición en metros (
pos_rms_m,pos_p95_m), de un solo eje (1-DOF (DOF: grado de libertad)) y una sola semilla (véaseCAPABILITY.md). - hybrid / fusion:
timing_spec_nsyposition_spec_men el nivel superior y, por cada lado, las figuras de temporización y de posición de un conjunto de sensores (position_p95_m,position_holdover_sypnt_holdover_s, el tiempo hasta que se supera cualquiera de las dos especificaciones), con un bloquefigure_tierscomo el del paquete de reloj en el que las figuras de posición figuran comountiered. - spoof: desfase de spoofing por paso frente a la cota de detección del reloj, y si el spoofing alcanzó la especificación antes de la detección (
src/spoof.rs). - skyline (
orbiteintegrityconuser_site,gnss-sim,jamming,leo-pvt,leo-pass; presente solo cuando el escenario tiene una sección[skyline], de modo que un escenario sin ella no cambia): un objetoskylinede nivel superior consource(cadena:preset:<name>,preset:<name>+overridesocustom),open_fraction(fracción [0.1] del ángulo sólido del hemisferio superior por encima demax(mask_deg, skyline)) yprovenance(cadena); por muestra,masked_by_skyline(recuento de satélites por encima de la máscara pero tras el horizonte:epochs[]deintegrityyjamming,gnss_measurements[]degnss-sim,joint.epochs[]deleo-pvt); y paraleo-pass,satellites[].pass.epochs_masked_by_skyline(recuento de épocas). Sus unidades y clases de procedencia están en el bloqueunits(src/skyline.rsUNITS;SKYLINE.md).
Para el conjunto exacto de campos de cualquier tipo, consulte su entrada en field-units-schema.json (más abajo), la sección de ese tipo en SCENARIOS.md o la estructura *Result correspondiente en src/.
Otros archivos que escribe una ejecución#
Además de <scenario>.result.json, la CLI (interfaz de línea de comandos) escribe <scenario>.chart.svg, un <scenario>.report.html imprimible y el mismo informe como <scenario>.report.json, cuyo bloque reproducibility registra la versión del motor, el SHA-256 del archivo de escenario, la semilla, la plataforma y el comando exacto (véanse REPORTS.md y REPRODUCIBILITY.md). Los tipos que publican una tabla de reproducibilidad escriben también <scenario>.table.csv (CSV: valores separados por comas). --export escribe archivos de intercambio (véase INTEROP.md) y --animate una animación (véase ANIMATION.md).
Unidades y procedencia, por campo, de cada tipo#
Esta página está escrita a mano y cubre los paquetes de reloj y órbita. La contrapartida legible por máquina cubre todos los tipos integrados:
- En el propio resultado. El documento de resultados de cada escenario lleva un objeto
unitsde nivel superior que asocia la ruta de un campo emitido con{"unit", "provenance", "note"}. La gramática de rutas (una matriz aporta un segmento con sufijo[]compartido por sus filas;*es un comodín de un solo segmento para objetos con claves de datos) y el vocabulario cerrado de procedencia se definen ensrc/field_schema.rs. - Como un único archivo.
field-units-schema.jsones la unión recopilada: para cada tipo, cada campo numérico que emite en una fuente declarada, con su unidad, clase de procedencia, nivel de evidencia y definición y, nombrado en lugar de omitido, cada campo que aún no tiene ninguno. Su bloquecoveragelleva los recuentos.
Ambos los exige tests/field_units_global.rs, que ejecuta todos los tipos registrados y falla si un campo numérico emitido carece de unidad y de clase de procedencia. Los tipos aún no cubiertos se nombran uno a uno en el UNCOVERED_KINDS de ese archivo con el motivo por el que cada uno sigue abierto, y el recuento está fijado de modo que la lista solo pueda reducirse.
Regenere el JSON tras cualquier cambio en la estructura de un informe o en un bloque units:
cargo test --test field_units_global zzz_emit_field_units_schema -- --ignored