Traducción automática, no revisada por un hablante nativo. El inglés es la referencia.

Validación y evidenciasEditar en GitHubFuente: docs/REPRODUCIBILITY.md

Reproducibilidad y procedencia

Kshana está construido para ser reproducible: las mismas entradas producen los mismos resultados, y los artefactos de compilación pueden rastrearse hasta la fuente que los produjo. Este documento establece con exactitud qué se garantiza, qué no y cómo se hacen cumplir las garantías.

Garantías de determinismo#

El motor no tiene reloj de pared, ni dependencia del hilo de ejecución, ni aleatoriedad sin semilla. Todo proceso estocástico se conduce con un flujo ChaCha8Rng con clave en el seed del escenario, extraído en un orden fijo. Consecuencias:

Propiedad Garantizado Se hace cumplir mediante
Mismo escenario, misma máquina → result.json idéntico byte a byte Sí scripts/check-reproducible.sh (ejecuta dos veces el escenario de referencia y compara el SHA-256 (SHA: Secure Hash Algorithm))
Mismo escenario → cifras de mérito idénticas campo a campo Sí, por plataforma tests/golden.rs fija cada cifra de mérito (FoM) de los cuatro escenarios de referencia
El hash de entrada del escenario (scenario_hash) es independiente de la plataforma Sí SHA-256 direccionado por contenido del escenario canónico, fijado en tests/golden.rs
Huella de entrada + forma de la salida idénticas entre SO (sistemas operativos) Sí tests/cross_platform_golden.rs fija un SHA-256 exacto por escenario (diez escenarios, un archivo .sha256 cada uno en tests/golden/), comprobado en la matriz de CI (integración continua) de 3 SO
Los valores de salida coinciden entre SO (ubuntu/macOS/Windows) Sí, hasta 1e-6 el trabajo de CI reproducibility-matrix ejecuta golden.rs (1e-6), sgp4_verification.rs (2e-5 km) y determinism.rs en los tres SO
Una trama de mensaje de navegación de órbita terrestre baja (LEO) son los mismos bytes en todas las plataformas y en todos los perfiles de compilación, incluida la compilación WebAssembly (WASM) Sí src/portable_math.rs (toda función trascendente y toda desviación normal del tipo de escenario leo-navmsg pasa por el crate libm de Rust puro); leo_navmsg::tests::the_encoded_frame_is_the_same_bytes_on_every_platform fija una trama completa sin condicionarla a la plataforma
Los sorteos de índices con semilla (remuestreo bootstrap, barajados) son iguales en destinos de 32 y de 64 bits Sí portable_math::uniform_index muestrea siempre como u64; fijado en portable_math::tests
La misma cadena de herramientas en todas partes Sí rust-toolchain.toml fija el canal; scripts/check-toolchain.sh hace fallar la compilación ante una deriva; la CI y la publicación fijan la misma versión
El mismo conjunto de dependencias Sí Cargo.lock está incorporado al repositorio y cargo metadata --locked se usa para el SBOM (lista de materiales de software)

Toda ejecución por línea de comandos escribe además un registro de reproducibilidad en su informe (<scenario>.report.json y .report.html): la versión del motor, el SHA-256 del archivo de escenario y del documento de resultado, la semilla, la plataforma y el comando exacto, que tests/advanced_report_cli.rs vuelve a ejecutar hasta obtener un resultado idéntico byte a byte. El informe es en sí una función pura de la ejecución: dos ejecuciones de scenarios/clock-holdover.toml escriben el mismo report.json byte a byte. Véase REPORTS.md.

La salvedad entre plataformas (y cómo la tratan los golden)#

Los resultados numéricos son idénticos bit a bit en una plataforma dada, pero pueden diferir en las últimas unidades en el último lugar (ULP) entre plataformas. La causa es la biblioteca matemática de la plataforma: IEEE-754 (IEEE: Institute of Electrical and Electronics Engineers) no exige que sqrt, ln, exp y similares estén correctamente redondeadas, de modo que Linux (glibc, la biblioteca C de GNU), macOS y Windows pueden devolver cada uno un último bit distinto. En una ejecución larga, estas diferencias de ~1e-16 se acumulan hasta quizá ~1e-12 relativo.

Dos cosas hacen que esa diferencia en el último lugar sea mayor de lo que empieza siendo, y ambas están medidas y no supuestas. Un integrador adaptativo elige su paso siguiente a partir de la estimación de error mediante una raíz quinta, de modo que una unidad en el último lugar cambia la secuencia de pasos y las dos plataformas solo coinciden entonces hasta la tolerancia de integración. Un estimador iterativo (un ajuste de mínimos cuadrados, un filtro de determinación de órbita) puede seguir un camino distinto hasta la convergencia. Los tipos de escenario construidos sobre cualquiera de los dos pueden diferir entre plataformas en más de 1e-6 en campos individuales; src/test_support.rs registra el mismo régimen para las pruebas unitarias.

El perfil de compilación importa del mismo modo, en una misma máquina. Una compilación optimizada en macOS fusiona un seno y un coseno de un mismo argumento en una sola llamada a la rutina combinada del sistema, cuyo seno difiere del sin aislado en el último bit para 379 de 200.000 argumentos; una compilación sin optimizar hace las dos llamadas. Medido en aarch64 macOS sobre los 138 archivos de escenario, una compilación de depuración y una de publicación de una misma fuente dan documentos de resultado idénticos byte a byte en 102. Los otros 36 difieren en los últimos lugares: 28 dentro de 1e-6, uno (leo-ppp-convergence) en 2.8e-6, y siete campañas solo en los resúmenes de sus ejecuciones miembro; ninguno difiere en una etiqueta, un recuento o un veredicto. La garantía de identidad byte a byte anterior es, por tanto, para una compilación: el mismo binario dos veces.

