Contribuir a Kshana
Gracias por su interés. Kshana aspira a ser una referencia neutral, reproducible y validada con honestidad para el PNT híbrido cuántico/clásico. Las contribuciones se someten a ese listón: corrección, citas y reproducibilidad por encima de la amplitud.
La forma en que se gobierna el proyecto (quién decide, el listón técnico y la frontera entre lo abierto y lo cerrado) está documentada en GOVERNANCE.md.
Desarrollo#
cargo build
cargo test # all tests must pass
cargo clippy # keep it warning-clean
cargo fmt
Los enlaces opcionales a lenguajes están controlados por características y desactivados por defecto (de modo que la compilación anterior y la puerta de auditoría de dependencias nunca los tocan). Para trabajar con ellos:
maturin develop --features python # Python extension (needs maturin)
wasm-pack build --target web -- --features wasm # WebAssembly module
cargo clippy --features python --features wasm # lint the binding modules
Antes de cada commit: el bucle rápido#
Estos tardan segundos. Son un subconjunto del trabajo check de ci.yml, en el mismo orden, de modo que un fallo aquí es un fallo allí:
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
./scripts/check-reproducible.sh # reference scenario is byte-identical across runs
./scripts/check-no-attribution.sh # repo hygiene (see below)
./scripts/check-version-sync.sh # every version surface agrees with Cargo.toml
./scripts/check-doc-coverage.sh # missing-docs ratchet: the count may fall, never rise
- La reproducibilidad es un invariante estricto. Un cambio que haga no determinista
(scenario, seed, version)es un fallo. La aleatoriedad debe pasar por el generador con semilla; las ejecuciones cuánticas y clásicas usan semillas independientes derivadas de forma determinista. - Higiene del repositorio. Los commits y el contenido no deben llevar líneas finales ni pies de atribución de herramientas automáticas, ni nombrar a un asistente de IA como autor en ninguna parte del contenido, los nombres de archivo o el historial. La salvaguarda lo aplica.
Antes de hacer push: la puerta completa#
scripts/gate.sh es la puerta canónica: ejecuta cargo test --all sin abreviar y luego scripts/check-repeatability.sh para volver a ejecutar unas cuantas veces más el conjunto de la biblioteca, porque una condición de carrera por entrelazado de hilos es invisible en una sola ejecución. Solo si tiene éxito escribe .gate-receipt.json (sin seguimiento: estado de la máquina sobre una ejecución, no contenido).
scripts/gate.sh
REPEAT=0 scripts/gate.sh # canonical suite only, no repeatability loop — a LOCAL
# shortcut: the pre-push gate refuses its receipt unless
# KSHANA_MIN_REPEAT_RUNS=0 is also set on the push
TEST_THREADS=6 scripts/gate.sh # cap per-binary concurrency if the run is memory-starved
scripts/check-gate-receipt.sh # is there a valid receipt for the commit being pushed?
scripts/install-gate-hook.sh --check # is the pre-push hook installed on this clone?
Es lenta a propósito (62-79 minutos en el régimen estacionario sano, según la cabecera de scripts/gate.sh, que lleva la cifra vigente) y no hay tiempo límite, porque un tiempo límite lo bastante corto para ser útil mataría una ejecución sana. Una ejecución parcial que salió en verde no es una puerta: los dos defectos para los que existe este mecanismo la atravesaron así.
Quienes trabajan desde una bifurcación no necesitan el gancho del recibo: es una puerta local de mantenimiento, y lo que realmente controla una pull request es la CI. Ejecutar gate.sh antes de abrir una significa simplemente que la CI no le dirá nada que usted no supiera ya.
Añadir o cambiar un modelo de sensor#
- Cada parámetro numérico necesita procedencia. Ponga la cita en la cadena
provenancedel modelo y en el archivo de escenario. Ninguna constante anónima. - Valide frente a la relación estándar, no solo frente a la coherencia interna; por ejemplo, la desviación de Allan para los relojes, el crecimiento del error de navegación a estima de Groves para los inerciales, la conversión temporización→distancia para la transferencia de tiempo. Añada una prueba de que la salida simulada reproduce el valor publicado o de la relación dentro de una tolerancia indicada.
- Sea honesto sobre la madurez. El registro de estado es
src/verification.rs::verification_matrix(): añada o modifique allí la fila, nombre su referencia independiente externa (o diga con claridad que no hay ninguna, lo que la convierte enModelled) y luego regenere los artefactos publicados concargo run --bin gen_validation_artifacts.docs/VERIFICATION-MATRIX.md,docs/MODELLED-RATIONALE.mdyweb/data/verification-matrix.jsonse generan todos a partir de esa función y dicen «do not edit by hand» por una razón. Actualice también la narrativa dedocs/VALIDATION.mdcuando la prosa lo necesite, y etiquete como tales las cifras que son objetivos o resultados de demostradores en tierra.
Pruebas#
- Guiado por pruebas: escriba primero la prueba que falla, con el valor esperado derivado a mano de la física o de la relación antes de implementar.
- Las pruebas deterministas afirman valores exactos (derivados a mano); las pruebas estadísticas afirman una tolerancia indicada y, idealmente, promedian sobre semillas para controlar la dispersión.
Commits y versionado#
- Conventional Commits (
feat:,fix:,docs:,test:,chore:…). - Semantic Versioning. Antes de la 1.0, el esquema de escenarios/resultados puede cambiar; señale los cambios incompatibles.
- Las versiones se cortan con una etiqueta
vX.Y.Z, y la publicación es automática pero ordenada. El flujo de trabajo Auto-tag empuja la etiqueta cuando la CI está en verde enmaincon un aumento de versión. El flujo de trabajo Release ejecuta la verificación completa sobre el commit etiquetado y solo si pasa publica en crates.io, el Python Package Index (PyPI), npm, ghcr.io, el registro del Model Context Protocol (MCP) y el JetBrains Marketplace; después comprueba que cada canal sirve la versión y reconstruye kshana.dev a partir de la etiqueta. Nadie ejecutacargo publisha mano. Los pasos, y cómo reintentar una publicación fallida, están endocs/RELEASING.md.
Mantenimiento del registro de cambios (obligatorio)#
Todo cambio visible para el usuario actualiza CHANGELOG.md:
- Añada una entrada en la sección
[Unreleased], en el grupo correspondiente (Added/Changed/Fixed/Removed/Documented/Planned). - Al publicar una versión, renombre
[Unreleased]a la nueva[x.y.z] - YYYY-MM-DD, inicie un[Unreleased]nuevo, aumenteversionenCargo.toml(para queengine_versionen el JSON de resultados coincida), actualice los enlaces de comparación del final y etiquetevx.y.z. - Mantenga las entradas concisas y orientadas al usuario; enlace incidencias/PR cuando sea útil.
Una pull request que cambia el comportamiento sin una entrada en el registro de cambios está incompleta.
Control de exportaciones#
La resiliencia PNT y la detección cuántica pueden afectar a los controles de exportación de doble uso. Mantenga el repositorio público en modelos y métodos genéricos y publicados. Todo lo que se parezca a una profundidad de resiliencia/antispoofing sensible a la exportación pertenece a la capa privada, no aquí. Si tiene dudas, pregunte antes de contribuirlo.
Licencia#
Kshana tiene doble licencia (AGPL-3.0 o una licencia comercial de Ashforde OÜ; véase LICENSING.md). Para que eso siga funcionando, las contribuciones deben poder usarse bajo ambas licencias. Por ello, al contribuir, usted acepta que:
- su contribución se licencia de entrada bajo la AGPL-3.0-only; y
- usted concede además a Ashforde OÜ una licencia perpetua, mundial, libre de regalías e irrevocable para usar, modificar y relicenciar su contribución como parte de la edición con licencia comercial de Kshana (es decir, para distribuirla también con términos comerciales no AGPL). Usted conserva los derechos de autor de su contribución.
Esta concesión ligera de doble licencia, que no es una cesión de derechos de autor, es lo que permite que el proyecto siga siendo abierto y ofrezca una edición comercial. Si no puede conceder (2) (por ejemplo, código propiedad del empleador), dígalo en su pull request antes de contribuir.
Excepción: integrations/opencpn/plugin/. Ese directorio tiene licencia GPL-3.0-or-later (véase su LICENSE) y queda fuera de la licencia comercial. Las contribuciones a él se licencian de entrada únicamente bajo GPL-3.0-or-later; la concesión (2) no se les aplica.
Firme cada commit para dar fe del Developer Certificate of Origin: git commit -s (añade una línea Signed-off-by).