Los sorteos normales con semilla son una tercera fuente, mucho más rara: el muestreador llama a la exponencial y al logaritmo del anfitrión en sus ramas raras, y aproximadamente un sorteo de cada millón difiere en el último bit entre la compilación nativa y la WASM.

Cuando una salida es discreta, una diferencia en el último lugar no es aceptable en absoluto, y el tipo de escenario se calcula con src/portable_math.rs en lugar de con la biblioteca del anfitrión. El tipo de escenario leo-navmsg es el primero: su trama binaria son enteros transmitidos, y el mismo escenario llegó a codificarse en tres tramas distintas: en una compilación de publicación, en una de depuración de la misma fuente y en el navegador. Ahora son los mismos bytes en las tres.

Por eso, las pruebas golden no fijan un único hash multiplataforma de la salida en coma flotante: sería frágil y haría fallar compilaciones correctas en otro SO. En su lugar:

  • tests/golden.rs fija cada cifra de mérito con una tolerancia relativa de 1e-6, cuatro órdenes de magnitud más ajustada que cualquier regresión real (que mueve un valor en porcentajes enteros) y aun así mucho más holgada que la fluctuación de la biblioteca matemática (libm) entre plataformas. Los campos acotados por la cuadrícula (segundos de holdover) y los campos exactamente cero se fijan de forma exacta.
  • scenario_hash, un hash de contenido de las entradas, es independiente de la plataforma y se fija de forma exacta.
  • tests/cross_platform_golden.rs fija un SHA-256 exacto, incorporado por escenario en tests/golden/, sobre la proyección que sí es idéntica entre plataformas: la huella de entrada más la forma de la salida (nombres de campo, anidamiento, tipos de hoja, longitudes de matriz; fijados por aritmética determinista de cuadrícula, nunca los valores en coma flotante). Esto detecta con exactitud las regresiones estructurales, mientras que las tolerancias anteriores detectan las regresiones de valores.
  • scripts/check-reproducible.sh exige una salida idéntica byte a byte entre dos ejecuciones en la misma máquina (la garantía de determinismo).
  • El trabajo de CI reproducibility-matrix ejecuta las cuatro pruebas anteriores (cross_platform_golden, golden, determinism, sgp4_verification) en ubuntu-latest, macos-latest y windows-latest, de modo que la reproducibilidad entre plataformas se afirma en cada push (los golden de forma y de entrada, de forma exacta; la numérica, hasta 1e-6; y los estados SGP4 (Simplified General Perturbations 4), hasta 2e-5 km) en lugar de depender de un único SO.

Si necesita regenerar las cifras fijadas (p. ej., tras un cambio intencionado del modelo), ejecute cada escenario de referencia y copie los valores de FoM impresos en tests/golden.rs, y anote después el cambio en CHANGELOG.md.

Lista de materiales de software (SBOM)#

scripts/gen-sbom.sh emite un SBOM CycloneDX 1,5 que enumera cada crate que se distribuye en un artefacto de kshana, con su versión exacta, su origen y su licencia. Es un generador sin dependencias construido sobre cargo metadata --locked (de modo que funciona solo con la cadena de herramientas) y recorre el grafo de resolución desde el paquete kshana a través de las dependencias normales y de compilación únicamente. Las dependencias de desarrollo (crates solo de pruebas, como sgp4) se excluyen porque ningún artefacto las contiene.

El grafo es la unión de los conjuntos de características con los que se construyen los artefactos distribuidos: la compilación por defecto (biblioteca y CLI (interfaz de línea de comandos)), --features python (la wheel de PyPI (Python Package Index), cuya cadena pyo3 es su frontera de interfaz de funciones externas) y --features wasm (el paquete npm, que lleva este mismo SBOM dentro de su tarball). Se incluyen las dependencias condicionadas por plataforma para todos los destinos, ya que las wheels se distribuyen para varios sistemas operativos y el paquete npm tiene como destino WebAssembly. Un solo documento cubre los tres artefactos, de modo que para cualquiera de ellos es un superconjunto. Actualmente enumera 107 componentes; el recuento está fijado en tests/fixtures/reproducibility_software_assurance/. El servidor independiente kshana-mcp tiene su propio manifiesto y no lo describe este SBOM.

La salida es determinista: el mismo conjunto de dependencias da un documento idéntico byte a byte, incluido un número de serie derivado de la lista ordenada de paquetes y no de una marca de tiempo.

El flujo de trabajo de publicación genera el SBOM (kshana-sbom.cdx.json) y lo adjunta a cada versión etiquetada; el flujo de trabajo de distribución también lo incluye junto a las wheels de PyPI y dentro del paquete npm.

Procedencia de la compilación#

El flujo de trabajo de publicación produce una atestación de procedencia de compilación SLSA (Supply-chain Levels for Software Artifacts) (actions/attest-build-provenance) que cubre todos los archivos que adjunta a la Release de GitHub: los binarios de línea de comandos de cada plataforma, el binario del servidor kshana-mcp, el SBOM, el resumen de validación y SHA256SUMS. Un consumidor puede verificar, con gh attestation verify, que los artefactos fueron construidos por el flujo de trabajo de publicación de este repositorio a partir de esta fuente, cerrando la brecha entre «aquí hay un binario» y «aquí hay un binario que puedo rastrear hasta su fuente». Por ejemplo, para el SBOM de v0.28.0:

curl -sLO https://github.com/AshfordeOU/kshana/releases/download/v0.28.0/kshana-sbom.cdx.json
gh attestation verify kshana-sbom.cdx.json --repo AshfordeOU/kshana