Traduction automatique, non relue par un locuteur natif. L'anglais fait foi.

ProjetModifier sur GitHubSource : CHANGELOG.md

Journal des modifications

Toutes les modifications notables de Kshana sont documentées ici.

Le format s'appuie sur Keep a Changelog, et ce projet adhère à Semantic Versioning. Tant que le projet est en version antérieure à 1.0, le schéma public des scénarios et des résultats peut encore changer ; les ruptures de compatibilité sont signalées explicitement.

Non publié#

[0.40.0] - 2026-10-29#

0,40 ajoute le fil de mission de classe Artemis et son segment lunaire, une étiquette de preuve sur chaque figure et chaque tableau qu'une exécution écrit, l'ingestion et l'ajustement d'horloge mesurée, une vérification des soumissions de partenaires de données, une région d'émetteur estimée à partir de rapports ADS-B ou AIS, la nouvelle campagne de benchmark 0,40, ainsi que la ligne de commande, les rapports et le Studio en dix-sept langues en plus de l'anglais (les documents machine restent en anglais). La matrice de vérification passe de 388 à 401 lignes : 176 VALIDATED (inchangé), 221 MODELLED (contre 208) et 4 PARTNER. Aucune ligne n'a été promue à VALIDATED. Les types de scénario passent de 87 à 92. Chaque seuil qu'une comparaison préenregistrée n'a pas atteint est énoncé ci-dessous et reste épinglé ; aucun n'a été assoupli. L'énoncé à titre consultatif est inchangé : Kshana est un logiciel à titre consultatif, et non un équipement de navigation homologué et pas une certification ; l'opérateur reste responsable.

Limites connues#

  • Les exécutions non anglaises prennent environ deux fois plus de temps, car le scénario s'exécute deux fois (une fois en anglais pour les fichiers machine, une fois dans la langue choisie pour la personne).
  • Certaines phrases du Studio sont assemblées à partir de fragments et peuvent manquer d'articles dans les langues qui ont un genre grammatical.
  • Les traductions sont des traductions automatiques qu'aucun locuteur natif n'a relues ; l'anglais fait foi.

Ajouté#

  • Dix-sept langues en plus de l'anglais pour le texte du moteur destiné aux personnes, ainsi que pour le site et le Studio : nl, pl, pt-BR, pt-PT, fi, sv, da, nb, cs, uk, ru, de, fr, es, et, ja, zh-Hans (--lang, KSHANA_LANG, les variables de paramètres régionaux ; lang sur les appels de la bibliothèque, de Python, de WebAssembly et de MCP). Les messages et erreurs de la ligne de commande, les synthèses d'exécution, le texte des graphiques, report.html, les descriptions des types et les mentions à titre consultatif sont traduits ; les documents machine (JSON, CSV, codes d'erreur, matrice de vérification) restent en anglais, et une exécution non anglaise exécute le scénario une fois en anglais pour les fichiers machine et une fois dans la langue choisie pour la personne (docs/i18n.md). Les traductions sont des traductions automatiques, non relues par des locuteurs natifs ; l'anglais fait foi ; le fichier REVIEW.md de chaque langue indique ce qu'un relecteur doit vérifier en premier, et les pages du site portent un avis qui le dit. Les mots de verdict, les niveaux de preuve et la portée de la mention à titre consultatif (« non homologué », « pas une certification », « l'opérateur reste responsable ») sont conservés dans toutes les langues.
  • kshana interference-map locate : une région d'émetteur estimée à partir de rapports ADS-B ou AIS. Une postérieure sur l'endroit où peut se trouver une source de rapports de position dégradés (ligne de visée radio sur un rayon terrestre de 4/3, hauteur d'antenne et puissance de l'émetteur marginalisées, aéronefs touchés qui tirent et aéronefs non touchés en ligne de visée qui repoussent), écrite sous forme de régions à 50, 90 et 95 %, d'un centroïde avec son ellipse d'incertitude (jamais un simple point), de sessions dans le temps (début, fin, durée, surface touchée, aéronefs distincts au-dessus du minimum de publication), d'un profil horaire et d'heures par jour, avec fusion facultative d'une position TDOA issue de geolocation. Sorties : GeoJSON, synthèse JSON, CSV des sessions et figure SVG, chacune portant la licence, l'attribution, l'identifiant de méthode, les hypothèses, les limites et son étiquette de preuve. Bibliothèque interference_map::api::emitter_regions_from_*, Python et WebAssembly interference_emitter_regions. MODELLED (ligne du registre VM-bc70cb57 ; la matrice compte désormais 401 lignes, 176 VALIDATED, 221 MODELLED, 4 PARTNER) ; étalonnée sur des données synthétiques seulement, la comparaison avec les sites d'émetteurs de Jammertest 2025 ayant été préenregistrée et exécutée une fois : ADS-B et AIS tous deux NOT ASSESSABLE (trop peu de sessions programmées dans les données ouvertes), de sorte que la ligne reste MODELLED (docs/emitter-region/RESULTS.md). Formulation neutre, agrégat seulement ; la publication des régions d'émetteurs dans l'observatoire public reste désactivée. Un exemple synthétique se trouve dans examples/emitter-region/ (docs/INTERFERENCE-MAP.md).
  • Journaux d'horloge mesurés. src/clock_log.rs lit un journal d'horloge mesuré pour en tirer une série de phase unique : huit formats (RINEX clock, TimeLab, TICC, linuxptp ptp4l, phc2sys et ts2phc, suivi et statistiques de chrony), chacun un sous-ensemble documenté ; tout ce qui sort de ce cadre est refusé avec une erreur qui nomme ce qui a été trouvé. Il est utilisé par telecom-timing ([series.clock_log]) et par le type horloge ([clock_log], qui ajoute un bloc measured avec le SHA-256 du journal et les ADEV, TDEV et MTIE qui se recouvrent), avec le scénario fourni clock-measured-log (docs/CLOCK-LOG-FORMATS.md). Comparé à allantools sur des données publiques réelles par rapport à des seuils préenregistrés : la première exécution n'a pas atteint B1 (5 cas sur 11, tous des horodatages TICC conservés en f64), B2, B3 (7 cas sur 24) et B4 (la version de l'en-tête n'était pas vérifiée) ; après les corrections, B1, B3 et B4 sont atteints et B2 l'est sauf pour une paire MTIE, qui est épinglée et n'est pas un défaut du moteur (allantools 2024,6 retire la fréquence moyenne avant d'intégrer ; par rapport à son MTIE en mode phase, le moteur concorde à 1e-10 près). La ligne reste MODELLED (tests/fixtures/clock_log_real/RESULTS.md).
  • Un holdover piloté par une série mesurée ajustée : le [clock_fit] du type horloge ajuste le bruit d'une série mesurée et pilote le holdover à partir de celui-ci (src/clock_fit.rs, scénario fourni clock-fitted-log). Comparaison préenregistrée : F1(b), F3 et F4 atteints ; F1(a) (retrouver la FM à marche aléatoire enregistrée) NOT MET sur les enregistrements C3 (non identifiable par construction) et sur deux des trois enregistrements C4 (FM à marche aléatoire absorbée par la FM de scintillement et la dérive) ; F2 (identification du bruit par rapport à allantools) atteint sur onze des douze enregistrements et D3, et NOT MET sur D2 tel qu'enregistré (atteint à périmètre égal). Tous les échecs sont épinglés (tests/clock_fit_known_noise.rs) ; le bloc fitted et le holdover qu'il pilote restent MODELLED (tests/fixtures/clock_fit/RESULTS.md).
  • La nouvelle campagne de benchmark 0,40, préenregistrée avec la validation du propriétaire avant toute exécution : A3 (EXPLORATORY, l'AUC bootstrap par regroupement de dossiers de agc_k_sigma, quantile à 2,5 % 0,8502 contre 0,80), D3 (EXPLORATORY, trois détecteurs sur cinq dépassent un écart d'optimisme de 0,05 à l'échelle 0,25), R3 (AUC 1,0) et R4 (P_fa 0,0, P_d 1,0) : tous MET, tous MODELLED. A2, D1 et R1 ne sont pas touchés et restent NOT MET ; rien ici ne les referme (xval/bench/RESULTS-0.40.md, Bench).
  • kshana partner check <submission.toml> : vérifie le format et les métadonnées d'une soumission de partenaire de données (kshana.partner-submission/1 : appareil, fichier de données et SHA-256, mode d'acquisition, lignes MODELLED pour lesquelles elle est proposée, licence, déclarations) et lit les données avec les lecteurs de journaux d'horloge ou d'IMU du moteur. Il ne note rien et ne valide rien. Un exemple synthétique se trouve dans examples/partner-submission/.
  • docs/PARTNER-DATA.md : quelles lignes MODELLED du registre des données mesurées pourraient promouvoir, les formats acceptés, comment une soumission est vérifiée, notée par rapport à un seuil préenregistré et créditée, et ce que signifient PARTNER et VALIDATED ; une note de prospection en brouillon pour le propriétaire dans docs/drafts/PARTNER-OUTREACH.md (rien n'est envoyé).
  • Deuxièmes campagnes pour les seuils non atteints de gnss-ssv et lunar-infrastructure, exécutées comme préenregistré (xval/gnss-ssv/PREREGISTRATION-v2.md, xval/lunar-infra/PREREGISTRATION-v2.md ; validées avant toute exécution). Chaque échec d'origine reste NOT MET et épinglé. gnss-ssv : le témoin reproduit l'exécution 1 cellule par cellule ; cinq ablations à lecture unique ramènent 2 des 78 cellules manquées dans la tolérance (EXPLORATORY, sans seuil) ; le nouveau seuil S7b (une forme d'émission à décroissance et plancher ajustée sur des panneaux Classic IIR) est NOT MET sur les panneaux IIR-M à 3,83 à 3,95 dB contre 3 dB ; la campagne de réception publiée mise de côté n'a pas été exécutée (aucune source épinglée) (xval/gnss-ssv/RESULTS-v2.md). lunar-infrastructure : les nouveaux seuils C3a, C3b (une limite de détection d'environ 3e-9 m/s2), Q3a, Q3b (une fonction de répartition normale précise supprime l'écart de 1.7e-6) et G3'' sont atteints comme seuils à part entière, et G3' avec des a priori illustratifs est atteint et étiqueté EXPLORATORY (xval/lunar-infra/RESULTS-v2.md). Tout reste MODELLED. Nouveaux éléments publics : kshana::lambda::{erfc_accurate, normal_cdf_accurate, bootstrap_success_rate_accurate}.
  • Une étiquette de preuve sur chaque figure et chaque tableau qu'une exécution écrit. Le JSON de résultat a une clé evidence, le SVG du graphique un élément de métadonnées et une ligne sous le tracé, et le tableau CSV des lignes de commentaire # evidence: : le niveau (VALIDATED, MODELLED ou PARTNER, le plus faible des lignes) et les identifiants des lignes de la matrice de vérification sur lesquelles l'exécution repose. Les lignes et les statuts sont lus dans la matrice, et non saisis à la main ; les identifiants sont stables (VM- et huit chiffres hexadécimaux, une nouvelle colonne ID dans docs/VERIFICATION-MATRIX.md, une liste figée dans tests/fixtures/evidence_ids.txt). Aussi sur receiver-trust, jammertest score, iq acquire/sweep/track/monitor, le rapport d'exposition de l'itinéraire et, dans le config.json signé, chaque paquet de preuves (config_version 1,1 ; kshana evidence verify indique le niveau ; les paquets créés avant 0,40 se vérifient sans changement). tests/evidence_labels_doc_sync.rs échoue si une figure n'a pas d'étiquette, si une étiquette est en désaccord avec la matrice ou si un nouvel écrivain de fichiers n'est ni étiqueté ni listé avec une raison. Les sorties qui n'en portent aucune sont listées dans docs/SURFACES.md. Les trois graphiques de démonstration du README ont été rendus de nouveau avec l'étiquette (la retirer restitue les anciens octets ; docs/revisions/STUDIO15-evidence-label-0.40.md). Aucune affirmation n'a changé.
  • Le type de scénario mission-thread (scenarios/mission-thread-artemis-class.toml, docs/MISSION-THREAD.md) : le budget d'erreur de navigation et de synchronisation d'une chaîne de phases du lancement à l'entrée, chaque nombre MODELLED et chaque entrée déclarée. Huit types de phase : launch-ascent, leo-rendezvous (covariance relative de Clohessy-Wiltshire sur des segments de capteur, fenêtre d'amarrage), tli-and-cruise (propagation de Cowell avec une matrice de transition d'état aux différences finies, erreur de poussée, mises à jour gnss-ssv et de suivi au sol, la Lune issue d'une découpe facultative du noyau DE440), entry (sigma de l'angle de trajectoire, probabilité de corridor, décélération maximale aux bords du corridor, empreinte d'atterrissage) et les quatre types lunaires. Règles de transfert (carry, inflate, reacquire), conversions de référentiel et d'échelle de temps comme lignes de budget à part, une superposition facultative du réseau au sol qui fixe le cycle de suivi de chaque phase, la marge par rapport aux exigences déclarées et le maillon le plus faible. L'exemple suit la séquence d'un diaporama public de concept d'opérations de la NASA avec des nombres ILLUSTRATIVE : un exemple de bout en bout de classe Artemis sur 11 phases, segments terrestre et lunaire. La propagation cislunaire a été comparée à la trajectoire publique d'Artemis I sur un arc de 72 h par rapport à un seuil fixé dans xval/mission-thread/PREREGISTRATION.md avant l'exécution : NOT MET (45,3 km et 0,25 m/s contre 5 km et 0,05 m/s). Le diagnostic situe l'écart dans cinq petits événements impulsifs de la référence ; entre eux, le modèle de forces reproduit les états horaires avec une médiane de 0,4 m. La ligne reste MODELLED (xval/mission-thread/RESULTS.md).
  • Le segment lunaire du fil de mission de classe Artemis : quatre types de scénario, chacun aussi un type de phase de l'interface mission-thread (src/mission_thread/lunar/), tous MODELLED.
    • lunar-orbit-rendezvous : navigation relative jusqu'à l'amarrage sur une orbite polaire circulaire à 100 km ou elliptique de 100 km sur 3000 km (scenarios/lunar-orbit-rendezvous.toml, ...-elfo.toml). Une estimation par lots de Gauss-Newton sur l'arc fusionne un point absolu par véhicule issu d'un ensemble illustratif de relais de classe LCNS, une erreur persistante du signal dans l'espace (commune aux deux véhicules et indépendante) et une distance par liaison croisée, sous le modèle de forces lunaires de la crate. Elle rapporte la position et la vitesse relatives dans les axes locaux de la cible, la disponibilité des points, l'erreur d'estimation normalisée moyenne au carré par rapport à sa valeur attendue, le coût d'ignorer les harmoniques de gravité, les modèles de capteurs relatifs terminaux à côté du chiffre des signaux seuls, et la covariance 6x6 transmise.
    • lunar-descent : le budget de dispersion à l'atterrissage sur un site polaire sud (scenarios/lunar-descent.toml ; lunar-descent-lola.toml lit le MNT LOLA depuis une copie du dépôt) : un modèle d'erreur inertielle à cinq états par axe, un point AFS (autonome ou différentiel, avec le résidu de la liaison de correction de lunar-differential-pnt), un point relatif au terrain (le comparateur terrain-nav sur son relief synthétique, ou la borne de Cramer-Rao de l'appariement avec le MNT LOLA), et le temps lunaire par l'horloge du véhicule (lunar-time-offset). Elle rapporte l'ellipse d'atterrissage à 3 sigma, chaque combinaison d'aides, et un étalonnage Monte Carlo de l'ellipse.
    • lunar-surface : disponibilité du positionnement et de la synchronisation temporelle par site et par saison (scenarios/lunar-surface.toml ; lunar-surface-terrain.toml ajoute l'horizon LOLA tracé par rayons) : le chiffre de positionnement à site unique égale celui de moonlight-service-volume au bit près ; c'est la visibilité de la Terre et du Soleil, issue des éphémérides analytiques, qui varie avec la saison.
    • lunar-ascent : l'ascension jusqu'à l'orbite de rendez-vous et la covariance de position et de vitesse reportée en orbite (scenarios/lunar-ascent.toml), avec la dispersion à la coupure des moteurs rapportée à côté.
    • docs/MISSION-THREAD-LUNAR.md ; le préenregistrement, ses amendements et chaque résultat, échecs compris, dans xval/mission-thread-lunar/.

Preuves#

  • Préenregistré dans xval/mission-thread-lunar/PREREGISTRATION.md avant toute exécution, avec six amendements datés (chacun fait avant la récupération des données, sauf l'amendement 6, qui corrige une erreur de calcul dans un nombre d'états après la récupération et avant tout résultat A2 ; chaque amendement est signalé dans le fichier). Aucun seuil n'a été assoupli.
  • A1 (le propagateur par rapport à la trajectoire reconstituée de LRO issue de JPL Horizons, 24 h) : MET, un écart 3-D maximal de 33 m contre un seuil de 500 m et un écart radial RMS de 2,4 m contre 60 m.
  • A2 (le même propagateur par rapport à la NRHO de CAPSTONE sur une révolution de 6,5 jours) : NOT MET, un écart de position finale de 136,8 km contre un seuil de 25 km et un écart de rayon de périapse osculateur de 28,4 km contre 10 km. La ligne reste MODELLED, et l'échec est épinglé par tests/mission_thread_lunar_oracles.rs.
  • B1 (la cohérence de l'estimation de rendez-vous avec son propre modèle) est MET à la quatrième conception d'estimateur, NEES moyenne de 5,85 à 5,93 contre une bande de [5,2, 6,8] ; les trois conceptions précédentes, un filtre de Kalman étendu en trois variantes, l'ont manquée. Un cinquième changement, fait après qu'on a constaté que le scénario livré de 2 h envoyait 4 essais sur 50 vers un minimum local (NEES moyenne 1e9), exécute l'ajustement de Gauss-Newton sur un arc croissant avec réduction du pas de moitié ; B1 n'en est pas modifié et les scénarios livrés donnent 6,51 et 6,33. L'historique se trouve dans xval/mission-thread-lunar/RESULTS.md.
  • Rien ici n'est VALIDATED : les lignes de références indépendantes testent le propagateur partagé, et non un filtre de navigation, un signal ou un budget.

[0.39.0] - 2026-10-22#

Aucune nouvelle fonctionnalité : une correction de ligne de commande, des mises à jour de dépendances dans l'outillage de validation croisée, et de la documentation. Les résultats du moteur sont inchangés par rapport à 0.38.0.

Corrigé#

  • La ligne de commande se termine silencieusement avec le statut 141 lorsque sa sortie standard se ferme (kshana kinds | head), au lieu de paniquer avec « failed printing to stdout: Broken pipe ». 141 vaut 128 plus SIGPIPE, le statut qu'un shell rapporte pour yes | head. Seul un tube fermé est géré : un disque plein ou toute autre erreur d'écriture se signale toujours, et un flux en direct écrivant dans un socket fermé reçoit toujours son erreur d'écriture. tests/cli_closed_pipe.rs ferme le lecteur avant le démarrage du programme, de sorte que la première écriture échoue à chaque exécution.

Sécurité#

Une mise à jour de dépendance dans la bibliothèque livrée (la première entrée), les autres dans l'outillage de validation croisée (xval/).

  • p256, p384 et p521 0,13 vers 0,14 (avec elliptic-curve 0.14.3, ecdsa 0.17.0 et crypto-bigint 0.5.5 vers 0.7.10 ; aussi la dépendance directe crypto-bigint, désormais 0,7) corrigent RUSTSEC-2026-0387, une variabilité de temps d'exécution dans crypto-bigint 0.5.5. Kshana n'utilise ces crates que pour vérifier des signatures publiques (la clé racine Galileo OSNMA et les jetons d'horodatage RFC 3161) et ne signe que dans les tests, avec des clés jetables ; l'exposition pratique était donc nulle ; la mise à niveau supprime l'avis sans entrée d'exclusion. Les fichiers de verrouillage de la bibliothèque et du MCP changent tous les deux ; aucun résultat de vérification ne change (les tests de vecteurs OSNMA et d'horodatage passent sans modification).
  • La version minimale de Rust prise en charge est désormais 1,88 (exigée par le correctif de RUSTSEC-2026-0387).
  • memmap2 0.9.10 vers 0.9.11 (RUSTSEC-2026-0186) dans les verrous de vérification croisée ANISE (xval/anise-lunar-od, xval/anise-mars-od) ; les verrous resynchronisent aussi la dépendance de chemin kshana du dépôt.
  • pillow 12.3.0 vers 13.0.0 et certifi 2026.7.22 vers 2026.10.19 dans les épinglages de l'environnement des références indépendantes (xval/oracles/requirements.lock, requirements.frozen.txt) : les versions corrigées pour huit avis de sécurité de pillow et un avis de certifi.

Documentation#

  • docs/BENCH.md, le README et ce fichier listent chaque seuil de kshana-bench qui est NOT MET, tel qu'enregistré dans xval/bench/RESULTS-v2.md : A2 (AUC de agc_k_sigma 0,766 contre au moins 0,80 sur la partition de test), D1 (plus grand écart 0,0301) et tâche (b) R1 (reporté, non ré-exécuté). Aucun seuil n'est assoupli.
  • Passe de complétude du README : une table des matières ; les types de scénario classés par familles, chacun avec une page sous docs/kinds/by-kind/ (la description et les champs du moteur, les entrées et résultats d'une exécution d'exemple, les lignes du registre et les références indépendantes, les limites que le rapport de l'exécution énonce, et le graphique que le moteur écrit), une planche-contact par famille, le tout indexé par docs/KINDS.md ; chaque commande dans docs/COMMANDS.md ; chaque surface, commande de greffon, compétence et page Studio dans docs/ALL-SURFACES.md ; chaque domaine de capacité dans docs/CAPABILITY-DOMAINS.md ; des diagrammes Mermaid intégrés (vue d'ensemble du système, surfaces, boucle interne, confiance du récepteur, aller-retour de laboratoire, Studio, flux de test et de publication, carte des modules, distribution). Écrit par tools/gen_kinds_index.py, tools/gen_readme_blocks.py et tools/gen_figures_038.py ; audité par tools/readme_audit.py ; protégé par tests/readme_completeness_doc_sync.rs, qui épingle aussi la description et les champs de chaque entrée au moteur.
  • tools/render-diagram-chromium.sh : rend un diagramme Mermaid en SVG et en PNG sous Linux et met à jour l'enregistrement de rendu.
  • README : les figures de l'utilisateur de l'espace et de la Lune utilisaient des chemins relatifs à docs/, de sorte qu'elles ne se chargeaient pas depuis le README ; un lien pointait vers ../../docs/JAMMERTEST.md.
  • Suppression de deux fichiers de graphiques périmés copiés à la main (docs/assets/clock-ensemble-band.svg, sweep-clock-stability.svg) qu'aucune page n'utilisait et qui ne correspondaient plus au moteur ; docs/KINDS.md porte les graphiques à jour.

[0.38.0] - 2026-10-19#

Ajouté#

  • Le GNSS au-delà de la constellation (gnss-ssv). Un nouveau type de scénario pour les engins spatiaux au-dessus, autour et au-delà des orbites GNSS (docs/SSV.md) : disponibilité d'un et de quatre signaux, durées d'interruption, C/N0, DOP et liaisons par lobe principal par rapport aux lobes secondaires pour GPS, GLONASS, Galileo, BDS, QZSS et NavIC sur une coquille ou le long de trajectoires LEO, MEO, GEO, HEO et de transfert lunaire ; diagrammes d'émission du livret, paramétriques ou fournis par l'utilisateur ; un modèle d'ionosphère, de plasmasphère et d'atmosphère par rayon rasant ; une conception de récepteur pour signaux faibles ; un filtre de Kalman étendu GNSS embarqué pour l'HEO et le transfert lunaire ; et la navigation relative en formation. Comparé au livret du volume de service spatial de l'ICG sous un préenregistrement commité avant l'exécution : les constantes de puissance rayonnée minimale et le seuil lunaire concordent, les autres seuils ne sont pas atteints selon la lecture préenregistrée (presque tous à cause de l'angle de faisceau GLONASS incohérent du livret), et le substitut paramétrique des lobes secondaires ne reproduit pas les diagrammes mesurés des panneaux GPS. Tout reste MODELLED (xval/gnss-ssv/RESULTS.md).
  • Orbite et surface lunaires comme infrastructure de navigation et de géodésie (lunar-infrastructure). Un nouveau type de scénario avec cinq études sélectionnées par study (docs/LUNAR-INFRASTRUCTURE.md) : cohérence d'une détermination d'orbite embarquée par GNSS terrestre sur une orbite de halo quasi rectiligne par rapport à une détermination indépendante au sol de distance et de vitesse radiale ; phase de la porteuse en double différence conjointe d'une station de surface et d'un orbiteur avec fixation des ambiguïtés entières par LAMBDA ; information de Fisher du datum lunaire à sept paramètres avec et sans mesures de distance orbiteur-surface ; décalages inter-techniques GNSS, VLBI et télémétrie laser par rapport au lien local ; et sensibilité à h2, k2, l2 et à la libration physique. MODELLED, avec des entrées ILLUSTRATIVE : les calculs sont vérifiés par rapport à des programmes numpy et scipy indépendants, et rien n'est comparé à une mesure d'une grandeur lunaire. Les seuils ont été fixés dans xval/lunar-infra/PREREGISTRATION.md et deux amendements divulgués. Trois sont NOT MET et chacun est épinglé par un test qui affirme l'écart : C3 (une erreur de force injectée n'est pas détectée au taux préenregistré), Q3 (le taux de réussite par rééchantillonnage diffère de la référence numpy de 1.7e-6 pour un seuil de 1e-9, du fait de l'approximation de la fonction de répartition normale de LAMBDA), et la moitié trace de G3 (ajouter une famille de mesures de distance ne diminue pas toujours la trace de la pseudo-inverse). Les autres sont atteints (xval/lunar-infra/RESULTS.md).
  • Un sixième article dans le tableau Recherche. « Cislunar navigation is an observability problem: arc-length thresholds, Gramian conditioning, and the Doppler lever » (arXiv:2610,23871, eess.SP) montre que la dilution de précision n'est pas définie pour un suivi cislunaire par mesures de distance seules et utilise à la place le gramien d'observabilité sur quatre orbites rétrogrades distantes planes : les mesures de distance seules donnent un rang 2 sur 4 à un instant donné et exigent un arc d'environ 2,09 h, la vitesse radiale (Doppler) donne le rang 4 instantanément, et l'estimation conjointe d'une station avec les états des satellites et les horloges reste déficiente en rang d'une unité sans observable interférométrique externe. Ses nombres sont régénérés par le type de scénario cislunar-observability (kshana scenarios/cislunar-observability.toml) ; cislunar-arc-recovery teste le seuil avec un estimateur indépendant. La carte de recherche du README, les README des crates, de npm et de PyPI, ainsi que le générateur la portent.
  • L'arbitre neutre, rendu mesurable. kshana jammertest import lit le catalogue d'essais et le plan de transmission NPRA Jammertest publiés comme vérité planifiée (identifiants du catalogue conservés) et kshana jammertest score note un journal de récepteur par rapport à celui-ci, par essai (latence de détection, alarmes manquées, fausses alarmes, délai de rétablissement), éventuellement sous forme de paquet de preuves signé (docs/JAMMERTEST.md). Les seuils de notation ont été préenregistrés avant toute exécution notée (xval/jammertest-score/). Sur le jeu de données JammerTest 2024 (récupéré, jamais intégré au dépôt), la règle préenregistrée de quantité minimale de données a échoué à la fois lors de la première exécution et lors de la révision du traitement des données, de sorte qu'aucun seuil n'est évaluable et que rien n'est revendiqué ; les deux exécutions sont consignées et épinglées. MODELLED : le calendrier est constitué des fenêtres journalisées du jeu de données, et non d'heures d'émission enregistrées. Le jeu NMEA SimulaMet de 2025 n'est pas adapté (aucune licence indiquée sur sa page).
  • Les propres indicateurs du récepteur, à côté de ceux de Kshana. UBX-NAV-STATUS spoofDetState et UBX-SEC-SIG sont lus dans self_report à chaque époque, et la comparaison receiver_self_report dans le résultat les met en regard des moniteurs de Kshana (les deux, récepteur seul, Kshana seul, aucun) ; elle ne déclenche aucune alarme et ne modifie aucun score. Un lecteur SBF Septentrio (PVTGeodetic, MeasEpoch, RFStatus, en lecture seule, sur la crate sbf-tools sous licence MIT) et receiver-trust live --serial (un flux NMEA série ou USB, en lecture seule ; il n'écrit jamais dans un récepteur) s'y ajoutent.
  • Synchronisation temporelle et sécurité du matériel (docs/TIMING-HIL.md, docs/HARDWARE-SAFETY.md). Le type de scénario holdover-test note un essai de holdover d'un système de synchronisation temporelle (GNSS retiré par l'opérateur, holdover, rétablissement) à partir d'un enregistrement mesuré de l'erreur de temps, mesuré par rapport aux gabarits de l'ITU-T issus de tables publiques. clock_log lit les journaux de linuxptp (ptp4l, phc2sys, ts2phc) et de chrony (tracking, statistics). iq scene --format sdrx écrit des métadonnées ION GNSS SDR et iq monitor --follow surveille un enregistrement SigMF pendant qu'il s'allonge (réception seule). compliance-report gagne le profil PNT fondamental NIST IR 8323r1 (15 lignes paraphrasées, apporte des éléments de preuve en faveur de). Un paquet de preuves peut consigner la lab-attestation de l'opérateur dans son manifeste signé, jamais vérifiée ; les étapes matérielles 0 à 4 et les notes juridiques figurent dans HARDWARE-SAFETY.md (en attente de relecture juridique). Il n'existe aucun chemin d'émission d'aucune sorte.
  • kshana-bench v1 (kshana bench, bench/SPEC.md, docs/BENCH.md) : tâches, partitions et métriques fixes pour la détection d'interférences GNSS sur des journaux de récepteur (JammerTest 2024) et en IQ, la prédiction du holdover de synchronisation temporelle (horloges IGS) et l'écart d'optimisme hors distribution ; manifestes de partitions avec hachages épinglés et scripts de récupération (aucune donnée intégrée au dépôt), un jeu réservé scellé par engagement puis révélation, un schéma de fichier de résultats et une page de classement statique. Références de base sous des seuils préenregistrés dans xval/bench/PREREGISTRATION.md : seuils du calcul de score atteints, C1 à C3 atteints, D2 atteint ; A2 NOT MET (AUC de agc_k_sigma 0,766 contre au moins 0,80 sur la partition de test), D1 NOT MET (plus grand écart 0,0301) et tâche (b) R1 NOT MET (reporté, non ré-exécuté), chacun épinglé (xval/bench/RESULTS-v2.md). Chaque score est MODELLED. Python bench_score, bench_leaderboard ; WebAssembly de même ; MCP score_benchmark, render_leaderboard.
  • Observatoire des interférences (kshana interference-map daily, sensitivity, docs/observatory/METHOD.md) : un GeoJSON quotidien reproductible, un PNG et un JSON de rapport d'incident avec trois états (dégradé, non dégradé, non observé), un délai minimum de 24 h, des cellules de 0,5 degré ou plus grossières, aucune cause attribuée et des données OpenSky refusées ; une étude de sensibilité des paramètres préenregistrés ; un catalogue rétrospectif de 30 jours sur la Baltique issu d'adsb.lol.
  • Entrées de machines et de capteurs pour receiver-trust (docs/MACHINE-INPUTS.md). Nouvelles valeurs [log] format, toutes en lecture seule, MODELLED, avec des fixtures écrites par nous et aucune donnée intégrée au dépôt : rtklib-pos (fichiers de solution RTKLIB .pos), novatel (BESTPOS OEM7 ASCII et binaire, C/No RANGE et RXSTATUS ; l'indicateur de brouilleur du récepteur devient le self_report de l'époque, mis en regard des alarmes de Kshana par la comparaison receiver-self-report), rtcm3 (C/N0 MSM4 et MSM7 pour GPS, GLONASS, Galileo, SBAS, QZSS, BeiDou et NavIC ; dispositions tirées des tables pyrtcm sous licence BSD, dont l'avis figure dans NOTICE, et non de la norme RTCM) et gnss-sdr (messages GNSS-SDR Monitor et PVT-monitor en lignes JSON, relayés par integrations/gnss-sdr/relay.py).
  • Les journaux IMU comme second capteur. [log.imu] (csv ou euroc) intègre la vitesse de lacet du gyromètre en le cap que lit le moniteur heading-course ; en ligne sur chaque surface et transporté dans les paquets de preuves. kshana imu-fit (Python imu_fit, WebAssembly imu_fit, MCP fit_imu_log, greffon /kshana-fit-imu, une action JetBrains) ajuste les paramètres de l'accéléromètre et du gyromètre des scénarios hybrid et fusion à partir d'un journal à l'arrêt par déviation d'Allan et imprime une table [accel_classical] avec le SHA-256 du journal dans sa provenance.
  • Intégrations : un paquet ROS 2 (integrations/ros2/kshana_trust : NavSatFix et ublox_ubx_msgs en entrée, topics de confiance en sortie ; sa passerelle sans ROS est testée avec le vrai moteur, le nœud lui-même n'a pas été exécuté sur un graphe ROS en direct), une passerelle gnss_lib_py (integrations/gnss_lib_py, dépendance MIT, optionnelle), et un relais GNSS-SDR.
  • Exportateur MQTT Home Assistant pour la télémétrie de confiance : kshana trust-telemetry --print-mqtt et --mqtt-tcp <host:port> (messages de découverte et document d'état JSON ; publication seulement, sans identifiants ni TLS), et format = "mqtt" en texte sous Python, WebAssembly et MCP.
  • Sept lignes MODELLED du registre pour ce qui précède. Rien ici n'est VALIDATED : aucune capture d'un vrai récepteur, d'une vraie station de base, d'une IMU, d'une exécution de GNSS-SDR, d'un graphe ROS ou d'un courtier MQTT n'a été lue.
  • Marge de liaison optique en fonction du temps. Le type de scénario optical-atmosphere accepte une table [timeseries] optionnelle (duration_h, step_s, seed) et écrit alors aussi, par site, une réalisation à germe fixé du modèle de site énoncé dans le temps : épisodes nuageux, une colonne d'eau liquide par épisode, un échantillon de scintillation gamma-gamma par pas, et à partir de ceux-ci la marge de liaison, les évanouissements dus aux nuages et à la scintillation et l'indicateur de liaison active, avec la disponibilité réalisée, la fraction nuageuse, le nombre d'interruptions et la plus longue interruption. MODELLED (un tirage du modèle, et non le climat ; aucune référence externe indépendante). Sans la table, le résultat est le document 0,37. Les deux scénarios optiques fournis portent la table (336 h, 600 s, germe 37). Seuils préenregistrés dans xval/optical-atmosphere/PREREGISTRATION-timeseries.md avant la première exécution.
  • Spécification des conditions d'essai et aller-retour de laboratoire. kshana.test-conditions/1 est publié sous docs/spec/TEST-CONDITIONS.md avec un schéma JSON, et gagne recording.kind = "receiver-log". kshana bench-export écrit aussi <base>.conditions.json. kshana evidence round-trip construit un paquet signé reliant le hachage du scénario, le hachage des conditions énoncées, le hachage du journal du récepteur et le score par rapport aux événements énoncés, et refuse des conditions en désaccord avec les événements de notation. Exemple traité avec gps-sdr-sim écrivant seulement un fichier ; la relecture est de la responsabilité de l'opérateur et n'est jamais automatisée. Python evidence_round_trip, MCP create_round_trip_pack, greffon /kshana-evidence-pack.
  • Paquets de normes (kshana standards-pack, standards/) : les profils d'essai du cadre DHS Resilient PNT pour les niveaux 1 à 4, les niveaux de précision et l'évaluation de l'intégrité de l'IMO MSC.1/Circ.1575, et surveiller, évaluer et atténuer de l'ICAO Doc 9849 Appendix F, chacun étant un ensemble de scénarios notés par rapport à des seuils énoncés avant l'exécution, avec les lignes compliance-report en faveur desquelles ils apportent des éléments de preuve. Les écarts sont consignés et épinglés : DHS L4-T1 et les quatre essais de précision de l'IMO. Le Doc 9849 lui-même n'a pas été lu (payant) ; le paquet ICAO suit la propre présentation du plan d'atténuation des RFI de l'ICAO. compliance-report gagne une section de paquets de normes. Tous MODELLED.
  • Signal avant augmenté LunaNet (docs/LUNANET-AFS.md) : codes de Gold AFS-I et de Weil AFS-Q pour les PRN 1 à 210, signaux lunanet-afs-i et lunanet-afs-q dans kshana iq, le code SB1 BCH, le CRC-24Q et l'entrelaceur, et kshana lunanet-afs-check (spec, symbols, generate), épinglé sur LNIS V5 Applicable Document 1 Volume A (LSIS-AFS V1.0, 29 janvier 2025). Codes VALIDATED par rapport aux tables imprimées du document (qu'il marque TBC) ; une colonne tertiaire imprimée (PRN 147) est probablement une coquille et l'écart est épinglé. Le codage LDPC des sous-trames 2 à 4 n'est pas implémenté.
  • Carnets du cours (notebooks/course/) : brouillage, leurrage, holdover, intégrité, OSNMA et carte d'interférence, chacun avec des exercices.
  • Étude de l'URA maximale du jalon 3 ARAIM du WG-C UE-États-Unis (xval/araim-m3/, src/bin/gen_araim_m3_study.rs), remplaçant le plan retiré « Table A-3 » ; MODELLED avec des écarts déclarés.
  • Brouillons pour approbation du propriétaire sous docs/drafts/ : article JOSS, amendement de la charte du TSC, processus de registre des références indépendantes et une proposition de scission de LICENSES/. Rien de cela n'est adopté.
  • Vues Studio pour les fonctionnalités de la 0,38 (kshana.dev/studio/). Relecture de passerelle (deux exécutions synthétiques sur une même horloge : trace, score de confiance, les satellites que le journal entend et le verdict, avec les propres indicateurs du récepteur à côté des alarmes de Kshana) ; PNT optique (les deux scénarios optical-atmosphere, avec une réalisation [timeseries] à germe fixé optionnelle, MODELLED) ; essai de holdover (le résultat holdover-test mesuré par rapport aux gabarits de l'ITU-T, tracé à partir du propre record.series du résultat) ; une visionneuse de l'observatoire des interférences qui ouvre les fichiers que vous avez produits et n'en fournit aucun ; dans la page Outils, un calcul de score Jammertest, un ajustement IMU et MQTT comme format de télémétrie ; et dans Confiance un sélecteur de format de journal (RTKLIB .pos, NovAtel OEM7, RTCM 3, GNSS-SDR, Septentrio SBF) avec un fichier IMU optionnel. Chaque vue lit des fichiers dans le navigateur et ne téléverse rien ; chaque chiffre conserve l'étiquette que le registre lui attribue, et chacune porte l'énoncé à titre consultatif. La page de site /benchmark affiche le fragment kshana bench leaderboard.

Corrigé#

  • Issue #36 : couches d'épinglage exactes à l'octet. Les couches d'épinglage exactes à l'octet ne s'exécutent que sur un hôte déclaré comme référence de base (KSHANA_EXACT_PINS=1, défini par scripts/gate.sh), et non sur chaque Mac Apple silicon, parce que la bibliothèque mathématique d'Apple diffère d'une version de macOS à l'autre ; la couche portable s'exécute partout, et tests/exact_pin_gate_guard.rs empêche qu'une couche exacte à l'octet soit de nouveau conditionnée par la seule plateforme. Les comparaisons avec les références indépendantes elles-mêmes réussissent sur macOS. Aucune valeur littérale n'a été reprise et aucune tolérance n'a changé. scripts/oracle-triage.sh et docs/LOCAL-ORACLE-TESTS.md indiquent comment trier une différence ; .github/workflows/oracle-macos.yml est un diagnostic manuel et hebdomadaire, et non une barrière.
  • CodeQL : un motif non ancré dans l'assistant d'ouverture de confiance du Studio correspond désormais à l'en-tête entier (web/studio/lib/trust-open.mjs).
  • CI : disque du runner. Le job check construit les profils de développement et de test sans informations de débogage, de sorte que l'édition de liens ne remplit plus le disque.
  • Garde-fous de sources. Chaque fichier source qui contient des fixtures de test porteuses d'épinglages déclare sa portée d'épinglage, et les tests qui écrivent des fichiers temporaires utilisent un chemin unique par appel, de sorte que les exécutions parallèles ne peuvent pas entrer en collision.
  • docs/SCENARIOS.md est régénéré pour le champ optionnel timeseries d'optical-atmosphere.
  • Greffon JetBrains : aucun usage d'API de plateforme obsolète ou prévue pour suppression. L'IntelliJ Plugin Verifier (verifyPlugin) sur IntelliJ IDEA build 263 (2026,3 : 263.6800.24 et 263.7031.23) a trouvé un appel obsolète, FileEditorManager.openFile, dans Insert Example ; il ouvre désormais le nouveau fichier avec OpenFileDescriptor. Le greffon est compatible avec 2024,3 (le since-build, inchangé) et les deux builds 263, et sans avertissement sur ceux-ci. La CI exécute désormais verifyPlugin et échoue sur les problèmes de compatibilité et sur tout usage d'une API prévue pour suppression.

[0.37.0] - 2026-10-17#

Ajouté#

  • PNT optique à travers l'atmosphère (type de scénario optical-atmosphere, docs/OPTICAL-ATMOSPHERE.md, note de conception docs/design/optical-atmosphere-0.37.md). Pour une liaison optique et un ensemble de sites au sol, il rapporte la perte par ciel clair dépendant de la longueur d'onde et de l'élévation, l'état de turbulence de Hufnagel-Valley (variance de Rytov, indice de scintillation, évanouissements gamma-gamma, moyennage d'ouverture), la disponibilité par rapport à la marge de liaison à partir d'un climat nuageux énoncé, la marge nécessaire pour des disponibilités visées et le plafond qu'aucune marge ne relève, la distribution des durées d'interruption, l'erreur de synchronisation temporelle et de télémétrie par interruption à travers le modèle de holdover de l'horloge, la diversité de sites corrélée à la distance, et les gains hypothétiques d'un changement de longueur d'onde, d'une plus grande ouverture, d'une réduction de scintillation par optique adaptative et d'une marge supplémentaire. optical_linkbudget gagne un bilan de liaison tenant compte de l'atmosphère ; sans lui, sa sortie est identique au bit près à 0,36 (seuil A5). Deux scénarios fournis portent des climats nuageux ILLUSTRATIVE. MODELLED : trois lignes du registre. Les calculs atteignent les seuils A1 à A6 préenregistrés dans xval/optical-atmosphere/PREREGISTRATION.md par rapport à un programme mpmath indépendant ; cela vérifie l'implémentation des formules énoncées, et non l'atmosphère, et aucun enregistrement de disponibilité mesurée n'a été comparé, de sorte qu'aucune ligne n'est VALIDATED. Le seuil A4 a d'abord été manqué de 3e-9 parce que la fonction de répartition normale utilisée était une approximation à 1.5e-7 ; la fonction de répartition a été remplacée et le seuil laissé tel qu'enregistré. Les builds natif et WebAssembly renvoient des documents identiques à l'octet près pour les deux scénarios fournis (A7, exécuté sur le commit d'intégration 0.37.0).

[0.36.0] - 2026-10-16#

Ajouté#

  • ROC de détection des moniteurs IQ (PRO-32, docs/design/DETECTION-ROC.md). Une campagne avec moniteurs conserve le maximum de la statistique de test de chacun sur les fenêtres d'événements énoncés (positif) et sur des fenêtres juxtaposées en dehors des événements (négatif, roc_window_s). Le rapport les regroupe par type d'alarme en une ROC avec son AUC et le point de fonctionnement au seuil configuré, sous forme de roc.json et d'une section de rapport. Sur des campagnes synthétiques, le contrôle du niveau de hasard est atteint. Le seuil d'AUC du C/N0 (0,95) n'est pas atteint (0,79), parce que les fenêtres négatives situées juste après un événement héritent de la décroissance du CUSUM issue de la détection ; cela est consigné. MODELLED.

  • Moniteurs IQ dans la campagne de relecture en laboratoire (PRO-31, docs/design/MONITORS-IN-CAMPAIGN.md). Une table [monitors] optionnelle dans un fichier de campagne exécute les moniteurs IQ dans la passe unique de l'exécuteur : puissance et spectre après chaque chaîne d'entrée, et C/N0, SQM et verrouillage par canal suivi. Leurs alarmes sont notées par rapport aux événements énoncés : détecté ou manqué, délai de détection, et fausses alarmes par heure d'exposition. Le chiffre de fausse alarme en forme close de chaque test est énoncé, y compris un nouveau chiffre gaussien bilatéral pour les tests SQM (2Q(k)). Sans la table, rien ne change. Sur des campagnes synthétiques, les seuils de fausse alarme de puissance et de SQM et le seuil de fausse alarme du C/N0 sont atteints ; 18 atténuations sur 18 sont détectées, mais la borne du délai de détection, inférieure à un échantillon de détecteur par construction, n'est pas atteinte et est consignée. MODELLED ; ligne du registre « Moniteurs IQ notés dans des campagnes de relecture en laboratoire ».

  • Ajustement de laboratoire à partir de campagnes IQ, suite (tests/iq_labfit_followup.rs, job CI labfit-iq-followup). Il teste les deux hypothèses que le §13,6 de docs/design/LABFIT-FROM-IQ.md a laissées ouvertes, par rapport à des seuils préenregistrés à 1e532f84. Il ajoute deux campagnes synthétiques : S, avec un J/S en escalier (germe 2026_1014), et R, une nouvelle rampe (germe 2026_1015). Les résultats sont dans docs/design/evidence/labfit-followup/RESULTS.md.

    • S1 atteint : avec chaque niveau de J/S maintenu, δ_eff est retrouvé à +0,185 dB près. L'erreur de −1,1 dB des campagnes en rampe est un retard de l'estimateur.
    • S2 non atteint, épinglé par un test qui affirme l'écart : (d) tel qu'écrit sur la campagne en escalier tient pour le modèle de boucle de poursuite (0,45 dB) mais pas pour le modèle empirique (6,42 dB).
    • R1 atteint : sur la nouvelle campagne en rampe, (d) avec les temps de maintien de chute ajustés, auxquels s'ajoute la vitesse de rampe de chaque événement, est à moins de 1 dB pour les deux modèles.
    • Les écarts (a′) et (d) se reproduisent sur R.
    • Une campagne peut désormais énoncer son J/S sous forme de profil step dans le banc de test.
    • Aucun verdict du §13 ne change, et la ligne du registre reste MODELLED.
  • Accrochage FLL plafonné, optionnel (DS-LOOP-05) : une nouvelle clé de conception de boucle [design.carrier] fll_pull_in_max_s (s), Rust LoopConfig::fll_pull_in_max_s. Avec fll_assist = "pull-in", elle force la passation de la FLL à la PLL après cette durée, quel que soit le PLI. Non définie par défaut, et alors hors du hachage de conception ; la conception par défaut et son hachage sont inchangés.

    • Vérifié par rapport à des seuils préenregistrés à 58789af0, sur une vérité injectée. Le témoin est atteint : la valeur par défaut ne passe jamais la main dans 9 germes sur 10 à 33 dB-Hz.
    • Non atteint : avec un plafond de 1,0 s, 16 exécutions sur 20 conservent le verrouillage à 33 dB-Hz et 8 sur 20 à 31 dB-Hz ; les autres alternent entre des passations forcées et le retour de la FLL. La gigue de phase vaut 1,8× celle de la PLL seule à 33 dB-Hz.
    • Le plancher d'accrochage d'environ 35 dB-Hz reste la limite documentée de la valeur par défaut.
    • MODELLED ; ligne du registre « Accrochage FLL plafonné en dessous du plancher de passation FLL vers PLL de la conception par défaut (optionnel) ».
  • Hystérésis d'acquisition et quantificateur de la chaîne d'entrée dans le type de scénario jamming (CAP-06c) : deux sections optionnelles pour un scénario jamming.

    • [acquisition] : acquisition_threshold_dbhz (dB-Hz, au seuil de poursuite ou au-delà) et reacquisition_delay_s (s, 0 par défaut). Un satellite est acquis au seuil d'acquisition ou au-delà, une fois qu'il est resté non acquis pendant le délai. Il est conservé tant qu'il est au seuil de poursuite ou au-delà. Sorties : epochs[].sats[].acquired (vrai/faux), epochs[].acquired (décompte) et fom.availability_acquired (1).
    • [front_end] : adc_bits (de 1 à 16) et bandwidth_mhz (MHz, deux fois le débit de chips par défaut). Produit un bloc front_end : agc_gain_reduction_db (dB, 10·log10(1 + J/N)), quantiser_loss_db (dB, retirée du C/N0 effectif de chaque liaison) et loss_model. La perte est celle pour une entrée gaussienne, signalée comme non valide pour les brouilleurs CW, à bande étroite et à balayage.
    • Sans les sections, toutes les sorties sont identiques à l'octet près.
    • Vérifié par rapport à des seuils préenregistrés à 70c72fcc. La perte du quantificateur est à moins de 0,0007 dB d'un Monte Carlo indépendant, et la lecture AGC à moins de 0,012 dB de la boucle AGC de la couche IQ.
    • Les exécutions d'hystérésis enregistrées n'étaient pas informatives (toutes les liaisons perdues), de sorte que ce seuil est NOT MET. Un jeu d'exécutions supplémentaire enregistré à 37793290 l'atteint : chaque indicateur égale un recalcul indépendant, et 732 liaisons sur 1824 montrent l'hystérésis.
    • Constat : avec un brouilleur CW, un CAN à 1 bit perd environ 5 dB de plus que le chiffre gaussien.
    • MODELLED ; ligne du registre « Hystérésis d'acquisition et quantificateur de la chaîne d'entrée dans le type de scénario jamming par rapport à des recalculs indépendants ».
  • Masquage du brouilleur par le relief dans le type de scénario jamming (CAP-06b) : une section [terrain] optionnelle dans un scénario jamming avec un brouilleur. Champs :

    • dem_hgt : une tuile SRTM .hgt, relative au répertoire de travail ;
    • samples_per_side, ll_lat_deg et ll_lon_deg (deg) : la taille et le coin de la tuile ;
    • geoid_undulation_m (m, 0 par défaut), k_factor (4/3 par défaut) et profile_step_m (m, 30 par défaut).

    Le moteur échantillonne le profil de terrain le long du grand cercle entre le brouilleur et le récepteur et trouve l'arête en lame de couteau dominante. La puissance reçue du brouilleur, et donc chaque J/S, est abaissée de la perte d'une seule arête en lame de couteau de l'ITU-R P.526-15 §4,1.

    • Le résultat gagne un bloc jammer_terrain : nu_max (1), diffraction_loss_db (dB), obstacle_distance_m (m), obstacle_terrain_m (m), path_length_m (m) et profile_points (décompte).
    • Sans la section, toutes les sorties sont identiques à l'octet près.
    • Vérifié par rapport à des seuils et à dix emplacements préenregistrés à 92cd2bfd, sur la vraie tuile SRTM versée de la Vallée de la Mort, par rapport à un recalcul numpy indépendant. Tous atteints : pire différence 1.6e-10 sur ν et sur la perte (seuil 1e-9), la perte monotone selon la hauteur du brouilleur, et la perte abaissant le J/S exactement d'elle-même.
    • MODELLED ; ligne du registre « Masquage du brouilleur par le relief dans le type de scénario jamming par rapport à un recalcul numpy indépendant sur une vraie tuile SRTM ».
  • Gains d'antenne CRPA dans le type de scénario jamming (CAP-06a) : une section [crpa] optionnelle dans un scénario jamming. Champs : elements_enu_m (positions des éléments en est-nord-haut local, m), weighting ("null-steering" ou "mvdr"), et bandwidth_mhz (largeur de bande de bruit MVDR, MHz, deux fois le débit de chips par défaut).

    • Chaque canal forme un faisceau sans distorsion vers son satellite. Le bruit de la liaison est mis à l'échelle par ‖w‖² et le brouilleur par |wᴴa_j|² avant l'équation C/N0 anti-brouillage existante.
    • Chaque liaison gagne un bloc crpa : array_noise_gain_db (dB) et jammer_gain_db (dB).
    • Sans la section, toutes les sorties sont identiques à l'octet près.
    • Une section invalide (une liste d'éléments vide, une pondération inconnue, une largeur de bande non positive) est une erreur, par kshana et api::run_toml aussi bien que par jamming::run_jamming.
    • Vérifié par rapport à des seuils préenregistrés à 08d83b4d. Atteints : additivité (après une correction : la première construction avait ajouté les nouvelles unités à la table d'unités de chaque exécution de brouillage) ; un élément n'est pas un réseau ; gain de bruit et C/N0 effectif par rapport à un recalcul numpy indépendant à moins de 1e-9 dB ; le MVDR tend vers l'annulation à JNR élevé.
    • Non atteint : le gain du brouilleur en MVDR sur 194 liaisons sur 456 avec les mathématiques portables de la 0,36 (202 avec les mathématiques de l'hôte ; docs/revisions/STUDIO15-batch4-rebaseline.md) (pire 1.7e-6 dB). Les résidus de −100 à −188 dB sont sous la résolution du float64 à ce seuil, et numpy est en désaccord avec lui-même du même ordre.
    • MODELLED ; ligne du registre « Gains d'antenne CRPA dans le type de scénario jamming par rapport à un recalcul numpy indépendant ».
  • Moteur de suivi IQ par rapport à GNSS-SDR 0.0.19 (PRO-33) : kshana iq track et GNSS-SDR suivent les mêmes enregistrements numpy indépendants de GPS L1 C/A de 30 à 45 dB-Hz.

    • Seuils préenregistrés à 48edd4a5. L'étalonnage enregistré a échoué sur une passation GNSS-SDR erronée (F3), de sorte que l'amendement 1 (1e4288c4) ajoute aux deux récepteurs une FLL limitée à l'accrochage, commité avant tout enregistrement de test.
    • Atteints : la gigue de porteuse et de code et le Doppler concordent à 5 % près à chaque C/N0.
    • Non atteints : le C/N0 NWPR du moteur lit 2,3–7,1 dB sous le SNV de GNSS-SDR (F4, une limite connue de l'estimateur ; le M2M4 est à moins de 0,06 dB de la vérité) ; les indicateurs de verrouillage diffèrent par définition (F5) ; un désaccord sur un décrochage à 30 dB-Hz (F6).
    • MODELLED ; ligne du registre « Moteur de suivi IQ par rapport à GNSS-SDR 0.0.19 sur des enregistrements indépendants ».
  • Deux lignes VALIDATED pour des codes de la couche IQ (DS-GIQ-06b, PRO-39).

    • BeiDou B1I. Les 63 codes primaires B1I concordent avec le générateur indépendant de GNSS-SDR v0.0.19 chip pour chip (seuil préenregistré à 911106d1). Seule la sortie de ce programme est versée : les codes PRN B1I que définit l'ICD public, sous forme de préfixe et de hachage.
    • GPS L1C. Les 126 codes L1CP/L1CD et les 63 recouvrements L1CO concordent avec les colonnes de contrôle qu'imprime l'IS-GPS-800J, et la séquence de Legendre calculée concorde avec sa Table 6.2-1 (seuils préenregistrés à fe372e26).
    • Lignes : « Codes de télémétrie primaires BeiDou B1I par rapport à un générateur indépendant » et « Codes de télémétrie et de recouvrement GPS L1C par rapport aux colonnes de contrôle imprimées de l'IS-GPS-800J ».
  • Bandes GLONASS, BeiDou et Galileo E6 dans le modèle de spectre (CAP-12, signaux) : nouveaux noms de bandes glonass-l1of et glonass-l2of (tout canal FDMA sous la forme glonass-l1of-k<K>, K = −7 à 6), beidou-b1i, beidou-b1c, beidou-b2a, beidou-b3i et galileo-e6. Chacune porte la porteuse, la modulation et la puissance reçue minimale de son ICD. Elles sont optionnelles, par le nom : l'ensemble de bandes par défaut et toutes les sorties existantes sont inchangés.

    • Vérifié par rapport à des seuils préenregistrés à 5806f28b : les valeurs de l'ICD, les zéros, le composite B1C et le chemin C/N0 sont atteints.
    • Deux seuils n'ont pas été atteints. Le seuil d'aire unitaire était inatteignable tel qu'écrit (F1). Les formes d'onde B1I et B1C de la couche IQ ne concordent avec le modèle que moyennées sur la bande, à cause des spectres de raies inégaux de leurs codes (F2).
    • MODELLED ; ligne du registre « Modèle de spectre : bandes GLONASS, BeiDou et Galileo E6 (optionnel) ».
  • Option CFAR à moyennage de cellules dans l'acquisition IQ (PRO-37) : iq::acq::ca_cfar et ca_cfar_cells décident sur une grille d'acquisition en comparant chaque cellule à la moyenne de cellules de référence de sa rangée Doppler. Le seuil provient de la probabilité de fausse alarme CA-CFAR en forme close pour M blocs non cohérents (ca_cfar_pfa, ca_cfar_alpha), de sorte que la décision ne dépend pas de la normalisation de la puissance d'échantillon. Elle est optionnelle ; le détecteur par défaut et toutes les sorties existantes sont inchangés.

    • Vérifié par rapport à des seuils préenregistrés à 3724aefa : la forme close par rapport au Monte Carlo (18 cas sur 18), et un taux de conception de 1 % mesuré à 0,97–1,01 % sur bruit gaussien et sur bruit quantifié sur 2 bits.
    • Un seuil n'a pas été atteint : sur un signal sur 2 bits sans bruit, 1,28 % des cellules hors pic dépassent le seuil, aux lobes secondaires de corrélation du code (constat F1).
    • MODELLED ; ligne du registre « Option CFAR à moyennage de cellules dans l'acquisition IQ ».
  • Modèle de scintillation par rapport à des données mesurées (PRO-34) : le modèle de scintillation de Cornell du canal IQ a été comparé à l'intensité et à la phase GPS L1 mesurées à 50 Hz lors d'une nuit de scintillation équatoriale (enregistrement Zenodo 16941224, INGV, Malindi, CC BY 4,0), sous des seuils préenregistrés à b6ccb499. Atteints : la distribution de l'intensité et la scintillation de phase liée à S4. Non atteint : le modèle s'évanouit 2,4 fois plus souvent sous −10 dB et 3,5 fois plus longtemps (constat F1). Le traitement enregistré lit la phase repliée du modèle (constat F2) ; le résultat de phase tient une fois celle-ci dépliée. scripts/fetch_scint_malindi.sh récupère les données. La ligne reste MODELLED : « Canal de scintillation ionosphérique IQ (modèle de Cornell) par rapport à une scintillation GPS L1 mesurée à 50 Hz ».

  • Lecteur d'échantillons LuGRE corrigé (MR-09) : realdata::lugre::parse_iqs_sdrx lit un lot IQ LuGRE avec I dans le quartet de poids fort et les niveaux à pas médian 2v + 1 (SdrLayout::mid_rise), qui retirent la moyenne de −½ que portent sur I et Q les entiers bruts en complément à deux. run_acq.py --corrected donne à GNSS-SDR la même lecture. Le lecteur ION générique et toutes les sorties existantes sont inchangés : 149 résultats de scénario et une étude sont identiques à l'octet près avant et après, et les constats LuGRE épinglés se lisent comme enregistrés (xval/lugre-reader/RESULTS.md). Aucune ligne du registre ne change.

  • Suivi BOC(1 1) optionnel (CAP-07 (a)) : LoopConfig::boc remet à l'échelle les discriminateurs du DLL pour le pic principal du BOC(1 1) en sinus et ajoute un moniteur de saut de bosse (corrélateurs très en avance et très en retard à ±0,5 chip, compteurs haut/bas, N = 8) qui écarte le NCO de code d'un pic latéral ; Channel::bump_jumps liste les sauts. Désactivé par défaut, et toutes les sorties existantes sont inchangées. Vérifié par rapport à des seuils préenregistrés à 6b68f6cc sur un signal BeiDou B1C synthétique : un départ sur pic latéral qui reste à 0,55 chip sans l'option est ramené sur le pic principal par un saut à 0,08 s avec elle, et aucun faux saut n'a été observé depuis le pic principal. Un seuil n'a pas été atteint : la grille de tests unitaires pour la mise à l'échelle sort de la plage linéaire des discriminateurs (constat F1 dans docs/design/evidence/boc-bump-jump/RESULTS.md). MODELLED ; ligne du registre « Suivi BOC(1 1) : mise à l'échelle du DLL et résolution d'ambiguïté par saut de bosse (optionnel) ».

  • Ajustement de laboratoire à partir de campagnes IQ (B7.1, docs/design/LABFIT-FROM-IQ.md). Le [input] campaign = "<out-dir>" d'un scénario labfit ajuste un dossier de sortie kshana iq campaign en CLI (kshana iq labfit), en Python (kshana.iq_labfit) et dans l'outil labfit du MCP (dossiers situés uniquement dans son répertoire de travail). Il ajuste une unité par signal, conception de boucle, chaîne d'entrée et type de brouilleur :

    • le modèle de C/N0 par rapport à un J/S énoncé, avec censure ;
    • le seuil de poursuite, directement et en forme close ;
    • les modèles de verrouillage de boucle de poursuite et empirique, couplés par le modèle de C/N0, avec leurs temps de maintien ;
    • un bootstrap par grappes à germe fixé sur les enregistrements, des intervalles de prédiction à 90 %, et des jeux réservés par exclusion d'un enregistrement à la fois ;
    • une table [validation] préenregistrée, hachée, avec PASS/FAIL par seuil.

    Le rapport est kshana.labfit-iq/1 en JSON, CSV et Markdown, avec un bloc d'unités. Q_eff n'est pas identifiable à partir des données de C/N0 sans mesure de puissance indépendante. Il est énoncé, jamais ajusté, et le paramètre ajusté est delta_eff = delta - 10 log10 Q (amendement de conception du 2026-10-12). Un type de brouilleur inconnu prend le Q énoncé le plus dommageable (cw, 1). Sur des campagnes synthétiques issues des propres scènes de Kshana, le seuil de couverture sur jeu réservé (c) est franchi. Les seuils delta_eff (a') et (b') (0 campagnes couvertes sur 50) et le seuil (d) portant sur le seuil de poursuite en forme close ne sont pas atteints : ils sont consignés avec leurs valeurs. MODELLED ; ligne du registre « Étalonnage des modèles de C/N0 et de verrouillage du récepteur ouvert sur les résultats de campagnes IQ, avec une erreur de prédiction énoncée ». Le chemin labfit à partir de journaux de récepteur et ses sorties sont inchangés.

  • solar-system sur un noyau JPL (CAP-31) : planetary_kernel_path prend chaque corps que contient le SPK (avec de440s : Mercure, Vénus, la Terre, la Lune) dans le noyau, étiquette KERNEL, et ajoute un bloc kernel uniquement lorsqu'il est défini. Nouvelle ligne, VALIDATED par rapport à SPICE (préenregistré f8e946ea ; pire 3.3e-5 m, 1.0e-11 m/s). Le rapport par défaut est inchangé.

  • Porkchop sur l'éphéméride DE440 (CAP-20b) : maneuver::porkchop_kernel balaie C3 et le V∞ d'arrivée sur des états héliocentriques issus d'un SPK DE440. Nouvelle ligne, VALIDATED par rapport à des états SPICE

    • pykep 3.0.1 (préenregistré 2d857fb1 ; Terre vers Mars 2026-2028, 304 cellules, pire 2.6e-14, la même cellule de C3 minimal).
  • Macro-modèle non gravitationnel de LRO : NOT MET (DS-LRO-10, préenregistré e82047e2). lunar_od::LunarMacroModel (optionnel via LunarForceModel::macro_model) : rayonnement solaire direct sur plaques planes avec l'ombre de la Lune, un panneau suivant le Soleil, et albédo lunaire et infrarouge thermique ; LunarMacroModel::lro_generic est une approximation générique étiquetée de LRO à partir de faits publiés (sans plaques du bus : la table des plaques n'a pas pu être obtenue). Sur l'arc LRO de 4 h, il laisse la RMS en dynamique réduite à 6,668 m et la RMS dynamique à 11,94 m, avec un facteur de rayonnement invraisemblable (environ +21 / −22), de sorte que les trois seuils sont manqués. Le constat est épinglé par un test, et aucune sortie par défaut ne change (docs/design/evidence/ds-lro-10-macro-model/RESULTS.md). Le SRP lunaire en boulet de canon optionnel utilise désormais le cône d'ombre de la Lune au lieu de celui de la Terre (forces::conical_shadow_body).

  • OD lunaire : marée solide k2 et relativité sélénocentrique optionnelles (DS-LRO-11), désactivées par défaut (LunarForceModel::lunar_tide, ::relativity) ; un commutateur KSHANA_LRO_DEGREE pour la validation croisée ANISE (DS-LRO-04) ; une fixture d'arc LRO de 24 h et un ajustement d'arc long à titre d'information seulement (DS-LRO-09). Les exécutions d'information sont consignées dans docs/design/evidence/ds-lro-09-11-longer-arc/RESULTS.md ; aucun nombre publié ne change.

  • NRHO 9:2 CR3BP par rapport à CAPSTONE (CAP-29d) : nouvelle ligne MODELLED mesurant la NRHO circulaire restreinte du moteur par rapport à l'orbite volée de CAPSTONE (JPL Horizons, mars 2023 ; préenregistré 4e868170) : période 1,07 %, apolune 0,05 %, périlune 4,1 % par rapport aux moyennes de CAPSTONE, à l'intérieur des seuils enregistrés de 3 / 5 / 20 %. Une mesure, et non une validation.

  • États tournants CR3BP vers l'ICRF centré sur la Lune (RM-34, FUT-06) : cr3bp::to_moon_centred_icrf / from_moon_centred_icrf / to_moon_centred_icrf_de440 projettent un état tournant adimensionné Terre-Lune sur la ligne Terre-Lune instantanée de DE440, y compris la vitesse hors plan du référentiel. Nouvelle ligne, VALIDATED par rapport à un référentiel SPICE à deux vecteurs (préenregistré 2313eb1b, amendé avant toute exécution d5ef79b3 ; 72 cas, pire 1.8e-7 m et 1.2e-9 m/s).

  • Membres de familles CR3BP par rapport à l'API Three-Body Periodic Orbits du JPL : NOT MET (RM-35, préenregistré a9074f65). cr3bp_family (correction de halo, de NRHO et de DRO, indice de stabilité de la monodromie, continuation par pseudo-longueur d'arc) concorde avec 54 membres de l'API sur 58 sur chaque seuil (état, période et Jacobi à moins de 1e-10 partout). Un indice de stabilité de halo L1 (9.5e-2) et trois fermetures de petites DRO (1.5e-8 à 3.3e-8 contre 1e-8) échouent, de sorte que le module est #[doc(hidden)] et qu'aucune ligne ne le revendique. Résultats : docs/design/evidence/cr3bp-families/RESULTS.md.

  • Orientation et environnement lunaires DE440 optionnels (FUT-05, DS-LRO-08 ; valeurs par défaut inchangées) : lunar_frame::try_icrf_to_moon_pa_de440, lunar::try_mci_to_mcmf_de440 / try_mcmf_to_mci_de440 (ancrés sur l'époque, axes principaux DE440) et lunar_od::De440LunarEnvironment (orientation PA DE440 intégrée plus le Soleil et la Lune géocentriques à partir d'un SPK DE440 fourni par l'utilisateur). Par rapport à ANISE (préenregistré ea537710) : orientation à moins de 3.5e-7 rad et ajustements LRO à moins de 1 mm, mais le volet éphéméride a manqué son seuil (Soleil 30,7 m, Lune 1,1 m, un décalage temporel d'environ 1 ms du côté d'ANISE), ce n'est donc pas une ligne validée. Résultats : docs/design/evidence/fut05-de440-lunar-env/RESULTS.md.

  • Datum de la campagne du référentiel lunaire, seuil NumPy mis à l'échelle du conditionnement : NOT MET (préenregistré b887eb05 ; reste MODELLED). L'étape 0 écarte le repli par pseudo-inverse comme cause de l'écart de 0,30 des stations estimées ; NumPy concorde dans le seuil sur six scénarios sur huit, mais stations_estimated le manque (6.8e-6 contre 5.9e-7), et à la date nouvelle 2026-12-01 une balise non observée du pôle sud rend l'information des balises déficiente en rang, ce que la référence indépendante inchangée ne peut pas évaluer. Résultats : docs/design/evidence/mr05-lunar-datum-cond/RESULTS.md.

  • Datum du référentiel lunaire à partir d'une vraie campagne d'observation (Lune analytique) VALIDATED sur des points normaux EDC de 2025 nouveaux (préenregistré 31f5283 avant qu'aucun ne soit récupéré) : la référence indépendante SPICE et NumPy inchangée concorde sur la comptabilité, les rangs et le couplage nul, et à moins de 1.11e-3 sur les sigmas (seuil 1e-2), 8.95e-4 sur le conditionnement et 1.79e-3 sur les rapports transversal/longitudinal (seuil 2e-2). Un contrôle de bibliothèque du seul calcul de covariance ; les seuils ne discriminent pas les modèles de Lune. Résultats : docs/design/evidence/mr06-llr-analytic-fresh/RESULTS.md.

  • Orientation IAU et GM des quatorze corps du système solaire ajoutés, séparés de la ligne « Constantes physiques de chaque corps du système solaire » en une ligne VALIDATED (préenregistré 154bc54) : Body::iau_rotation_et concorde avec pxform de SPICE sur pck00011 à moins de 1e-9 rad sur 574 matrices aux époques d'origine et sur 574 à 41 époques nouvelles jamais comparées auparavant (pire Phobos 1.38e-10 rad), et Body::mu égale gm_de440 pour les quatorze corps. Le reste de la ligne d'origine (J2, rayon moyen, le rapport) reste MODELLED. Résultats : docs/design/evidence/mr08-body-orientation/RESULTS.md.

  • Lambert multi-révolutions (maneuver::lambert_multirev) : toutes les solutions jusqu'à trois révolutions, les deux branches. Nouvelle ligne du registre, VALIDATED par rapport à pykep 3.0.1 (préenregistré a75de851 ; 382 cas, 1058 solutions, pire différence de vitesse 1.6e-13 contre 1e-8). Le garde-fou interne d'atterrissage de Kepler a trouvé une limite de maneuver::kepler_universal sur un arc à e = 0,994 ; elle est consignée dans docs/design/evidence/lambert-multirev/RESULTS.md.

  • Pression de radiation solaire en boîte et ailes et ECOM2 (DS-PA-14), optionnelle. srp_boxwing : un modèle boîte et ailes à plaques planes avec les tables Galileo FOC/IOV issues des métadonnées de satellites du GSC, en pilotage de lacet GNSS nominal, avec facteur de radiation et dérivées partielles par panneau, et le modèle empirique ECOM2 avec ses dérivées partielles. Sélectionné avec ForceModel::box_wing_srp / PreciseForceModel::box_wing_srp (champs srp_boxwing, None par défaut : le chemin du boulet de canon et toutes les valeurs de référence sont inchangés) ; avec un jeu boîte et ailes, cr est son facteur de radiation. Comparé à Orekit 12,2 sous un préenregistrement (xval/srp-boxwing-orekit/) : tous les seuils atteints, environ 1e-15 en relatif ; VALIDATED comme évaluation de modèle, la prédiction de la SRP de Galileo reste MODELLED.

  • Ombre de SRP pour Terre aplatie et assombrissement centre-bord solaire (FUT-09, RM-11). Nouveau module srp_shadow : oblate_conical_shadow (ellipsoïde occultant WGS-84), limb_darkened_shadow (loi d'Eddington) et ShadowModel, sélectionnés avec ForceModel::srp_shadow (par défaut : l'ombre conique sphérique existante, inchangée) ; forces::srp_accel_with_lit_fraction. L'ombre aplatie concorde avec le rapport d'éclairement d'Orekit 12,2 à moins de 7.4e-9 sur 2400 géométries (VALIDATED, xval/srp-oblate-shadow-orekit/) ; l'assombrissement centre-bord n'a aucune référence externe indépendante (MODELLED).

  • Thermosphère NRLMSISE-00 (FUT-08, RM-10, DS-PA-13). nrlmsise00 : un portage de gtd7 et gtd7d (commutateurs, modes Ap journalier et tableau ap toutes les 3 heures) à partir de la version C du domaine public du Fortran du NRL. Il est identique au bit près à ce portage C et à moins de 1.9e-6 en relatif de pymsis 0.13.0 (Fortran du NRL, simple précision) sur une grille de 720 points, et il reproduit les 17 cas de test publiés (VALIDATED ; xval/nrlmsise00-pymsis/). Cela valide le portage, et non la précision du modèle par rapport à une densité mesurée.

  • Niveau de densité de traînée NRLMSISE-00 optionnel. forces::DensityModel::{Exponential, Nrlmsise00 { f107a, f107, ap }}, forces::drag_accel_with_density, density_at et propagator::ForceModel::drag_density. Le modèle exponentiel statique reste le choix par défaut, bit pour bit. La météorologie spatiale est constante par modèle. VALIDATED au niveau de l'orbite par rapport à la propre traînée NRLMSISE-00 d'Orekit 12,2 sur 24 h (pire 0,03 m pour un déplacement dû à la traînée allant jusqu'à 142 km ; xval/drag-tier-orekit/).

  • Soleil et Lune DE440 optionnels dans le propagateur de Cowell (RM-33, FUT-10). propagator::ForceModel::with_ephemeris accepte tout EphemerisProvider (par exemple un KernelEphemeris DE440) pour les termes de troisième corps et de SRP ; il refuse un fournisseur qui ne peut pas servir l'époque, compte les replis sur la série analytique, et est désactivé par défaut. EphemerisProvider::relative_position_jd2 conserve la précision en deux parties. Par rapport à Orekit 12,2 sur son propre lecteur DE440, les orbites de 24 h concordent à 0,017 m ; le seuil préenregistré de position du Soleil et de la Lune a été manqué (6,4 m / 0,24 m ; SPICE montre le même écart), donc MODELLED (xval/propagator-de440-orekit/).

  • Marée atmosphérique S1 optionnelle (DS-PA-03). tides::atmospheric_tide_s1 et s1_air_tide_acceleration (Biancale & Bode 2006, GFZ STR06/01 Table 1 modèle N1, degrés 2–6), activés avec air_tide_s1() sur propagator::ForceModel et precise_od::PreciseForceModel ; désactivés par défaut. MODELLED (coefficients revérifiés par rapport à la table publiée ; aucune référence externe indépendante pour l'effet de la force).

  • Détermination d'orbite par lot en vitesse radiale et azimut/élévation avec masque d'élévation (RM-36, FUT-13). orbit_determination::determine_orbit_batch_tracking, simulate_tracking, predict_tracking, propagate_with_stm (STM variationnelle avec dérivées partielles analytiques à deux corps + J2), is_visible, measurement_with_partials ; batch_ls::gauss_newton_analytic. Le chemin par mesures de distance seules est inchangé. Comparé aux moindres carrés par lot d'Orekit 12,2 sur 8 scénarios préenregistrés : tous les seuils atteints sauf la concordance d'état sans bruit (≤ 1 cm), manquée sur 2 scénarios sur 4 à 1,46 et 1,74 cm avec kshana à moins de 1e-8 m de la vérité ; consigné, MODELLED.

  • Pondération de précision SP3 (DS-PA-06). sp3::parse_sp3_accuracy et Sp3Accuracy::position_sigma_m associent les codes de précision de l'en-tête et de chaque enregistrement à des sigmas d'observation ; une variante d'ajustement Galileo pondérée par SP3 (RMS 3D de niveau 2 de 0,035 m contre 0,070 m sans pondération) est ajoutée à côté des exécutions enregistrées inchangées. MODELLED.

  • Job de déclenchement de l'arc complet Swarm-A (DS-PA-08) dans .github/workflows/agency-od-validation.yml.

  • Gravité planétaire à partir des tables PDS SHADR (CAP-30, partie de CAP-31). SphericalHarmonicField::from_shadr (src/gravity_pds.rs) lit Mars GMM-3 (d/o 120) et GRAIL GL0660B (d/o 660) ; Body::with_gravity_field attache tout champ chargé (valeurs par défaut inchangées). Des extraits de degré 20 sont fournis (NASA PDS, domaine public ; tests/fixtures/planetary_gravity/NOTICE.md) ; les fichiers complets sont récupérés par xval/planetary-gravity-pyshtools/fetch_data.sh. VALIDATED par rapport à pyshtools 4.14.1 (à moins de 4e-15 de la gravité totale à d/o 120 sur toute la sphère, 5e-14 à d/o 660 pour |lat| ≤ 60°) ; le câblage dans le référentiel du corps reste MODELLED (le référentiel natif de chaque champ n'est pas le référentiel IAU utilisé).

  • Gravité de haut degré jusqu'au degré 2190 (RM-14, FUT-07). SphericalHarmonicField::acceleration_hf / potential_hf (colonne avant modifiée de Holmes–Featherstone, sans sous-dépassement, sans singularité polaire), prepare_high_degree, un chargeur ICGEM en flux from_gfc_file / from_gfc_reader (contrôles de norme et de degré maximal, système de marée consigné, termes variables dans le temps rejetés), et scripts/fetch_egm2008.sh (EGM2008 complet, SHA-256 épinglé, non fourni ; tests conditionnés par KSHANA_EGM2008_GFC). propagator::FieldEvaluator le sélectionne sur le Geopotential optionnel. Concorde avec Orekit 12,2 à 7.3e-17 m/s² jusqu'au degré 2190, et une orbite 200×200 de 24 h concorde à 0,13 m. MODELLED : pyshtools a manqué le seuil préenregistré près du pôle (attribué à pyshtools) et le contrôle de sensibilité au degré 70 de l'orbite a été manqué (0,73 m < 1 m) ; les deux sont consignés dans xval/.

  • Intégrateur DOP853 (FUT-11). integrator::integrate_dop853, integrate_dop853_checked, integrate_dop853_dense (sortie dense d'ordre 7), dop853_step, dop853_initial_step, avec un garde-fou de pas à échec fermé ; propagator::Integrator::Dop853, propagate_dop853, propagate_dop853_checked. Le pilote par défaut est inchangé. VALIDATED par rapport à SciPy 1.18.1 solve_ivp(method="DOP853") : pas isolés à moins de 5.6e-15, séquences de pas identiques, états finaux à moins de 1.6e-12 (xval/dop853-scipy/).

  • Résolveur de Kepler robuste (FUT-12). Nouveau module kepler : solve_kepler_markley (point de départ de Markley 1995, résidu sans annulation) pour tout 0 ≤ e < 1, enveloppé par propagator::solve_kepler_robust. VALIDATED par rapport à des racines mpmath à 50 chiffres à 0,9 ε·|E| jusqu'à e = 0,999999 (xval/kepler-mpmath/).

  • Gravité terrestre tessérale optionnelle dans le propagateur de Cowell (RM-09). propagator::ForceModel gagne geopotential: Option<Geopotential> (with_geopotential, with_egm2008(nmax)). Il évalue un SphericalHarmonicField (EGM2008 fourni jusqu'au degré/ordre 70, ou tout .gfc ICGEM) dans un référentiel terrestre fixe atteint par l'angle de rotation de la Terre (EarthFixedFrame::Era) ou par la chaîne CIO GCRS vers ITRS (EarthFixedFrame::Cio). None par défaut : aucune sortie existante ne change. VALIDATED par rapport à Holmes–Featherstone d'Orekit 12,2 sur 24 h (6 cas, pire 0,036 m), avec les seuils préenregistrés dans xval/cowell-tesseral-orekit/PREREGISTRATION.md.

  • Dates juliennes en deux parties à travers la rotation de la Terre sur le chemin orbital : jd2::gmst82, cio::gcrs_to_itrs_matrix_jd2, frames::teme_to_itrf_jd2 / itrf_to_teme_jd2, orbit::Propagator::position_in_frame_jd2 et own_jd2_utc, conversions From entre jd2::Jd2 et timescales::TwoPartJd, et un two_part_jd = true optionnel pour le scénario ephemeris (ECEF, trace au sol et vue de station ; désactivé et inchangé par défaut, et la clé est omise du hachage du scénario lorsqu'elle est désactivée). Nouvelle ligne du registre, VALIDATED par rapport à pyerfa gmst82/c2t06a (préenregistré b10475ee ; 40 dates : GMST identique au bit près, matrice à moins de 2.7e-14, rotation sur des pas de 1 µs à moins de 1.1e-14 rad, là où le chemin à un seul f64 les manque). L'époque du modèle de force de Cowell reste à un seul f64 ; la raison figure dans sa documentation.

  • Prédiction des EOP au-delà de la table (EopSeries::with_ls_ar_prediction, EopSeries::last_mjd) : une extension optionnelle d'une série IERS d'orientation de la Terre par le prédicteur LS+AR émis à sa dernière ligne, de sorte que les arguments de référentiel d'une époque ultérieure suivent la prévision au lieu de se figer sur la dernière ligne. Les réponses dans la table sont identiques au bit près (testé) ; la série se fige toujours sur la dernière ligne sauf si cela est appelé. La précision de la prévision reste le constat LS+AR existant par rapport au Bulletin A (MODELLED).

  • Décalages du pôle céleste dX, dY sur la chaîne CIO (cio::gcrs_to_cirs_matrix_with_offsets), et contrôles vectoriels ERFA directs de precession_matrix, teme_to_gcrs_matrix et de la nouvelle fonction. Nouvelle ligne du registre, VALIDATED par rapport à pyerfa (préenregistré 979c1e39 ; 40 époques 1950–2100 : précession et CIO identiques au bit près, TEME→GCRS à moins de 1.1e-10 rad, l'effet prévu de la série à deux termes de l'équation des équinoxes). Les fonctions existantes sont inchangées.

  • UTC antérieur à 1972 sur le chemin temporel en deux parties (timescales::tai_minus_utc_on_date, et Jd2::from_utc_calendar, jd2::utc_to_tai et jd2::tai_to_utc à partir de 1960-01-01) : l'ère à taux dérivant (« seconde élastique »), avec la table de dérive de SOFA, des sauts fractionnaires de fin de journée, et la mise à l'échelle UTC vers SI de la fraction de jour. Nouvelle ligne du registre, VALIDATED par rapport à pyerfa dtf2d/utctai/taiutc (préenregistré 23c40661 ; 117 instants 1960–1971, pire 2.9e-11 s contre un seuil de 1 µs). Tout résultat de 1972 et au-delà est identique au bit près (somme de contrôle épinglée avant la modification). Avant 1960, TAI − UTC vaut 0, comme dans SOFA. Le timescales::tai_minus_utc à un seul f64 est inchangé.

  • Horloge de satellite diffusée GLONASS (GlonassEphemeris::sv_clock_bias_s) : −τn + γn·(t − tb) à partir de l'enregistrement RINEX, à un instant lu sur l'horloge du satellite (deux itérations en virgule fixe, la convention de RTKLIB). Les −τn et γn analysés étaient auparavant inutilisés. Nouvelle ligne du registre « Horloge de satellite diffusée GLONASS et propagation de l'orbite diffusée », VALIDATED par rapport à RTKLIB 2.4.2-p13 geph2clk/geph2pos (préenregistré e099c42a ; 292 cas sur un vrai fichier de diffusion de 2013 : différence d'horloge 0 s, pire position 1,1 mm contre un seuil de 1 cm). Fonction de bibliothèque ; aucune sortie de scénario ne change. Aucune transformation PZ-90.11 → ITRF n'est appliquée, et le module le dit.

  • Solution de temps PPP par rapport à l'horloge de station de l'IGS (0,36, FUT-19) : l'horloge du récepteur du filtre PPP flottant sur WTZR concorde avec l'horloge combinée finale de l'IGS pour la station à 0,075 ns (écart type) avec un décalage constant de −0,66 ns sur les deux heures convergées. Les seuils ont été préenregistrés dans xval/ppp-time/. VALIDATED (nouvelle ligne du registre). Nouvelle fixture igs_2025055_WTZR_05m_0006.clk, les enregistrements d'horloge de station du fichier d'horloge final de l'IGS déjà utilisé pour les horloges de satellites.

  • Parité du PPP avec gLAB (0,36, WP-07, RM-31) : gLAB 6.0.0 a été exécuté sur les mêmes entrées WTZR comme outil séparé (cœur Apache-2.0 ; somme de contrôle du téléchargement vérifiée par rapport à la liste publiée), avec la ligne de commande d'un amendement de procédure commité avant l'exécution. Lors de sa première exécution enregistrée, le PPP flottant de Kshana et celui de gLAB concordent à moins de 0,05 m à 240 époques sur 240 et à 5,0 mm à la dernière. Le seuil du SPP a été manqué (médiane 1,187 m contre 0,50 m) et est consigné comme constat : les solutions SPP propres de gLAB et de RTKLIB diffèrent l'une de l'autre de 0,852 m. La règle enregistrée laisse donc les volets des deux outils non atteints dans leur ensemble, alors que la parité du PPP tient.

  • Lecture de navigation RINEX 4 (0,36, WP-07, PRO-41) : rinex::parse_nav lit des fichiers de navigation RINEX 4.00-4.02 (> EPH GPS LNAV, Galileo I/NAV et F/NAV, BeiDou D1/D2, QZSS LNAV ; les autres enregistrements sont ignorés jusqu'à l'en-tête d'enregistrement suivant), et parse_nav_with accepte des options. VALIDATED par rapport au fichier fusionné RINEX 3 de l'IGS du même jour : chaque champ décodé identique et 0 m en position. La lecture RINEX 2/3 est inchangée.

  • Positions diffusées BeiDou GEO (optionnel) : NavParseOptions::include_beidou_geo et RinexEphemeris::sv_position_ecef_bds_geo (ICD BDS, inclinaison de −5 deg). parse_nav ignore toujours les GEO. MODELLED : la comparaison préenregistrée avec une orbite précise est conditionnée par les données et pas encore exécutée.

  • Fichiers d'observation RINEX 4 : un vrai fichier d'observation MGEX RINEX 4,00 est lu dans les tests (MODELLED, respect du format).

  • RTK avec LAMBDA sur du vrai RINEX (0,36, WP-07 ★) : rtk_real::run_rtk, doubles différences à courte ligne de base de code et de phase GPS bifréquence avec un filtre de Kalman flottant et une fixation entière LAMBDA (test de ratio). VALIDATED sur les stations IGS WTZR et WTZZ (à 1,4 m l'une de l'autre) par rapport à leur ligne de base ITRF2020 sous des seuils préenregistrés : fixé à chaque époque après les dix premières minutes, erreur de ligne de base médiane de 4,5 mm et 95e centile de 5,5 mm.

  • Parité du PPP sur données réelles avec RTKLIB (RM-31) : xval/ppp-parity/run.sh et tests/ppp_parity_glab_rtklib.rs avec des seuils préenregistrés. Le PPP de RTKLIB v2.4.2-p13 sur les mêmes entrées WTZR concorde avec Kshana à moins de 5 cm à chaque époque des deux dernières heures (9,7 mm à la fin) lors du troisième enregistrement ; les deux premières exécutions, consignées comme constats, avaient la marée solide désactivée et l'antenne du récepteur sur l'emplacement de base de RTKLIB. Le seuil de parité en point unique a été manqué (1,09 m médian contre 0,5 m). Le volet gLAB n'a pas été exécuté (conditionné par les données).

  • Encodeurs de message de navigation au-delà de LNAV (0,36, WP-07, PRO-40) : gnss_navmsg encode le CNAV GPS (types de message 10, 11, 30 ; CRC-24Q ; codage continu de rendement 1/2 K=7), le I/NAV Galileo (types de mot 1-5 dans des pages nominales paires/impaires ; entrelaceur 30x8 ; synchronisation 0101100000) et le F/NAV Galileo (types de page 1-4 ; entrelaceur 61x8 ; synchronisation 101101110000), avec des décodeurs de test. MODELLED : allers-retours et réponses connues de l'ICD ; une vérification préenregistrée que les éphémérides Galileo diffusées se situent sur la grille de LSB de l'encodeur a tenu (pire 3.6e-3 LSB) mais a manqué son seuil de nombre de satellites (15 sur 20), consigné. Les encodeurs sont des fonctions de bibliothèque ; le câblage dans la scène ne fait pas partie de cette modification.

  • Lecteur de fichiers IONEX (0,36, WP-07) : ionex::parse_ionex_file avec IonexFile, IonexHeader, IonexEpoch, IonexFileMap et IonexTimeInterp : un lecteur IONEX 1,0 strict à colonnes fixes avec des époques comptées à partir du jour de la première carte, 9999 lu comme manquant, des cartes RMS, et les interpolations temporelles du format par carte la plus proche, consécutive et tournée ; TEC oblique à la hauteur de coque de l'en-tête. Vérifié sur une carte synthétique versée et, conditionné par les données (récupéré au moment du test avec un SHA-256 épinglé, non intégré au dépôt), sur un extrait d'un vrai GIM du CODE : chaque nœud exact ; l'interpolation concorde avec une référence par formule à 4e-13 TECU. iontec de RTKLIB concorde à 3.6e-13 TECU en 6885 points (B6 préenregistré). VALIDATED sur une preuve conditionnée par les données (décision du propriétaire, 2026-10-13) : le test échoue sur toute carte autre que celle au SHA épinglé.

  • Lissage de porteuse de Hatch (0,36, WP-07) : hatch::HatchFilter et pvt::assemble_epoch_precise_smoothed, la forme sans divergence (sans ionosphère) dans l'assemblage de point unique précis. MODELLED avec un constat consigné : sur la station IGS WTZR, il abaisse l'erreur médiane en point unique de 1,55 m à 1,12 m et le 95e centile de 3,47 m à 3,21 m, en deçà de la réduction préenregistrée de 40 % (l'erreur restante est de type biais, et non du bruit).

  • PPP flottant sur du vrai RINEX (0,36, WP-07) : ppp_real::run_ppp, un filtre de positionnement ponctuel précis flottant statique sur du vrai code et de la vraie phase GPS bifréquence avec les produits finaux de l'IGS (décalages et variations d'antenne, marée terrestre solide, enroulement de phase, retard de Shapiro, retard humide estimé, détection de sauts de cycle), avec parse_antex_receiver. VALIDATED sur la station IGS réservée WTZR par rapport à sa coordonnée ITRF2020 sous des seuils préenregistrés : après 6 h, l'erreur est de 1,5 mm en horizontal et de 2,9 cm en vertical, et chaque époque des deux dernières heures est à moins de 10 cm.

  • Interpolation d'horloge précise SP3 (0,36, WP-07) : Sp3File::clock_s et clock_nodes interpolent linéairement les horloges de satellites tabulées SP3 entre les deux nœuds valides qui les encadrent (valeur sentinelle d'horloge défectueuse ignorée), et ClockRinex::from_sp3 les fournit à PreciseProducts, de sorte que la chaîne précise fonctionne à partir d'un SP3 seul. VALIDATED par rapport aux horloges finales de l'IGS à 30 s du 2025-02-24 sous des seuils préenregistrés : 32 satellites GPS, RMS au point médian 0,121 ns (seuil 0,15 ns), 95e centile 0,265 ns (seuil 0,30 ns).

  • RAIM à côté des chiffres de mérite de holdover d'horloge (CAP-05b) : une section [integrity] optionnelle sur le type de scénario clock rapporte un bloc integrity_fom séparé (RAIM instantané sur un ciel prédéfini depuis un site énoncé : verdict par époque et niveaux de protection, disponibilité ; indisponible tant que le GNSS est refusé, jamais extrapolé). Les chiffres de holdover sont inchangés ; sans la section, la sortie est identique à l'octet près. MODELLED.

  • Seuils de confiance du récepteur étalonnés sur JammerTest 2024 (CAP-13) : un étalonnage préenregistré des moniteurs de chute de C/N0, d'AGC et d'indicateur de brouillage sur le jeu de données public JammerTest 2024 (récupéré à l'exécution, jamais intégré au dépôt ; examples/jammertest_trust_calibration.rs), livré uniquement comme [monitors] profile = "jammertest-2024-calibrated" optionnel (1,5 dB, 3,5 sigma, 29). Sur jeu réservé : les seuils AGC, indicateur de brouillage et union sont franchis ; le seuil de fausses alarmes du C/N0 échoue (0,023 contre 0,02), de sorte que la ligne est MODELLED (xval/jammertest-trust/RESULTS.md). Les valeurs par défaut et les sorties sans le profil sont inchangées.

  • Hypothèses de défaut ARAIM à plusieurs satellites (CAP-05a) : la règle de sous-ensembles ADD v4.2 généralisée au-delà des paires (add_v42_subset_plan, add_v42_protection_levels_to_order ; l'ordre 2 est exactement le chemin existant vérifié par MAAST) et un RAIM avancé optionnel sur ces hypothèses (araim_subset_raim), qui rapporte le sous-ensemble de plus grande séparation lorsqu'un défaut est détecté. Les a priori exigeant des sous-ensembles plus profonds sont refusés, jamais tronqués. MODELLED.

  • Ligne d'horizon dans la confiance du récepteur (FUT-01) : une session receiver-trust peut énoncer un [skyline] ; les satellites situés derrière sont perdus pour le ciel (sky-blocked, behind_skyline, open_fraction) et leurs pertes sont classées geometry, jamais environment ; sans cela, le repli sur l'intervalle d'azimut et toutes les sorties sont comme avant. Le générateur d'entraînement d'équipage gagne un événement natural-degradation (un ciel bloqué, et non une interférence) et le scénario scenarios/training/fjord-natural-degradation.toml. Le Monte Carlo UERE x DOP gagne les deux géométries de ligne d'horizon masquée de la note de conception, préenregistrées seules : les 26 vérifications réussissent.

  • Vérification d'horodatage RFC 3161 (CAP-14) : kshana::evidence::tsa::verify_token vérifie la signature d'un jeton d'horodatage (RSA PKCS#1 v1.5, RSA-PSS, ECDSA P-256 et P-384), sa liaison au certificat de signature ESS, l'usage timeStamping du signataire et sa chaîne jusqu'à une ancre de confiance à l'instant genTime du jeton, hors ligne ; kshana evidence verify --tsa-ca <anchors.pem> l'applique au timestamp.tsr d'un paquet (optionnel ; sans lui le rapport est inchangé). VALIDATED, de façon restreinte : les 27 cas auto-générés concordent tous avec OpenSSL 3.0.13 sur le verdict et le genTime, selon une comparaison préenregistrée avant que le vérificateur ne soit écrit. La révocation n'est pas vérifiée.

  • Niveaux de vérification par chiffre pour chaque type de scénario (RM-04) : le résultat de chaque type de scénario se termine désormais par un bloc figure_tiers nommant ses chiffres principaux, la ligne de la matrice de vérification qui possède chacun d'eux et le niveau lu sur cette ligne (les chiffres qu'aucune ligne ne possède sont listés comme sans niveau). Le bloc est ajouté après l'exécution et se retire pour redonner le document précédent octet pour octet (api::without_figure_tiers). lunar-station-coverage n'a pas de figure_tiers tant qu'une nouvelle prédiction datée ne remplace pas sa prédiction figée ; leo-ppp, solar-system, sweep et sweep-nd n'ont aucun chiffre principal scalaire, et lunar-attack-surface écrit du JSON compact. Les membres de campagne conservent leurs documents sans niveau.

  • Préréglage quantique quantum-cai-coast (CAP-08c) : un scénario inertiel fourni dans lequel un accéléromètre à interféromètre d'atomes froids, spécifié par la physique de son interféromètre ([accel_quantum.cai] avec un niveau de vibration de plateforme énoncé), file en inertie contre un accéléromètre à quartz de qualité navigation pendant une interruption GNSS de 110 minutes. MODELLED.

  • Degrés de liberté équivalents exacts de Greenhall (CAP-03) : allan::edf_greenhall, l'algorithme complet de Greenhall et Riley (2003) (ordres de différence 1 à 3, exposants de bruit +2 à -4, avec et sans recouvrement, modifié et non modifié, avec les tables des grands J), avec des enveloppes ADEV, MDEV et HDEV. VALIDATED sous une comparaison préenregistrée avec allantools 2024,6 : 4 876 points de grille à moins de 6.0e-13 en relatif ; allantools échoue en 32 points supplémentaires, qui sont consignés sans valeur de référence indépendante. Les intervalles de confiance de assurance::uncertainty sont inchangés bit pour bit.

  • Termes d'erreur de l'interféromètre à atomes froids (RM-26/27/28) : bruit de phase du laser Raman (avec le terme de retard de rétroréflexion), biais de courbure de front d'onde d'un nuage thermique (défocalisation pure, avec un rayon de détection) et résolution de l'ambiguïté de franges (assistée par le classique et à deux temps d'interrogation), comme fonctions de bibliothèque dans src/inertial/cai_error_terms.rs, chaque forme close étant vérifiée par quadrature ou par Monte Carlo. MODELLED ; pas encore accessible depuis un type de scénario (docs/QUANTUM-MODELS.md).

  • Formats de journaux d'horloge (RM-03) : src/clock_log.rs lit des fichiers d'horloge RINEX, des journaux ASCII de phase ou de fréquence de style TimeLab et des journaux de compteur TAPR TICC dans une série de phase normalisée unique (tau0 énoncé ou trouvé, lacunes comptées, une politique de lacunes). Optionnel : une série de synchronisation de télécommunications peut nommer un journal ([series.clock_log]), et la table [clock_log] d'un scénario d'horloge ajoute un bloc measured (ADEV, TDEV, MTIE). Sans la table, les deux types de scénario sont identiques à l'octet près (docs/CLOCK-LOG-FORMATS.md). Une comparaison préenregistrée sur trois journaux synthétiques a atteint ses seuils de phase et de câblage ; les estimateurs concordent avec allantools à moins de 2.5e-14 partout où il évalue, et il n'évalue pas le point MTIE sur l'enregistrement entier (consigné). MODELLED.

  • Gabarits de dérive de synchronisation en fréquence (RM-01) : le type de scénario telecom-timing gagne sept gabarits de génération de dérive MTIE et TDEV à température constante, ITU-T G.811 PRC, G.812 Types I à III, G.8262 EEC Options 1 et 2 et G.8262.1 eEEC, avec les morceaux en loi de puissance que les tables écrivent, et le scénario de référence scenarios/telecom-synce-eec.toml (un OCXO en roue libre contre les gabarits EEC : il échoue à 1 000 s, là où une boucle doit faire le travail). Chaque ligne a été relue par rapport au texte de itu.int ; la G.812 (06/2004) est remplacée par une édition préparée 08/2026 qui n'a pas pu être lue. MODELLED (une transcription) ; les gabarits et sorties existants sont inchangés.

  • Conseils sur l'a priori de filtre pour le type de scénario gnss-ins (0,36, WP-09, constat RM-21) : l'a priori de filtre par défaut du paquet convient à une IMU de qualité tactique. Avec une IMU de qualité navigation, la valeur par défaut peut rendre l'inertie fusionnée pire qu'un INS libre : 52 m contre 11 m sur un profil d'aéronef à 70 m/s. Réglez [imu_*.filter_prior] pour correspondre à la qualité du capteur, comme le font les nouveaux paquets maritime, ferroviaire et aviation. Aucun scénario fourni n'associe une IMU de qualité navigation à l'a priori par défaut : chacun de ceux qui utilisent la valeur par défaut a des biais d'accéléromètre résiduels d'au moins 0,015 m/s². Documentation seulement ; aucune sortie ne change.

  • Export pour banc d'essai vérifié avec les propres lecteurs d'un simulateur (0,36, WP-09, CAP-16) : les fichiers de mouvement kshana bench-export de 8 scénarios fournis ont été relus par les lecteurs NMEA, latitude/longitude/hauteur et mouvement terrestre fixe de gps-sdr-sim (MIT, commit 28ca29a6, utilisé comme outil séparé via xval/testbench-gpssdrsim/ ; aucune fonction de signal n'est appelée). Ils restituent la trajectoire exportée à 1,2 mm, 0,15 mm et exactement. CONSTAT : le lecteur terrestre fixe de ce simulateur ne peut pas lire le CSV pleine largeur, parce que son tampon de ligne de 100 caractères coupe chaque ligne. docs/TEST-BENCH.md donne désormais les coupes de colonnes à utiliser et le plafond de 300 s du simulateur. VALIDATED (nouvelle ligne du registre) ; les octets de l'export sont inchangés.

  • GNSS/INS sur le jeu de données KF-GINS (0,36, WP-09, FUT-17) : chargeurs et exécuteur fusion::kfgins et modèle de mesure de bras de levier dans l'EKF en boucle fermée. Sur le jeu de données de démonstration de KF-GINS (récupéré au moment du test, non intégré au dépôt), la RMS horizontale de Kshana par rapport à la trajectoire de référence est de 1,09 cm contre 1,11 cm pour KF-GINS lui-même, et chaque seuil préenregistré a tenu. VALIDATED sur une preuve conditionnée par les données (décision du propriétaire, 2026-10-13) : le jeu de données est récupéré avec des SHA-256 épinglés et le chemin de reproduction se trouve dans xval/kfgins/PREREGISTRATION.md.

  • Filtre PNT couplé dans le paquet de fusion (0,36, WP-09, FUT-16) : le type de scénario fusion accepte une table [coupled] optionnelle qui exécute un filtre empilé sur des pseudodistances avec un état de biais d'accéléromètre (fusion::coupled::CoupledPntBiasFilter), et fusion::coupled::CoupledPnt3d est la version 3D à 8 états. Nouveau scénario fourni fusion-pnt-coupled : avec des accéléromètres biaisés, le mode couplé maintient la position de la suite quantique à 18,7 m (95e centile) avec une intégrité complète, là où les filtres découplés atteignent 430 m. Sans la table, fusion et hybrid sont tous deux inchangés (épinglé) ; hybrid refuse la table. MODELLED.

  • Paquets GNSS/INS maritime, ferroviaire et aviation (0,36, WP-09, RM-21) : scénarios fournis gnss-ins-maritime, gnss-ins-rail et gnss-ins-aviation sur la bibliothèque de trajectoires, et une table [tight] optionnelle pour le type de scénario gnss-ins qui fusionne les pseudodistances d'une constellation Walker SGP4 (tous les satellites en nominal, les quelques plus hauts en dégradé). Sur le paquet ferroviaire, le couplage serré maintient la solution de qualité navigation à 5,3 m à travers une tranchée et un tunnel, contre 12,9 m en couplage lâche. Sans [tight], le paquet est inchangé (épinglé). MODELLED.

  • Couplage serré sur phase de la porteuse (0,36, WP-09, RM-25 / FUT-17) : fusion::carrier_tc, un EKF à état d'erreur avec une horloge de récepteur explicite à deux états et des ambiguïtés de porteuse flottantes, piloté par une constellation Walker SGP4 avec des corrections de Klobuchar et de Saastamoinen dans la boucle de mesure, une détection de sauts par porteuse différenciée dans le temps et une réinitialisation des ambiguïtés, et une exécution sur le seul code avec les mêmes mesures pour comparaison. MODELLED : sur un parcours en 8, la solution sur porteuse est de 2,5 cm contre 47 cm sur le seul code, et NIS/NEES sont cohérents selon les germes.

  • Bibliothèque de trajectoires GNSS/INS (0,36, WP-09, RM-24) : le type de scénario gnss-ins accepte une table [trajectory] optionnelle avec profile = "straight" | "figure8" | "stop_go" | "aircraft" | "uas" | "csv". Les profils commandent des vitesses d'Euler et une accélération le long de la trajectoire à partir de l'état de vérité et en déduisent l'IMU vraie par la cinématique du corps rigide (virages coordonnés, montées, Coriolis) ; csv importe une trajectoire de vérité (t, lat, lon, alt, vn, ve, vd, roll, pitch, yaw) et résout l'IMU qui la reproduit. Sans la table, le paquet vole son parcours historique, bit pour bit (épinglé). MODELLED.

  • Tuiles MNT latitude/longitude pour l'horizon lunaire : [terrain] dem_tile_path lit une tuile texte realdata::lola_dem (hauteurs au-dessus de la sphère moyenne sur une grille latitude/longitude) à la place du dem_path en projection stéréographique polaire, pour lunar-station-coverage comme pour moonlight-service-volume ; le rapport reprend la tuile (terrain.dem_tile, avec son SHA-256). realdata::lola_dem est désormais câblé dans le lancer de rayon d'horizon. Une tuile rééchantillonnée à partir de l'extrait fourni donne à la station l'horizon de l'extrait à 0,22 deg. MODELLED.

  • Relief au site d'export du volume de service : avec une section terrain, chaque ligne de l'export de géométrie par satellite de moonlight-service-volume porte clears_terrain (le satellite dépasse le masque plat et l'horizon du site d'export à son azimut), le rapport porte l'horizon du site (export_site_terrain), et le CSV d'exécution gagne la colonne. Sans relief, l'export est inchangé. MODELLED.

  • Champs principaux issus du moteur (0,36, STUDIO-06) : kshana::api::HEADLINE_FIELDS, field_importance_json() et le field_importance() WebAssembly indiquent, pour douze types de scénario, quels champs d'un scénario répondent à sa question, du meilleur au moins bon, sous forme de chemins pointés (jammers[].eirp_dbw). Le Studio les lit avant son propre classement. Métadonnées d'affichage seulement : le moteur ne les lit jamais, aucun fichier de scénario n'en a besoin, aucun résultat n'en dépend. tests/field_importance.rs échoue si un type de scénario n'est pas répartissable ou si un chemin ne se trouve dans aucun des scénarios fournis du type (il a détecté deux chemins que les identifiants aplatis du Studio avaient écrits sans les crochets de tableau).

  • Table type de scénario vers module issue du moteur (0,36, STUDIO-05) : kshana::api::KIND_MODULES, kind_modules_json() et le kind_modules() WebAssembly donnent, pour chaque type de scénario dont les lignes de la matrice de vérification nomment un autre module que le sien, les noms de modules. La carte des capacités du Studio utilisait sa propre copie écrite à la main ; tests/kind_modules.rs échoue si un type de scénario de la table n'est pas répartissable ou si un module n'apparaît dans aucune ligne de la matrice. Aucune sortie n'a changé.

  • Courte exécution IQ dans la version navigateur (0,36) : iq_signals() et iq_run_short(fs_hz, duration_s, signal, ids, dopplers_hz, cn0_dbhz, seed) dans le module WebAssembly construisent une scène synthétique, acquièrent chaque satellite et suivent ceux qui ont été acquis, le tout en mémoire, limité à 0,25 s, 1 000 000 d'échantillons et 8 satellites. Le constructeur de scène et la recherche de signal par nom ont été déplacés hors de iq::cli réservé au natif (vers iq::scene::synthetic et iq::signals::by_name) afin que les deux versions les partagent ; la sortie de la ligne de commande est inchangée. Le test natif et web/smoke.mjs comparent la même requête à une seule référence (tests/fixtures/iq_short_golden.json), octet pour octet : depuis le changement de mathématiques portables (STUDIO-15, ci-dessous), la version navigateur et la version native donnent les mêmes bits.

  • API Python et TypeScript typées (CAP-34) : kshana.pyi type les vocabulaires fermés (ScenarioKind, chaque nom de type de scénario ; ErrorKind ; ProvenanceClass) et les dictionnaires KindMeta et FieldUnit ; scenario_kinds() et error_kind() les renvoient. Le paquet WebAssembly ajoute run_typed (une exécution sous forme d'objet RunOutput typé avec le document analysé comme data) et scenario_kinds (les KindMeta[] analysés), et son kshana.d.ts porte le même vocabulaire ; error_kind est typé ErrorKind | "". tests/typed_api_sync.rs maintient les deux listes égales à celles du moteur.

  • Unités pour chaque colonne sweep-nd (FUT-28) : un résultat sweep-nd porte désormais key_units et metric_units, l'unité de chaque clé balayée et de chaque métrique enregistrée, lues dans la propre table d'unités du paquet balayé. Un axe peut déclarer unit pour une clé que le paquet ne reprend pas ; une unité déclarée qui contredit celle du paquet est refusée, et une unité qu'aucun des deux ne donne vaut null, jamais devinée. points[].coords[] et points[].metrics[] sont décrits, de sorte que chacun des 76 types de scénario est désormais entièrement couvert par la barrière des unités de champs (plafond de types de scénario non couverts 1 -> 0).

  • Tableaux NumPy à partir de RunOutput (FUT-26) : le RunOutput Python gagne array(path), columns(path) et series(), qui renvoient des numpy.ndarray pour une liste numérique, les colonnes numériques d'une liste d'enregistrements, ou chaque série d'enregistrements du document. Chaque tableau égale numpy.asarray des mêmes valeurs issues de data() (dtype et bits). NumPy n'est importé que lorsque l'une d'elles est appelée et reste hors des exigences d'exécution. Typé dans kshana.pyi et vérifié par stubtest.

  • Optimiseur de campagne (CAP-32) : la nouvelle section [optimize] optionnelle du type de scénario campaign cherche, parmi une à trois clés de scénario dans des bornes énoncées, la meilleure valeur d'une métrique : la minimiser, la maximiser ou atteindre une cible. Elle cherche de façon exhaustive sur une grille, ou avec un simplexe de Nelder–Mead déterministe et borné. Chaque évaluation est une vraie exécution du type de scénario nommé et est listée dans le trace du résultat. Exemple : scenarios/campaign-optimize-link-budget.toml. Les seuils ont été préenregistrés (docs/design/evidence/cap32-optimize/) :

    • la fonction de Rosenbrock est atteinte (f* = 1.7e-20) ;
    • une résolution de cible 1D en forme close est atteinte (6e-15 en relatif) ;
    • la grille est égale au bit près à une force brute indépendante ;
    • le simplexe fait au moins aussi bien qu'une grille de 41 × 41 en 177 exécutions.

    Le seuil 1D du tour 1 est consigné NOT MET, parce que la boîte préenregistrée excluait la solution. MODELLED ; ligne du registre « Optimisation bornée d'une métrique sur des paramètres de campagne ». Additif : les campagnes sans la section sont inchangées.

  • Ensembles d'étalonnage (CAP-10) : trois vérifications à germe unique ré-exécutées sur 200 germes indépendants par rapport à des seuils préenregistrés, dans docs/CALIBRATION-ENSEMBLES.md (générées par gen_calibration_ensembles ; valeurs par germe dans docs/data/calibration-ensembles.csv).

    • L'intervalle à 95 % du bootstrap Monte Carlo de campagne couvre la vraie moyenne sur 192 ensembles sur 200, et son contrôle du khi-deux est franchi sur 196.
    • La tolérance de centile à germe unique n'est franchie que sur 183 sur 200 : NOT MET, comme prévu. C'est un seuil d'environ 2 sigma, consigné et non assoupli.
    • Les étalonnages ADEV en FM blanche sont franchis sur chaque germe, avec leur pire erreur très en deçà de la tolérance.

    MODELLED.

  • Types de scénario intégrés via le trait Scenario (FUT-27, en cours) : le trait BuiltinKind (api::BuiltinKind, avec un crochet de niveau par chiffre et append_figure_tiers), et les premiers types de scénario déplacés vers lui (inertial, spoof, passes, link-budget, jamming). La sortie est inchangée : un manifeste du catalogue entier des SHA-256 de chaque sortie est identique avant et après (tests/scenario_output_manifest.rs).

  • Contrôle d'absence de récupération du terrain de jeu (RM-07) : tests/playground_no_fetch.rs vérifie trois choses :

    • chaque scénario de la bibliothèque du Studio est dans le paquet du navigateur ;
    • le paquet est identique à l'octet près à scenarios/ ;
    • chaque scénario du navigateur s'exécute depuis un répertoire de travail vide.
  • Cartes Alt-PNT : champ de gravité réel, Monte Carlo d'erreur de carte, SRTM pleine résolution (0,36, WP-10). Le type de scénario gravity-map accepte un [reference] optionnel : une anomalie de gravité synthétisée à partir des coefficients EGM2008 fournis (ou d'un fichier ICGEM .gfc via gfc_path, versions natives seulement). Cette synthèse concorde avec l'ICGEM Calculation Service à environ 1e-8 mGal sur 794 nœuds dans deux régions, par rapport à des seuils préenregistrés de 0,005 mGal en RMS et 0,02 mGal en maximum (VALIDATED ; ligne du registre « Synthèse d'anomalie de gravité à partir d'un modèle d'harmoniques sphériques »). Le nouveau scénario fourni gps-denied-gravity-nav-egm2008 exécute le banc d'essai de 60 minutes sur ce vrai champ de degré 70. Résultat préenregistré : erreur d'appariement de 3106 m, de sorte que le seuil < 500 m est NOT MET, comme prévu (le degré 70 est trop lisse), et la réduction par dix de la dérive est MET (MODELLED). Un [map_error_mc] optionnel ré-exécute le banc d'essai sur des erreurs de carte gaussiennes corrélées, à germe fixé, et rapporte la distribution de l'erreur d'appariement (scénario fourni gravity-map-error-mc). Exploratoire et non préenregistré : avec une erreur de carte de 2 mGal corrélée sur 0,2 deg (la taille que budgète le propre sigma de l'apparieur), 1 réalisation sur 20 reste à moins de 500 m (médiane 2,9 km, p95 14,7 km), contre 144 m avec une carte parfaite. Le positionnement synthétique du banc d'essai en deçà de 500 m suppose que la carte est exacte. Sans l'une ou l'autre option, le document est identique à l'octet près à celui des versions antérieures. combined-altpnt accepte un [magnetic_grid] optionnel (csv_path, column) qui lit le canal magnétique à partir d'un CSV au format EMAG2v3. EMAG2 n'est pas intégré au dépôt parce que ses conditions ne sont pas explicites : tools/fetch_emag2_tile.py le récupère avec un SHA-256 épinglé et en découpe un rectangle. Aucun résultat de navigation n'est revendiqué sur la vraie grille EMAG2. Estimation conjointe de la carte (SLAM de terrain, RM-18) : altpnt::sequential::run_sequential_trn_on_map fait voler le navigateur séquentiel de terrain sur une carte stockée qui diffère de la vérité, soit en lui faisant confiance, soit en estimant une correction de carte par cellule avec un filtre Rao-Blackwellisé de type FastSLAM. Préenregistré par rapport au SITAN à carte connue avec une erreur de carte corrélée de 15 m sur 20 germes : un gain moyen de 1,5 %, meilleur dans 10 cas sur 20, de sorte que les deux seuils d'amélioration sont NOT MET (10 % et 12 sur 20), sans dommage sur une carte parfaite (MET). Un seul passage sans revisites ne permet pas d'apprendre la carte (xval/terrain-slam-rbpf/, MODELLED). Les documents terrain-slam sont identiques à l'octet près. Les tests SRTM réels s'exécutent désormais en CI sur deux extraits pleine résolution versés ; tous les seuils préenregistrés sont atteints, le nœud le plus proche égalant GDAL 3.8.4 en 8 points sur 8 (xval/srtm-ungate/).

  • Interopérabilité, WP-08 (0,36 ; chaque élément préenregistré et commité seul avant son exécution de référence indépendante, chacun une nouvelle ligne VALIDATED du registre sauf l'élément de télémétrie, qui élargit une ligne existante) :

    • Messages de données d'orbite CCSDS (src/odm.rs) : OPM 3.0/2.0, OMM 3.0/2.0 et OCM 3,0 (blocs TRAJ, PHYS, COV, MAN, USER) écrits et lus en KVN et NDM/XML, et un OMM en pleine précision à partir d'un jeu d'éléments SGP4 (OmmMessage::from_omm_file) ; la sortie de OmmFile::to_omm_kvn est inchangée. Par rapport à Orekit 13.1.8 dans les deux sens : 27 messages Kshana sur 30 sont analysés par Orekit et Kshana lit chaque message écrit par Orekit, valeurs à moins de 1e-14 en relatif et époques à moins de 1e-9 s ; quatre constats épinglés (Orekit exige ELEMENT_SET_NO, refuse COMMENT dans les paramètres XML définis par l'utilisateur, n'écrit pas BTERM sans BSTAR, et lit les époques relatives de l'OCM en TDB en secondes SI). Le META_START de l'ancien écrivain OMM est refusé par Orekit (consigné). Ligne « Messages de données d'orbite CCSDS (OPM, OMM, OCM) ».
    • Messages de données d'attitude CCSDS (src/adm.rs, src/ndm_xml.rs) : AEM 2.0/1.0 et APM 2,0 en KVN et XML par rapport à Orekit 13.1.8, tous les seuils atteints ; l'écrivain APM d'Orekit refuse une manœuvre sans MAN_DELTA_MASS (épinglé). Ligne « Messages de données d'attitude CCSDS (AEM, APM) ».
    • Export SPICE SPK (src/spk_writer.rs) : écrivain et lecteur des types SPK 9 et 13 et export OEM vers SPK ; par rapport à CSPICE N0067, les noyaux sont identiques à l'octet près à ceux de SPICE et s'évaluent à l'identique au bit près. Ligne « Export SPICE SPK (types 9 et 13) ».
    • Types SPICE SPK 3 et 21 (src/spk_writer.rs) : segments de type 3 (Tchebychev) et de type 21 (lignes de différences étendues) écrits à partir d'enregistrements donnés et évalués comme le fait SPICE ; par rapport à CSPICE N0067, les noyaux sont identiques à l'octet près à ceux de SPICE et chaque évaluation concorde bit pour bit dans les deux sens. Ligne « Types SPICE SPK 3 et 21 (Tchebychev, lignes de différences étendues) ».
    • Extensions de Space Packet (src/space_packet.rs) : en-tête secondaire avec codes de temps CUC/CDS, contrôle d'erreur de paquet, segmentation et contrôles de flux, par rapport à ccsdspy 2.0.1, spacepackets-rs 0.18.0, spacepackets-py 0.32.0 et crc_hqx de CPython, zéro écart. Ligne « En-tête secondaire, contrôle d'erreur de paquet et segmentation des CCSDS Space Packet ».
    • Schéma de télémétrie 1,3 à travers de vrais consommateurs : l'exposition Prometheus et le JSON OTLP/HTTP d'un flux synthétique de schéma 1.3, y compris la série de géométrie et l'étiquette class, lus exactement par prometheus_client et le proto OTLP, acceptés par promtool 3.5.0 check metrics sans problème de lint, et transmis inchangés par l'OpenTelemetry Collector contrib 0.135.0 (conditionné par les données : outils récupérés avec des SHA-256 épinglés, sorties versées).
  • Détermination d'orbite de Mars, exécution 2 (0,36, WP-14, CAP-30) : mars_od::fit_damped met la matrice normale à l'échelle de sa diagonale et amortit le pas (Levenberg-Marquardt), après l'échec de l'ajustement de Gauss-Newton enregistré sur une matrice dont la diagonale brute s'étend sur huit ordres de grandeur. Enregistré séparément (xval/mro-od/PREREGISTRATION-RUN2.md, même arc, mêmes seuils et même édition). Sur les passages MRO notés, l'orbite est à moins de 0,36 km en RMS (0,53 km au maximum) de la reconstruction de navigation de MRO, seuils atteints. Le Doppler après ajustement est de 48,6 mHz contre le seuil de 30 mHz, non atteint (constat épinglé). Un amendement portant uniquement sur la notation, R2-A1, est divulgué dans docs/revisions. La ligne reste MODELLED.

  • Modèle Doppler à 2 voies à rampe de Mars et détermination d'orbite (0,36, WP-14, partie de CAP-30, étape 2) : mars_od prédit le Doppler à 2 voies en bande X à rampe du DSN à partir de tables de rampe ODF (temps de lumière, Shapiro, troposphère, temps de station, stations du DSN par la chaîne CIO et les EOP de l'IERS) et ajuste un orbiteur martien (GMM-3, troisièmes corps, SRP, traînée). naif_kernel lit le SPK de type 1 (vérifié par rapport à CSPICE) et gravity_sh::from_shadr lit les champs PDS SHADR. Préenregistré par rapport à la reconstruction de navigation de MRO sur de vrais passages MRO (conditionné par les données, scripts/fetch_mro_od.sh, CI mensuelle) : le Doppler prédit concorde avec les observations à 12,5 mHz (seuil 30 mHz, atteint) ; l'ajustement d'orbite enregistré a échoué sur l'arc noté et n'a produit aucune orbite (constat épinglé). La ligne reste MODELLED.

  • Lecteur de fichiers de données d'orbite du DSN (0,36, WP-14, partie de CAP-30) : odf::parse_odf lit des ODF TRK-2-18. Sur un vrai ODF du Mars Reconnaissance Orbiter (NASA PDS, intégré au dépôt), le lecteur concorde avec le nombre d'enregistrements, les positions de groupes, les stations et les heures de l'étiquette PDS, et tous ses types de données sont connus. La table de fin de fichier de l'étiquette a une ligne de moins que le fichier, une incohérence de l'étiquette consignée comme constat. MODELLED. La détermination d'orbite sur ces données n'est pas encore faite.

  • Bilan TWSTFT et stabilité du transfert de temps : le type de scénario time-transfer-budget (0,36, WP-14, FUT-19).

    • Équation bidirectionnelle : twstft_budget la résout pour T_A − T_B avec les retards d'équipement des stations, l'asymétrie ionosphérique montante/descendante en bande Ku, la différence de retard du transpondeur et les termes de Sagnac, et retrouve le modèle direct à 1e-15 s.
    • Bilan d'incertitude : combiné en quadrature, avec le TDEV de la liaison comme terme de type A.
    • Bruit de liaison : la série bidirectionnelle gagne un plancher de bruit de phase de scintillation, une non-réciprocité diurne et un résidu de réciprocité constant. Le paquet timetransfer à gigue blanche est inchangé.
    • Série réelle : la stabilité d'une série fournie de la Circular T du BIPM, d'un CSV MJD,ns ou d'horloges de station de l'IGS.

    MODELLED. Nouveau scénario fourni time-transfer-budget. La solution de temps PPP est VALIDATED séparément par rapport à l'horloge de station de l'IGS sur la branche de données réelles GNSS.

  • Échauffement d'entrée, radiométrie EO et pertes à l'ascension (0,36, WP-14, CAP-28) : trois nouveaux types de scénario.

    • entry-heating : une entrée à 3 degrés de liberté en masse ponctuelle sur une Terre ou un Mars en rotation avec échauffement au point d'arrêt de Sutton-Graves.
    • eo-radiometry : SNR de l'imageur, FTM à Nyquist, réponse relative de bord et NIIRS GIQE 4.
    • ascent-losses : une ascension à virage gravitationnel à plusieurs étages avec pertes de gravité, de traînée, de pilotage et de contre-pression, vérifiée par l'identité exacte dv idéal moins pertes.

    La décélération maximale de l'entrée a été vérifiée par rapport au nominal publié de Stardust sous un seuil préenregistré : 35,44 g contre 33,4 g (+6,1 %, seuil 10 %). Cette ligne est VALIDATED. L'échauffement, la radiométrie et l'ascension sont MODELLED. Nouveaux également : reentry::us76_pressure, les scénarios fournis entry-heating-stardust, eo-radiometry et ascent-losses, et docs/ENTRY-EO-ASCENT.md.

  • Contrôle d'attitude par roues de réaction : le type de scénario aocs (0,36, WP-14, CAP-21). Une manœuvre de pointage inertiel d'un corps rigide avec trois roues de réaction équilibrées ou plus sous rétroaction MRP, avec des couples de roues de norme minimale écrêtés à la limite de chaque moteur (aocs). Il peut aussi boucler sur un EKF multiplicatif à partir d'un gyromètre et d'un viseur d'étoiles simulés (aocs_mekf). La boucle d'état vrai a été comparée à Basilisk 2.9.1 sur trois cas préenregistrés avant l'existence du code (trois roues orthogonales, une pyramide à quatre roues, un cas de saturation). Chaque composante MRP, vitesse du corps, vitesse de roue et couple de moteur concordait à chaque échantillon, pire 2.4e-14 en sigma et 2.9e-11 rad/s en vitesse de roue. Cette ligne est VALIDATED ; le MEKF est MODELLED (cohérence NEES). Nouveaux scénarios fournis aocs-slew et aocs-slew-mekf, et docs/AOCS.md.

  • Planification des contacts sol et ACM DVB-S2 (0,36, WP-14, CAP-22/23) : deux nouveaux types de scénario. acm-link donne, pour un satellite au-dessus d'une station, l'Es/N0 de chaque passage et le MODCOD DVB-S2 choisi le long de celui-ci (seuils de la Table 13 de l'ETSI EN 302 307-1 plus une marge). Il donne aussi le volume de données que l'ACM déplace par rapport à la référence de base à codage constant. contact-schedule fait de même pour plusieurs satellites au-dessus de plusieurs stations et construit un plan de contacts sans conflit (retournement d'antenne, une station par satellite, livraison pondérée par priorité plafonnée à chaque arriéré). Il rapporte un plan glouton à valeur marginale, une référence de base au premier arrivé et l'optimum exact sur de petits ensembles, avec l'écart d'optimalité du glouton. Les fenêtres d'accès proviennent du prédicteur de passages apparents VALIDATED. Nouveaux scénarios fournis acm-link et contact-schedule (entrées à titre d'illustration) et docs/CONTACT-SCHEDULING.md. MODELLED (deux nouvelles lignes du registre).

  • Positionnement Doppler Starlink par rapport à une expérience publiée (0,36, WP-14, partie de CAP-11, MODELLED). Il s'agit d'une comparaison par substitut préenregistrée du mode Doppler leo-pvt avec le préréglage starlink-sop par rapport aux centiles du jeu de données 3 de « Unveiling Starlink for PNT » (NAVIGATION 72(1), 2025, doi:10.33012/navi.685). Le modèle utilisait 3 satellites (un masque de 47 deg choisi par une règle fixe), aucune aide d'altitude et un sigma Doppler de 30 Hz, sur 200 germes. Son erreur 3D au 90e centile est de 92,2 m à 20 s et de 870 m à 8 s, contre 2 m et 10 m publiés, de sorte que les deux seuils d'un facteur deux sont NOT MET. Le modèle est pessimiste, et non optimiste comme prévu : trois satellites fixes donnent bien moins de diversité géométrique que les 63 satellites de l'expérience sur 10 minutes avec un changement de canal toutes les 15 s. Les deux écarts sont affirmés (tests/starlink_doppler_published_proxy.rs).

  • Optimiseur de transfert impulsionnel sur DE440 (0,36, WP-14, CAP-20c/d) : maneuver::optimise_transfer_kernel trouve les dates de départ et d'arrivée d'un transfert balistique à deux impulsions à une seule révolution qui minimisent le C3 au départ ou le V-infini à l'arrivée dans le Type I ou le Type II. Il cherche sur une grille de 2 jours, puis affine par Nelder-Mead 2D, sur des états héliocentriques issus du noyau DE440 ; il s'appuie sur porkchop_kernel. La comparaison a été préenregistrée (bf0439e8) par rapport à un optimiseur indépendant SPICE + pykep 3.0.1 + SciPy 1.18.1 sur l'opportunité Terre vers Mars de 2026 : les quatre optimisations concordent à 8.7e-13 en relatif, avec des dates à moins de 1e-5 jour (VALIDATED, nouvelle ligne du registre). Comme référence publiée secondaire, NASA/TM-2010-216764 (le manuel Terre vers Mars 2026-2045) concorde pour le C3 minimal du Type II (9,182 contre 9,144) et pour le V-infini minimal à l'arrivée du Type II (2,564 contre 2,565). Son C3 minimal du Type I ne concorde pas : 10,535 contre 11,11 (-5.18 %), alors que la référence indépendante de bibliothèque concorde avec Kshana. Cet écart est consigné et affirmé.

  • Étude d'une station de référence lunaire (0,36, motivée par des documents publiés sur une station de référence lunaire prévue au pôle sud ; sources dans docs/LUNAR-REFERENCE-STATION.md) : le type de scénario lunar-station-coverage, un balayage Monte Carlo du modèle PNT différentiel lunaire sur une grille d'utilisateurs polaire sud et une journée d'époques, donnant par point et sur la région l'erreur corrigée et non corrigée en centiles, la disponibilité avec ses raisons, la couverture par rapport à un seuil énoncé, les niveaux de protection, le rayon de couverture par azimut et le bilan de la liaison de corrections. Il se réduit exactement à lunar-differential-pnt en un point, une époque et un essai ; son arithmétique a été recalculée par numpy sous un seuil préenregistré (positions et centiles atteints ; les corrections de la station ont manqué les leurs à cause d'arrondis en double précision, consigné). MODELLED ; ligne du registre « Carte de couverture et de précision d'une station de référence lunaire ». Sans affiliation ni aval d'aucune agence ; aucune déclaration sur les performances d'un système réel.

  • Prédiction préenregistrée : couverture d'une station de référence lunaire (pas une validation ; MODELLED). docs/predictions/lunar-reference-station.md fige, au commit c05dac1d, les résultats de lunar-station-coverage sous les hypothèses énoncées publiquement, avec des hachages SHA-256 des entrées et des résultats et un protocole de notation fixé dès maintenant (facteur 2 pour les précisions et les niveaux de protection, 10 points de pourcentage pour la disponibilité et la couverture ; une hypothèse modifiée donne une nouvelle prédiction datée, jamais une modification ; un échec est publié aussi visiblement qu'une réussite). Chaque chiffre est dominé par le jeu d'éléments non publié de la constellation de quatre satellites, qui est ILLUSTRATIVE, et le dit. tests/prediction_frozen.rs la protège ; docs/VALIDATION.md gagne une section « Prédictions préenregistrées ». Aucune ligne du registre.

  • Extensions de la station de référence lunaire (0,36 ; les limites 2 et 3 de l'étude de la station et le style de solution des sources), chacune optionnelle sur lunar-station-coverage et absente par défaut, de sorte que chaque document existant, la prédiction figée comprise, est inchangé : [receiver] (trajets multiples a + b exp(-el / el0) chez l'utilisateur et à la station, celui de la station éventuellement de Gauss-Markov sur les époques, bruit de code du DLL issu du C/N0, biais inter-canaux ; valeurs ILLUSTRATIVE sur la Lune) ; orbit_err_growth_m_per_s (croissance linéaire de l'erreur d'orbite diffusée sur la latence de correction, ILLUSTRATIVE) ; [solution] (contrainte de hauteur, minimum de trois satellites avec elle, une fenêtre d'utilisateur statique sur les époques). Deux addenda à la comparaison avec les affirmations publiées, chacun préenregistré seul avant son exécution, figurent à côté de l'exécution consignée non modifiée : K5 avec croissance échoue à chaque taux ; avec le style de solution des sources, K1 à K5 échouent et K6 est franchi (1 sur 6), l'erreur 3D corrigée au p95 de R300 passant de 280,6 m à 2,11 m. MODELLED ; trois lignes du registre.

  • Masques d'horizon de relief lunaire (0,36 ; la première limite de l'étude de la station de référence lunaire) : une section [terrain] optionnelle sur lunar-station-coverage (la station et chaque point utilisateur) et moonlight-service-volume (chaque point de grille) donne à chaque site un horizon dépendant de l'azimut au format de la table de ligne d'horizon de la 0,36, à partir d'un profil énoncé étiqueté avec sa source (station_horizon, user_horizon) et/ou d'un lancer de rayon sur un MNT polaire (dem_path) le long de grands cercles de la sphère lunaire avec la courbure exacte. Intègre au dépôt un extrait de 0,98 Mo du MNT polaire sud LRO LOLA du domaine public LDEM_75S_240M, rééchantillonné par moyenne de blocs 5 x 5 à 1200 m (data/lunar-dem/, avec son NOTICE, son SHA-256 et scripts/make_lola_south_polar_crop.py), et le scénario réservé au dépôt scenarios/lunar-station-coverage-terrain.toml. Vérifié par rapport à des horizons en forme close (sphère nue, cratère dans un plateau, cône rastérisé) ; MODELLED, ligne du registre « Masques d'horizon de relief lunaire à partir d'un profil énoncé ou d'un MNT polaire ». Sans la section, chaque document, bloc d'unités compris, est identique à l'octet près.

  • Confiance tenant compte de la géométrie (note de conception de la géométrie 0,36, section 4). Chaque époque receiver-trust, statique ou navire, par lot ou en direct, porte sa géométrie de satellites : good, degraded (raisons few-satellites, high-pdop, high-hdop, et sky-blocked à titre informatif) ou unknown lorsque le journal ne donne aucune géométrie de satellites, avec le HDOP, le PDOP, le VDOP et les satellites utilisés. Elle est dérivée des élévations et azimuts que rapporte le récepteur (NMEA GSV, UBX NAV-SAT) par le noyau existant orbit::dop, ou prise dans NMEA GSA. Chaque époque porte aussi une étiquette, good, fair ou poor, toujours rapportée et jamais notée, et une note avec le HDOP, le PDOP, le VDOP, le nombre de satellites et la perte de signal en toutes lettres. Le score d'un navire gagne un moniteur geometry qui ne retranche rien sauf si la géométrie est mauvaise (HDOP supérieur à 4, PDOP supérieur à 6 ou moins de 5 satellites utilisés), puis monte progressivement jusqu'à un plafond de 15 points ; la géométrie seule atteint au plus la bande dégradée, jamais la bande non fiable (aucune alarme). Chaque retrait reçoit une classe, geometry, environment ou inconsistency, de sorte qu'un mauvais ciel ne se lit pas comme une attaque. loss-of-lock est geometry lorsque les satellites perdus étaient tous sous 15 degrés à leur dernier rapport ; un retrait pour mauvaise géométrie est inconsistency lorsque le HDOP que le récepteur énonce est en désaccord avec son ciel énoncé de plus de max(1,0, 25 % du HDOP dérivé), de sorte qu'un mauvais ciel falsifié ne peut pas acheter l'étiquette. Une nouvelle table [geometry] énonce chaque seuil avec sa provenance (HDOP 4, PDOP 6, au moins 5 utilisés, sigma_UERE 1,5 m, une tolérance de HDOP de max(1,0, 25 % du HDOP dérivé) avec les 25 % comme choix représentatif pour des récepteurs à horloges par constellation ou à solutions par sous-ensembles, 15 degrés ; les chiffres de l'IEC 61108-1 et du GPS SPS tels que cités, à vérifier par rapport au texte des normes). La perte totale de signal n'est pas étiquetée comme ciel : lorsque des satellites en vue ne sont pas suivis et que le DOP des satellites en vue est bon (et que ceux qui ne sont pas suivis ne sont pas confinés à une moitié de l'horizon), l'époque porte signal_loss et le retrait de géométrie est environment. Un HDOP ou PDOP énoncé de 99 ou plus, une qualité GGA de 0 et un mode GSA de 1 sont lus comme une absence de point, et non comme un DOP. Le plafond (cap_points 15), la fin de la rampe (full_ratio 1,5) et le plancher (floor, par défaut le degraded_min du score) figurent dans [geometry], de même que les bons niveaux de l'étiquette (HDOP 2, PDOP 3, 6 satellites, représentatifs) ; le plafond en vigueur est min(cap_points, 100 - floor), de sorte qu'une table [score] qui relève degraded_min (y compris une de 0,35) abaisse le plafond au lieu d'être refusée, et un plancher sous degraded_min est refusé. MODELLED ; logiciel à titre consultatif, et non un équipement de navigation homologué (IEC 61108, IEC 61162) : l'opérateur reste responsable de la navigation du navire.

  • La géométrie atteint chaque surface : le JSON de résultat (epochs[].geometry, class sur chaque retrait, geometry_model, geometry_summary), les lignes JSON en direct (schéma 1,3), les receiver_trust, assess_vessel_log et receiver_trust_replay Python et WebAssembly, les outils MCP assess_*, les paquets de preuves (epochs.json, config.json, une voie de géométrie sur la page de synthèse) et trust-telemetry (Prometheus kshana_trust_geometry* et une étiquette class sur kshana_trust_reason_active, OTLP kshana.geometry.*, champs personnalisés CEF cs6 (état et classes de géométrie), cfp3 (HDOP) et cfp4 (PDOP), vérifiés par rapport aux deux analyseurs de référence CEF, et LEEF geoStatus, geoHdop, geoClass). L'étiquette de géométrie est exportée aussi, ajoutée après chaque série et chaque champ antérieurs et seulement pour les entrées qui la portent : Prometheus kshana_trust_geometry_label{label} et kshana_trust_geometry_vdop, OTLP kshana.geometry.label et kshana.geometry.vdop, LEEF geoLabel, geoPdop, geoVdop, geoUsed, et CEF un troisième champ cs6 (l'étiquette) et cn1 (satellites utilisés) ; le VDOP n'est pas dans CEF (les champs personnalisés à virgule flottante sont pris). Les deux analyseurs de référence CEF relisent les cas d'étiquette tels qu'écrits (amendement 5 : 176 lignes, 172 analysées par pycef, 176 par Logstash). Un HDOP énoncé que le ciel énoncé n'explique pas est signalé à chaque époque et compté (geometry_summary.hdop_mismatch, une ligne sur la page de synthèse des preuves), noté seulement lorsque la géométrie est mauvaise. La perte de signal est exportée séparément, puisque l'état de géométrie reste degraded tant qu'elle dure : Prometheus kshana_trust_geometry_signal_loss, OTLP kshana.geometry.signal_loss, LEEF geoSignalLoss=1 ; en CEF elle apparaît comme la classe environment dans cs6.

  • orbit::dop_cofactor : le facteur de covariance (HᵀH)⁻¹ derrière orbit::dop, extrait de celui-ci avec la même arithmétique.

  • Ligne du registre « Erreur de position due à la géométrie : erreur RMS = sigma_UERE x DOP » (MODELLED, cohérence interne) : un Monte Carlo à germe fixé de la solution par moindres carrés du moteur sur les 8 géométries DOP appariées à gnss_lib_py par rapport au facteur de covariance du noyau DOP validé, avec des tolérances préenregistrées avant la première exécution et deux contrôles négatifs qui échouent comme requis ; à côté, un contrôle antérieur sur quatre ciels choisis à la main avec des intervalles de confiance du khi-deux, rapporté comme exécuté avant le préenregistrement.

  • Masques de ligne d'horizon dépendant de l'azimut (src/skyline.rs, docs/SKYLINE.md, élément 1 de la note de conception) : une coupure d'élévation qui dépend de l'azimut, le maximum point à point de tables (chacune interpolée séparément, rebouclée à 360°), un canyon de rue en forme close (avec extrémités ouvertes optionnelles), des secteurs à bords nets et un profil de relief avec la courbure de la Terre ; la coupure effective est max(mask_deg, skyline). Quatre préréglages REPRESENTATIVE avec une provenance énoncée (city-street, harbour-approach, fjord, container-terminal), modifiables champ par champ. Une section [skyline] optionnelle dans les fichiers d'entraînement gnss-sim, jamming, leo-pvt (chaque mode, balayage polaire compris), leo-pass et nmea-scenario, et dans orbit et integrity par un nouvel utilisateur au sol, user_site = { lat_deg, lon_deg, height_m } (angles de vue géodésiques sur la Terre en rotation, avec le haut géodésique pour la séparation horizontale et verticale de l'ARAIM ; chaque échantillon est un instant absolu, epoch + t, auquel les jeux d'éléments, les éphémérides diffusées et les fichiers SP3 sont avancés à partir de leurs propres époques, datés à partir de l'époque de satellite la plus récente lorsqu'aucun epoch n'est énoncé ; un user en orbite refuse une ligne d'horizon). Les résultats gagnent skyline { source, open_fraction, provenance } et, par échantillon, masked_by_skyline. Sans la section, chaque scénario est identique à l'octet près à la 0.35.0, vérifié par rapport à des empreintes du commit de version. Six exemples fournis : orbit-urban-canyon-skyline, integrity-harbour-approach, gnss-sim-container-terminal-skyline, jamming-harbour-approach-skyline, leo-pvt-fjord-skyline et la campagne leo-vertical-autonomous-vehicle-skyline (le canyon du véhicule autonome comme coupure plate et comme rue ; la campagne existante est inchangée). MODELLED.

  • Fonctions de géométrie du ciel (src/geometry.rs, élément 2 de la note de conception) : sky_geometry (satellites visibles et masqués depuis un site, à un instant donné et avec des préréglages de constellations, des jeux d'éléments à deux lignes (tle, au plus 4 MiB, propagés par le SGP4 du moteur jusqu'à une epoch UTC) ou des satellites donnés ; sky_source et sky_statement disent si le ciel est représentatif ou bien le ciel que donnent les jeux d'éléments à cette époque, et non une mesure ; tle_skipped liste chaque ligne inutilisée avec sa raison ; plafonds d'entrée de 2000 satellites au-dessus de l'horizon, vérifiés avant qu'une table de système soit construite, et de 16 horloges de récepteur ; les cinq DOP ; le cofacteur et la covariance ENU avec une horloge par système ou une horloge commune ; l'ellipse d'erreur horizontale à un sigma et à une confiance énoncée), sky_monte_carlo (erreurs par moindres carrés à germe fixé, au plus 5000), skyline_presets, skyline_profile et skyplot_svg. orbit::dop_cov expose la covariance derrière orbit::dop, qui en est désormais la réduction (les scalaires validés sont inchangés). Surfaces : kshana sky et kshana skyline, fonctions Python et WASM de mêmes noms, et l'outil MCP sky_geometry (40 outils), et le carnet notebooks/geometry.ipynb (avec son miroir .md ; exécuté par tests/python/test_notebooks.py). Chaque résultat porte l'étiquette MODELLED, l'énoncé du modèle d'erreur et la mention à titre consultatif.

  • Registre : cinq lignes de ligne d'horizon et de géométrie du ciel. VALIDATED, chacune dans une comparaison préenregistrée avant l'exécution de sa référence indépendante : Masque de ligne d'horizon dépendant de l'azimut : ensemble visible, azimut et élévation, et DOP sous le masque par rapport à Orekit 12,2 (TopocentricFrame, ElevationMask) et gnss_lib_py 1.0.4 (get_dop), pires différences d'angle de vue et de masque 1.1e-12° contre 1e-9°, ensembles visibles identiques, DOP 3.3e-13 en relatif (xval/orekit-skyline/) ; Ellipse d'erreur horizontale et cofacteur par système à partir de la covariance de géométrie par rapport à linalg.inv et linalg.eigh de numpy (P2 standard), 270 cas, axes 5.1e-13 en relatif (xval/numpy-ellipse/). MODELLED : les réductions de canyon, de secteur et de relief ; les préréglages ; la composition de la géométrie du ciel (ciel prédéfini, nuage Monte Carlo).

  • Avec les lignes de confiance de la géométrie, de ligne d'horizon et de station de référence lunaire, le registre compte 274 lignes : 134 validées, 136 modélisées, 4 partenaire.

  • Station de référence lunaire : laboratoire de temps de station (MODELLED). Un bloc [time_lab] optionnel sur lunar-time-budget (src/lunar_time_lab.rs). Il modélise une horloge de station (par défaut la classe miniRAFS, toute classe nommée, ou une fiche d'appareil ajustée sur des points de stabilité énoncés) pilotée sur le LTC, puis en roue libre ou re-pilotée toutes les N secondes. Il émet la courbe d'erreur de temps x(t), le temps pour atteindre 1, 10 et 100 ns (bissection à côté de la forme close) et le terme dominant par horizon, le tout avec des unités. Le résidu de pilotage est ILLUSTRATIVE. Le taux du LTC n'est pas redérivé et garde sa propre ligne VALIDATED. L'objectif au niveau de la nanoseconde du document public ICG WG-B Lunar PNT (juin 2024) est cité comme énoncé de source, et non comme revendication. L'ordre des horloges optique < PHM < RAFS < miniRAFS tient de 1 s à 7e5 s, et le test épingle le croisement des courbes PHM et RAFS près de 7.5e5 s. Ce croisement est une propriété des modèles d'horloge à un seul type de bruit (FM de scintillation pure contre FM blanche pure), et non un résultat physique. Sans le bloc, le rapport, sa table et sa synthèse sont inchangés. Exemple : scenarios/lunar-station-time-lab.toml. Ajoute une ligne du registre, étiquetée MODELLED.

  • Station de référence lunaire : géodésie de la station (MODELLED). Des entrées optionnelles extra_reflectors et extra_beacons sur lunar-llr-datum ajoutent un bloc station_geodesy. L'information de datum à cinq réseaux issue de la tranche archivée de télémétrie laser est combinée avec ce qu'apporteraient un rétroréflecteur ajouté et une balise VLBI ajoutée à des sites énoncés. Le réflecteur est visé aux époques archivées où il est visible, avec leurs poids archivés. La balise utilise le réseau et le calendrier de lunar-frame-campaign, les stations étant fixées. Le bloc donne chaque 1-sigma de Helmert avant et après, et leur rapport. Ce sont des bornes de Cramer-Rao pour un jeu de paramètres réduit, sur un calendrier et un site ILLUSTRATIVE. Des entrées absentes ou vides laissent le rapport identique à l'octet près. Exemples : scenarios/lunar-station-geodesy-baseline.toml et -with-station.toml. Ajoute une ligne du registre, étiquetée MODELLED.

  • Station de référence lunaire : comparaison avec les affirmations publiées (MODELLED). Chaque affirmation chiffrée de cinq sources publiques est listée avec sa formulation exacte, sa page et ses hypothèses énoncées, et classée comme comparable, partiellement comparable ou non comparable (tests/fixtures/lunar_station_published/CLAIMS.md ; sources avec URL, date de récupération, SHA-256 et licence dans tests/fixtures/lunar_station/SOURCES.md). Les affirmations partiellement comparables ont été notées sous six seuils unilatéraux préenregistrés avant l'exécution (PREREGISTRATION.md, révision 2, 05bf9a19) : 1 affirmation sur 6 dans le seuil préenregistré (préenregistré 05bf9a19). La couverture est de 0,00 contre >= 0,95 sur les deux cercles polaires sud, et le p95 corrigé est de 280,6 m contre <= 1,5 m. La cause tient aux éléments orbitaux des satellites, qu'aucune source ne publie : sur les éléments ILLUSTRATIVE du dépôt, quatre satellites sont en vue commune dans 8 % des époques, avec une géométrie quasi singulière. L'exécution ne reproduit pas les affirmations sur ces éléments et n'est pas une preuve que les affirmations sont fausses. Épinglé dans tests/lunar_station_published_oracle.rs. Une ligne du registre, étiquetée MODELLED avec le constat.

  • Station de référence lunaire : préparation des données de fichiers d'horloge. realdata::clk::rinex_clock_series énonce désormais le système de temps de ses époques. C'est la valeur de TIME SYSTEM ID ou, lorsqu'elle n'est pas déclarée, la valeur par défaut du système de satellites de l'en-tête. Le résultat indique aussi si le système était déclaré. La fonction refuse un système de temps inconnu (une échelle de temps lunaire, par exemple), un fichier à systèmes mixtes non déclaré, et des fichiers en désaccord, au lieu de les lire comme du temps GPS. Elle fournit une fixture d'horloge de station synthétique. Aucun format de fichier de corrections n'est défini, parce qu'aucun format public n'existe.

Modifié#

  • La documentation de module de fusion::ukf, fusion::tightly_coupled et fusion::gnss_ins_ekf ne présente plus comme un travail futur le navigateur UKF à 17 états, le couplage serré à INS complet et l'état d'horloge explicite ; elle renvoie à hybrid_ukf, tightly_coupled17 et carrier_tc.

  • RINEX 4 n'est plus refusé (0,36, WP-07) : un fichier de navigation RINEX 4 était rejeté volontairement ; il est désormais lu (voir Ajouté). Pour les fichiers d'observation de version 4 et ultérieure, les étiquettes d'en-tête ne sont appariées que dans les colonnes 61-80, de sorte que les nouveaux enregistrements de texte libre ne peuvent pas passer pour des étiquettes.

  • ionex::parse_ionex lit de vrais fichiers IONEX (0,36, WP-07) : un enregistrement complet de 16 valeurs remplit les colonnes 61-80, que le lecteur prenait pour une étiquette, de sorte qu'il renvoyait None sur chaque vrai fichier IONEX. Il lit désormais comme des valeurs un enregistrement dont le champ d'étiquette est numérique. Aucune sortie livrée ne l'utilisait.

  • Puissances reçues Galileo E1 et E5a selon l'OS SIS ICD Issue 2,1 (révision, 2026-10-14). Les bandes de spectre galileo-e1 et galileo-e5a, et les victimes GNSS du signal LEO qui en tirent leur puissance, utilisent désormais les puissances reçues minimales de la Table 12 de l'OS SIS ICD Issue 2,1 de Galileo : −157,25 dBW (auparavant −157,0) et −155,25 dBW (auparavant −155,0).

    • Neuf résultats de scénario changent : les exemples de spectre, la campagne de spectre, trois verticales de résilience LEO et trois conceptions de signal LEO. Le C/N0 effectif varie de −0,25 dB et le J/S de +0,25 dB sur ces bandes.
    • Chaque valeur modifiée (1766, ancienne → nouvelle) est listée dans docs/revisions/CAP12-galileo-icd21-power-changes.md et son CSV, avec les tables de documentation qui ont changé. Aucune ligne du registre ne change de statut.
    • Seconde partie, le même jour : les victimes du signal LEO galileo-e5b (−155,0 → −155,25 dBW, Table 12 E5b) et galileo-e5-altboc (−152,0 → −152,24 dBW). L'ICD n'a aucune ligne E5 pleine bande, de sorte que la valeur AltBOC est la somme des puissances des totaux E5a et E5b de la Table 12, construite comme l'ancienne valeur. Trois résultats de conception de signal LEO changent (64 valeurs : ces puissances reçues et la dégradation du C/N0 du LEO vers le GNSS sur les deux victimes), listés dans la même révision (§5) et le même CSV. Rien d'autre ne change.
  • Correction de la marée atmosphérique S2 (tides::atmospheric_tide). Les harmoniques S2 de pression de l'air de Ray (2001) sont des coefficients de P_nm non normalisés avec des retards de phase en cosinus ; elles étaient utilisées comme entièrement normalisées avec le retard pris comme l'avance en sinus de l'IERS. Elles entrent désormais divisées par N_nm avec ε = 90° − ψ ; le nouveau tides::s2_air_waves reproduit le modèle A2 de la Table 5 de GFZ STR06/01 pour les 21 ondes (pire 0,0005 cm, 0,05° ; VALIDATED). Seules les sorties avec marée activée changent : l'ajustement Galileo de CI 0,132 → 0,133 m, les composantes de Swarm-A de 1–2 mm (préenregistré dans xval/s2-air-tide-fix/).

  • Documentation seulement : propagator::solve_kepler_checked, orbit::solve_kepler et ephem::solve_kepler sont documentés comme des résolveurs hérités, numériquement inchangés, renvoyant à kepler::solve_kepler_markley.

  • État du tour 3 de D9 (utck_bound). La Circular T 465 du BIPM est parue le 2026-10-12. Le score prospectif préenregistré n'est toujours pas exécuté : le numéro 465 contient environ 285 valeurs de test, et la règle d'arrêt en exige 1000, soit environ les numéros 465–468. L'exécution exige aussi les fichiers archivés par laboratoire du 2026-09-30, parce que le BIPM a depuis réécrit 87 des 113. La ligne du registre et l'en-tête du test le disent ; le test, ses seuils et sa partition sont inchangés.

  • Passe de vérité de la documentation (0,36). Feuille de route, lignes de capacités, lignes d'état des documents de conception et commentaires de modules mis en accord avec le code ; aucune sortie ne change. Les éléments déjà construits mais encore listés comme ouverts sont désormais marqués terminés : les contrôles de gabarits ITU-T, le scénario de holdover de 24 h et l'ingestion de journaux d'horloge (synchronisation de télécommunications), les démarrages rapides de la première minute, Lense–Thirring et la vérification croisée du propagateur avec Orekit, la chaîne GCRS précise ITRF, les hachages de référence et multiplateformes, la provenance, l'ARAIM multi-défauts (ADD v4.2), la FDE à un seul satellite, la bibliothèque CRPA, la limite d'ambiguïté de franges CAI, le dimensionnement par rues de couverture et la vue d'orbite 3D, la dynamique d'attitude du corps rigide, l'écrivain OMM et le lecteur de noyaux NAIF, la libration lunaire DE440, la phrase de sens de l'exécution dans le terrain de jeu, PositioningFom, le navigateur à couplage serré à 17 états et le type de scénario gravity-map. Les lignes indiquent aussi précisément ce qui reste ouvert (par exemple la JD en deux parties dans orbit::Propagator, le lecteur src/ionex.rs par rapport à un vrai produit, et l'exclusion multi-satellites dans raim). Le docs/design/evidence/cn0-m2m4/RESULTS.md manquant est écrit à partir d'une exécution récente de ses tests (M1–M4 réussis), et le brouillon de validation IQ destiné aux partenaires porte les décomptes actuels du registre.

  • Les codes mémoire Galileo E1 ne sont plus fournis avec le logiciel. data/galileo-os-sis-icd/C7_E1B.txt et C8_E1C.txt (annexe C.7/C.8 de l'ICD) sont retirés du dépôt et des paquets. Les conditions de l'ICD (citées dans LICENSING.md) permettent à un utilisateur de conserver les codes en mentionnant la source et de les utiliser dans un produit, mais n'autorisent la redistribution qu'à des fins non commerciales, et Kshana est aussi proposé sous licence commerciale. galileo::e1b_table / e1c_table renvoient désormais un Result et lisent la copie propre à l'utilisateur depuis KSHANA_GALILEO_E1B / KSHANA_GALILEO_E1C ou, dans une copie source, depuis data/galileo-os-sis-icd/, où le nouveau scripts/fetch_galileo_e1_codes.sh les extrait du PDF de l'ICD (avec vérification de l'empreinte). galileo::E1B_TABLE_TEXT / E1C_TABLE_TEXT sont supprimés. Sans les tables, les signaux Galileo E1 (galileo-e1b, galileo-e1c) renvoient une erreur qui indique comment les fournir, et les tests E1 sont ignorés avec un message. Avec les tables en place, chaque sortie E1 est inchangée. Aucune sortie de scénario, de référence figée (golden) ou de spectre n'utilise les tables de codes. Les fichiers de test de l'annexe C.3/C.4 pour E5a (la référence indépendante LFSR dans tests/iq_signals.rs) sont traités de la même manière : récupérés par le même script, exclus de git, et le test est ignoré en leur absence.

  • Mathématiques portables partout (0,36, STUDIO-15) : toutes les fonctions transcendantes f64 de la bibliothèque, ainsi que les échantillonneurs normal, gamma et exponentiel de rand_distr, calculent désormais via libm en Rust pur (portable_math::PortableFloat, portable_distr), de sorte qu'une compilation native et la compilation WebAssembly renvoient un JSON de résultats identique à l'octet près pour les 141 scénarios fournis et pour la courte exécution IQ. Le coût est que les derniers bits des résultats calculés avec la bibliothèque mathématique de l'hôte ont bougé : 98 des 141 scénarios fournis ont changé, 43 non ; 5 ont changé de plus de 1e-3 dans leur plus grand champ, et les autres de moins. Chaque valeur modifiée est listée ancienne -> nouvelle dans docs/revisions/STUDIO15-portable-math-rebaseline.md (avec un CSV de tous les 136 127 nombres modifiés) ; aucun seuil ni aucune tolérance n'a changé. Chiffres publiés qui ont changé : disponibilité de europa-surface-pnt avec la portée Terre 0,719 -> 0,713 et erreur RMS 86,147 -> 86,499 m (une époque en limite de disponibilité se résout désormais de la même façon partout ; elle affichait 0,725 / 85,800 m sur macOS arm64) ; erreur de station de lunar-joint-od-clock 3,541350 -> 3,536885 m avec VLBI et 2183,558 -> 2184,021 m sans ; paper/crossover/inertial.json, huit valeurs de vibration_psd de 3 unités sur le dernier chiffre (erratum dans le rapport technique) ; le document cislunar-observability publié, pour des grandeurs au plancher d'arrondi (huit valeurs au-delà de six chiffres significatifs, jusqu'à 6.8e-5 en relatif ; aucun rang ni seuil n'a bougé). Les empreintes figées des garde-fous d'identité à l'octet (skyline_scenarios, geometry_corpus_identity, geometry_trust_no_change) sont rebasées sur une référence de base nommée « 0,36 portable », les valeurs 0.35.0 étant conservées comme trace historique ; la prédiction figée de la station de référence lunaire n'est pas touchée et sa réexécution portable est stockée à côté (docs/predictions/*.portable-0.36.json). tests/lunar_joint_od_numpy_oracle.rs (la ligne validée de détermination d'orbite conjointe lunaire) : jeux de test réexportés et comparaison numpy relancée avec numpy 2.4.6, la version enregistrée, le script et le seuil restant inchangés ; les six réseaux passent (docs/revisions/STUDIO15-lunar-joint-od-oracle-rerecord.md). Le travail des lots 2-3 fusionné après STUDIO-15 utilise lui aussi les mathématiques portables (457 points d'appel dans 62 fichiers) ; ce qu'il a modifié figure dans docs/revisions/STUDIO15-batch4-rebaseline.md : 12 scénarios fournis (plus grand changement relatif 5.2e-8, aucun chiffre affiché ne bouge), 28 lignes de garde-fou skyline réétalonnées, le condensé M2M4 de iq_campaign, les empreintes de vérité terrain de l'ancien gnss-ins, le sigma de référence (datum) des balises non observées (632,3769 -> 632,3772 m), et deux constats consignés (fermetures DRO du CR3BP ; CRPA A3, 194 liaisons sur 456). L'edf exact de Greenhall conserve son seuil validé grâce à un logarithme en double-double dans son noyau (docs/revisions/STUDIO15-greenhall-edf-portable.md), et la référence indépendante du banc d'essai gps-sdr-sim a été relancée sur les exports NMEA modifiés, chaque seuil étant respecté (docs/revisions/STUDIO15-testbench-gpssdrsim-rerun.md).

  • README : la ligne de la suite lunaire indique le niveau de preuve de chaque élément (elle disait que tous étaient MODELLED).

  • realdata::clk::rinex_clock_series renvoie RinexClockSeries (série, journal de grille, système de temps, indication de sa déclaration, type d'enregistrement) au lieu d'un tuple (PhaseSeries, GriddingLog). Elle se rabat désormais des enregistrements de satellite (AS) vers les enregistrements de récepteur/station (AR) du nom demandé.

  • Aucun score ne change tant que la géométrie n'est pas mauvaise ; l'étiquette est toujours indiquée. Avec une géométrie bonne ou moyenne (y compris un ciel dégagé GPS seul de 8 satellites) ou une géométrie inconnue (le moniteur ne tourne pas), chaque score est identique à celui de 0,35 : tests/geometry_trust_no_change.rs fige les sorties des deux sessions d'exemple et tests/geometry_corpus_identity.rs chaque corpus NMEA de navire versionné dans le dépôt (y compris en ciel dégagé GPS seul) et les scénarios d'entraînement d'équipage aux octets de 0.35.0 une fois les clés ajoutées retirées ; dans les deux scénarios d'entraînement dont le brouillage rend la géométrie mauvaise, les époques mauvaises ne diffèrent que par la seule déduction liée à la géométrie. Un journal à mauvaise géométrie perd jusqu'à 15 points qu'il ne perdait pas en 0,35. Changements voulus par ailleurs, tous des ajouts : les clés ci-dessus dans le JSON de résultats et les paquets de preuves (score_model.weights est inchangé) ; le schéma JSON-lines en direct passe de 1,2 à 1,3 (geometry ajouté, class dans chaque déduction) ; le résumé d'extrait gagne geometry ; la télémétrie gagne des séries, des champs de géométrie et l'étiquette class uniquement pour les entrées qui en portent, de sorte qu'un flux ou un résultat 0,35 s'affiche octet pour octet comme avant. geometry est le 17e nom de moniteur ; il est listé en dernier dans monitors_run lorsqu'il a statué (un navire dont le journal fournit la géométrie ; une liste 0,35 garde son ordre et le nombre de moniteurs du résumé augmente d'une unité) et n'a pas d'entrée [score.weights] (en définir une est refusé : sa déduction se règle dans [geometry]).

  • tests/fixtures/dop/NOTICE indiquait que la licence de gnss_lib_py était Apache-2.0 ; la version 1.0.4 est sous licence MIT.

  • Le lecteur NMEA lit désormais GSA (un GSA court est ignoré, sans être compté comme sauté) et conserve les élévations et azimuts GSV, y compris pour les satellites listés sans signal ; le lecteur UBX conserve l'élévation et l'azimut de NAV-SAT. Le C/N0 est lu exactement comme avant.

  • Changement de résultat : les brouilleurs à large bande et à balayage utilisent désormais Q = 2. L'équation anti-brouillage utilise l'ajustement Q classique de l'étalement de spectre pour ces brouilleurs, là où elle utilisait 1. Q = 2 correspond à un bruit blanc sur le lobe principal avec la puissance du signal dans la bande normalisée ; il est figé dans les tests sur la forme analytique issue de navsignal.

    • Inchangés : les brouilleurs CW et à bande étroite (Q = 1), un type de brouilleur non reconnu (Q = 1, la valeur la plus pénalisante), et q_override.
    • Effet : là où un brouilleur à large bande ou à balayage agit, le C/N0 effectif augmente jusqu'à 3,0103 dB, les seuils J/S dérivés augmentent de 3,0103 dB, et les rayons de déni en espace libre diminuent d'un facteur 0,7071.
    • Scénarios fournis modifiés : 12 sur 144 changent, tous comme préenregistré (xval/jammer-q/PREREGISTRATION.md, résultats dans xval/jammer-q/RESULTS.md) :
      • jamming-demo : C/N0 +3,01 dB ;
      • jamming-harbour-approach-skyline: min_tracking 6 → 7;
      • lunar-jamming : satellites perdus 26 → 0, distance de sécurité médiane de perte d'accrochage 27,4 → 19,4 km ;
      • tracking-loop : rayon de déni de la dynamique de boucle 75,2 → 53,2 km ;
      • et les campagnes et vérifications croisées de spectre qui les contiennent.
    • Consommateurs concernés : les types de scénario jamming, lunar-jamming, tracking-loop et impairment-eval, la jamming_kind_cross_check des types de scénario de spectre, la courbe de référence MODELLED de la campagne IQ et le Q par défaut de labfit, ainsi que l'export de scène d'interopérabilité.
  • Greffon JetBrains : aucune API de plateforme obsolète ou dont le retrait est programmé. Les cinq boîtes de dialogue de choix utilisent un petit DialogWrapper avec une liste déroulante à la place de Messages.showChooseDialog, obsolète ; les sélecteurs de fichier unique utilisent le constructeur FileChooserDescriptor à la place de FileChooserDescriptorFactory.createSingleFileDescriptor(), obsolète ; l'animation s'ouvre avec BrowserUtil.browse(Path) à la place de browse(File), dont la plateforme 2026,3 programme le retrait. Since-build reste 243. L'IntelliJ Plugin Verifier signale Compatible, sans usage obsolète ni programmé pour retrait, face à 2024,3 (IC-243.21565.193), 2025,2 (IC-252.23892.409), 2026.2.3 (IU-262.10968.63) et 2026,3 EAP (IU-263.6259.32) ; verifyPlugin vérifie 2024,3 par défaut et toute liste fournie dans KSHANA_VERIFY_IDES.

  • gnss_sim::run_gnss_sim et jamming::run_jamming renvoient Result : une section [skyline] non valide est une erreur lorsqu'on appelle directement, comme c'était déjà le cas via api::run_toml, plutôt qu'un repli silencieux sur le masque plat. Changement incompatible pour les appelants Rust de ces deux fonctions.

Corrigé#

  • Évaluateur de campagne : un vrai faux accrochage du suiveur n'était jamais compté (iq::campaign). Le contrôle de faux accrochage du suiveur fait passer un canal de LOCKED à LOST au moment où il se déclenche. L'évaluateur marquait à la place la mise à jour suivante du canal, qui était alors déverrouillée et n'était donc jamais comptée. Un événement false-lock signalé depuis LOCKED est désormais un épisode à son instant, dans l'exécution et dans chaque événement déclaré qui le contient. Un épisode trouvé pendant la phase d'acquisition, ou répété par un canal déjà LOST, n'est pas un nouvel épisode. Un nouveau test provoque un vrai faux accrochage : une porteuse GPS L1 C/A légitime qui fait un saut de 1/(2T) alors qu'elle est accrochée (tests/iq_campaign_false_lock.rs).

    • Dans la campagne de référence de tests/iq_campaign.rs, seul le PRN 11 de ramp/agc-3bit change (épisodes de faux accrochage 0 → 1, 426 et 437 par heure d'accrochage).
    • Ses DIGESTs de cellule sont de nouveau figés.
    • Le point de contrôle préenregistré des résultats évalués reste actif et se reproduit toujours exactement : dans son empreinte, seuls ces six champs, modifiés par cette correction faite après l'enregistrement, sont ramenés à leurs valeurs d'avant la correction. Les valeurs corrigées sont figées séparément.
    • Aucun seuil n'a été modifié, et aucune ligne VALIDATED, aucun chiffre ni aucun nombre du site web n'a bougé.
  • lunar-frame-campaign : une balise sans observation est désormais signalée (trouvé par MR-05). Le rapport gagne unobserved_beacons et warning uniquement lorsqu'une balise n'a aucune observation, et les sigmas des balises observées proviennent alors de leur propre information au lieu d'être tous nuls. Le datum est inchangé, et aucune sortie par défaut, fournie ou publiée ne bouge (docs/revisions/BEACON-unobserved-cell-changes.md).

  • Référentiel lunaire des axes principaux (lunar_frame::icrf_to_moon_pa, utilisé par lunar_od et par l'ajustement LRO) : le décalage DE421 entre le référentiel moyen Terre et les axes principaux (PA), défini dans moon_080317.tf, était appliqué dans le mauvais sens et avec le mauvais ordre d'angles d'Euler, de sorte que le référentiel PA analytique se trouvait à environ 208″ du PA au lieu de coïncider avec lui. Il est maintenant transcrit comme le définit le Frames Required Reading de SPICE et s'accorde avec pxform('MOON_ME','MOON_PA') de SPICE à 2.6e-16 rad près ; le référentiel PA analytique est à 6″ à 8″ du PA de DE440 (préenregistré e1ead19b, réenregistré be33382e après que la première modification proposée a manqué le seuil de 1e-12 ; docs/design/evidence/fut05b-me-pa-offset-sign/). Chiffres publiés qui bougent : l'ajustement LRO (tests/agency_lro.rs) recouvrement brut 53,8 → 39,9 m, dynamique 12,6 → 12,05 m, dynamique réduit 6,65 → 6,67 m (seuils inchangés). La pile analytique concorde maintenant avec la validation croisée ANISE de niveau DE (12,0 / 6,67 m) sur les deux niveaux ; l'écart antérieur du niveau dynamique venait de cette erreur.

  • Le serveur MCP refuse [terrain] dem_hgt (suite de CAP-06b). Le chemin de la tuile de terrain du type de scénario de brouillage figure désormais dans inline_only::FILE_SOURCE_KEYS. Une surface en ligne refuse un scénario qui en nomme un, avec un message qui ne contient ni le chemin ni une erreur du système d'exploitation. Le test de garde des sources de fichier signale aussi désormais les champs se terminant par _hgt.

  • Jd2::from_parts avec une partie de jour fractionnaire perdait la fraction dans les conversions UTC, TAI, UT1 et de rotation terrestre (une heure de partie de jour faisait dévier la Terre de 15°) ; la partie de jour est maintenant normalisée en entier. Aucun appelant du moteur n'a été touché : tous passent un jour entier, et chaque sortie livrée est identique bit à bit.

Prévu#

  • La géométrie à partir d'un horizon (skyline) indiqué (élément 1 de 0,36, désormais dans le moteur sous la forme src/skyline.rs) : sky-blocked et open_fraction issus de l'horizon lorsque l'entrée en fournit un (l'intervalle d'azimut en repli), un événement de dégradation naturelle (fjord ou terminal) dans nmea-scenario, et les deux géométries masquées de la note de conception dans la ligne sigma_UERE x DOP, préenregistrées sous forme d'addendum.
  • La géométrie pour les journaux RINEX avec navigation (à partir du calcul de position propre au moteur) et les journaux Android (à partir des lignes Status) ; les deux affichent unknown aujourd'hui. La géométrie dans $PKSHT (version 1 inchangée en 0,36) et les intégrations Signal K et OpenCPN.
  • Une lacune préexistante, non introduite en 0,36 : dès que le champ SNR de chaque satellite est vide, aucune déduction loss-of-lock ni C/N0 ne se déclenche ; la perte totale de signal n'est visible qu'à travers signal_loss du moniteur de géométrie (classé environment). Une déduction pour ce cas est prévue.
  • Un flux de schéma 1,3 dans les références indépendantes de télémétrie externes (l'analyseur de format texte Prometheus et le collecteur OTLP), qui ne couvrent aujourd'hui que les flux 1,2.
  • Une obstruction des deux côtés (un canyon ou un fjord étroit) se lit comme une perte de signal plutôt que comme un ciel bloqué tant que l'horizon n'est pas intégré.

[0.35.0] - 2026-10-12#

Un passage nommant des clients d'IA tiers est omis ici ; il figure dans CHANGELOG.md sur GitHub.

Vérificateur Galileo OSNMA#

  • Nouveau module kshana::osnma et kshana osnma verify <input> : un vérificateur ouvert, en Rust pur, côté récepteur pour Galileo OSNMA. Il lit les pages I/NAV et indique, par satellite et par époque, si les données de navigation sont authentifiées, avec une raison pour chaque échec ou retard : analyse de HKROOT et MACK, réassemblage de DSM-KROOT et DSM-PKR, vérification de Merkle de la clé publique, vérification de la chaîne de clés TESLA, vérification de MACSEQ et des étiquettes pour ADKD 0, 4 et 12 y compris l'authentification croisée, et un résultat de forme $PKSOS pour le moniteur de confiance du récepteur. La sortie porte une mention indiquant que l'état n'est pas un service d'intégrité de la navigation. docs/OSNMA.md indique ce qui est et n'est pas vérifié, l'exigence de temps, et que Kshana n'accorde aucun droit au titre des droits de propriété intellectuelle de l'UE sur l'ICD OSNMA (les utilisateurs s'appuient sur l'autorisation de l'annexe E de l'ICD). Implémenté d'après le SIS ICD Issue 1,1 et les Receiver Guidelines Issue 1,3. Les pages sont contrôlées par CRC, et un flux d'octets UBX-RXM-SFRBX d'un u-blox peut être lu directement (--format ubx). Les tests par défaut utilisent des données synthétiques et des tests à réponses connues publiés pour les primitives ; un test facultatif lit une copie téléchargée localement des vecteurs officiels. Après relecture indépendante, le vérificateur ne tire son temps que de clés TESLA vérifiées (une sous-trame leurrée située très loin dans le futur ne peut plus effacer un échec), laisse une authentification expirer et suivre l'IODnav utilisé, tient compte des messages d'alerte vérifiés (dont la feuille de Merkle inclut désormais le champ aléatoire NPK) et de l'état NMA « don't use », garde les étiquettes factices hors de l'état du satellite, conserve les chaînes par CID avec révocation et renouvellement, vérifie l'empreinte de remplissage de KROOT, et plafonne les longueurs de trame UBX et le travail de vérification TESLA. Un satellite n'apparaît authentifié que tant que les données d'éphéméride et d'horloge les plus récentes qu'il envoie sont, bit pour bit, les données qui ont été authentifiées (et pas seulement sous le même IODnav), un état ou une révocation provenant de l'en-tête NMA non authentifié ne compte que lorsque deux satellites concordent ou qu'un KROOT vérifié le porte, un ancien KROOT rejoué ne peut pas remplacer une chaîne, et un flux de clés bloqué est signalé.

Ajouté (canaux du serveur MCP)#

    Un passage nommant des clients d'IA tiers est omis ici ; il figure dans CHANGELOG.md sur GitHub.

  • kshana-mcp --http <addr>, HTTP en flux (streamable), auto-hébergé. Bouclage local par défaut ; une adresse hors bouclage exige --allow-remote et un jeton porteur dans KSHANA_MCP_HTTP_TOKEN ; aucun outil ne lit ni n'écrit de chemin (les outils de fichiers IQ sont désactivés) ; limites de taille, de durée et de concurrence des requêtes ; pas d'en-tête CORS ; contrôles de Host et d'Origin. Kshana n'héberge aucun point d'accès (docs/deploy/mcp-http.md, avec des modèles Docker, Fly.io et Cloud Run).

Ajouté (surfaces)#

  • osnma_verify sur Python et WebAssembly. Le vérificateur derrière kshana osnma verify sur des octets en mémoire, renvoyant le JSON qu'affiche --json (mention indicative dans son champ advisory ; état d'authentification seulement, et non un service d'intégrité de la navigation). Les mêmes refus que la ligne de commande. Pas sur MCP : l'entrée est un long flux brut de récepteur, mieux servi par la CLI et Python. docs/SURFACES.md et docs/OSNMA.md le précisent.

  • trust_telemetry sur WebAssembly, Python et MCP, avec une commande de greffon et une action JetBrains. Rend un flux de confiance ou un résultat receiver-trust sous forme de texte Prometheus, de lignes syslog CEF ou LEEF, ou de charge utile JSON OTLP, avec les encodeurs qu'utilise kshana trust-telemetry (kshana::surface::trust_telemetry) ; ni socket ni horloge. Greffon : /kshana-trust-telemetry et la compétence trust-telemetry. JetBrains : Render Trust Telemetry. Les fonctionnalités wasm et python ainsi que le serveur MCP activent désormais aussi otlp, qui n'ajoute aucun crate.

  • Balayage de parité. Actions JetBrains Validate Scenario, List Scenario Kinds et Assess Receiver Stream ; kshana --help liste désormais receiver-trust evidence, evidence, trust-telemetry et nmea-scenario ; le notebook compliance-and-test-bench (correspondance compliance et export de banc d'essai) ; et chaque cellule JetBrains « CLI uniquement » restante dans docs/SURFACES.md est maintenant un N/A explicite avec sa raison.

  • Un passage nommant des clients d'IA tiers est omis ici ; il figure dans CHANGELOG.md sur GitHub.

Ajouté (paquets de preuves)#

  • kshana receiver-trust evidence et kshana evidence verify : des paquets de preuves signés et vérifiables pour un événement de confiance GNSS. Un paquet regroupe l'extrait brut du journal et le SHA-256 du journal complet, la configuration avec chaque seuil, les résultats et raisons par époque, la version du moteur, un manifeste chaîné par empreintes et un résumé HTML autonome, signés en Ed25519 (une clé issue de kshana evidence keygen ou votre propre fichier ; les clés ne sont jamais stockées dans un paquet et *.evidence-key est exclu de git). verify vérifie chaque empreinte, la chaîne et la signature et nomme exactement ce qui échoue ; avec --pubkey il épingle le signataire. Un jeton RFC 3161 peut être joint, et il est lu et lié au manifeste (la signature propre de l'autorité n'est pas vérifiée par cette version ; openssl ts -verify la couvre). L'extrait du journal correspond aux octets exacts de la fenêtre lorsque le lecteur indique les plages de la source (NMEA, UBX, RINEX 3, Android), sinon au journal entier, et le manifeste indique lequel. La création et la vérification sont de pures fonctions publiques (kshana::evidence) qui se compilent pour wasm32. Les paquets précisent qu'ils sont un dossier technique, et non un avis juridique. Les nouvelles dépendances sont l'arbre ed25519-dalek (BSD-3-Clause et Apache-2.0/MIT, fonctionnalités minimales) et un zeroize direct (déjà dans cet arbre) pour effacer le matériel de clé. Voir docs/EVIDENCE-PACKS.md.

Ajouté (télémétrie de confiance)#

  • kshana trust-telemetry : la confiance GNSS comme source de télémétrie de sécurité. Lit le flux de confiance par époque (lignes JSON : score 0-100, bande, raisons) ou un résultat receiver-trust par lots et alimente un point d'accès Prometheus /metrics (localhost par défaut), des événements syslog en CEF ou LEEF dans une enveloppe RFC 5424 (UDP ou TCP) et, derrière la fonctionnalité otlp désactivée par défaut, un export JSON OTLP/HTTP. La livraison s'exécute sur des fils de travail avec des limites de temps de connexion et d'écriture, un recul de reconnexion plafonné et un compteur kshana_trust_syslog_send_failures_total, de sorte qu'un collecteur mort ou bloqué ne peut ni bloquer l'évaluation en direct ni geler /metrics ; les étiquettes de raison sont plafonnées à 64 séries. Aucune nouvelle dépendance. Un exemple de tableau de bord Grafana se trouve dans deploy/grafana/. Les noms de métriques, les étiquettes et la correspondance des champs CEF/LEEF sont dans docs/TRUST-TELEMETRY.md. Le format du flux est isolé dans src/telemetry/sample.rs.

Ajouté#

  • Confiance maritime : un score de confiance en direct de 0 à 100 pour la position d'un navire en mouvement, à partir du NMEA 0183 que le récepteur produit déjà, avec une barrière activable. kshana receiver-trust accepte une table [platform] (kind = "static" ou "vessel", la vitesse, l'accélération et la vitesse de giration maximales du navire, la hauteur de l'antenne au-dessus de la ligne de flottaison et un capteur de cap facultatif ; chaque valeur par défaut est documentée avec sa raison). Pour un navire, le moniteur de saut de position statique, qui mesure la distance à la moyenne d'étalonnage et se trompe sur un navire en route, est remplacé par des moniteurs causaux de plateforme mobile : cohérence cinématique de la position avec la vitesse et la route signalées et avec les limites du navire, cap gyroscopique par rapport à la route fond, loch par rapport à la vitesse fond, altitude de l'antenne par rapport à la hauteur indiquée au-dessus de la ligne de flottaison, effondrement de la dispersion du C/N0 et hausse simultanée par rapport à la référence de base d'étalonnage, et cohérence temporelle (aussi avec l'horloge de cet ordinateur, en mode direct). Il lit aussi un état d'authentification signalé, global ou par satellite (un état signalé seulement : pas de cryptographie OSNMA). Chaque seuil est indiqué dans une table [maritime] avant l'exécution. Chaque époque reçoit ensuite un score de 0 à 100 par une correspondance déterministe et préenregistrée (sans apprentissage, rien d'ajusté sur des événements ; les poids, les bornes des bandes et la preuve se trouvent dans une table [score]), reportée sur les états de confiance existants, avec les moniteurs qui ont déduit et leurs points. Les scénarios statiques sont inchangés et ont la même empreinte qu'avant. kshana receiver-trust live <session.toml> lit l'entrée standard, un fichier en cours d'ajout, TCP ou UDP et écrit une ligne JSON par époque et une phrase propriétaire $PKSHT ; avec --gate il transmet le flux inchangé tant que la position est jugée fiable et marque la position comme invalide (qualité GGA 0, état RMC et GLL V, mode GNS et VTG N) tant qu'elle ne l'est pas. La barrière est désactivée sauf demande ; --listen tcp:<port> sert le flux filtré à un nombre quelconque de clients TCP (bouclage local par défaut, un client lent est déconnecté plutôt que de bloquer les autres). Il s'agit d'un logiciel à titre consultatif, et non d'un équipement de navigation homologué (IEC 61108, IEC 61162) ; l'opérateur reste responsable. examples/maritime-trust/ est un journal synthétique de Tallinn à Helsinki, écrit en texte seulement, avec un décrochage de position en cours de route pendant lequel le récepteur continue d'indiquer une position valide ; sa sortie attendue est figée par un test. Guide : docs/MARITIME-TRUST.md. Les contrôles ne peuvent pas voir un leurre dont la position est cohérente avec tout ce qui circule sur le bus ; le guide le dit.

Carte des interférences#

  • kshana interference-map et kshana route-exposure : un tableau public des endroits où des aéronefs et des navires ont signalé des données de navigation dégradées, et de la part d'une route qu'elles touchent. Les entrées sont des fichiers CSV locaux produits à partir de données ouvertes sous licence libre ADS-B (adsb.lol, ODbL 1,0) et AIS (NOAA MarineCadastre, Kystverket sous NLOD 2,0) ; chaque fichier de sortie correspond à une source et à un jour UTC de GeoJSON portant la méthode, ses seuils, la licence des données, l'attribution et le biais de couverture de la source. La méthode ADS-B agrège NIC et NACp sur une grille fixe et déclare une cellule dégradée d'après la part d'aéronefs distincts, avec des garde-fous pour les équipements qui ne signalent jamais la précision, la basse altitude et les causes à grande échelle. La méthode AIS exécute cinq détecteurs : positions sur terre (par rapport à un trait de côte fourni par l'utilisateur), trajectoires circulaires, sauts invraisemblables, vitesses invraisemblables, et nombreux navires à une même position. Les seuils sont des constantes préenregistrées d'une version de méthode nommée. Agrégats seulement : les identifiants sont hachés en mémoire et jamais écrits, et les cellules de moins de 5 aéronefs ou navires distincts ne sont pas publiées. Une cellule dégradée n'est pas un constat d'interférence. Les commandes par défaut n'utilisent aucun réseau ; un assistant facultatif fetch-land --allow-network télécharge les polygones de terres de Natural Earth depuis une adresse figée sur un commit et ne garde le fichier que si son SHA-256 correspond. L'entrée ADS-B est un CSV ou directement les fichiers d'historique readsb d'adsb.lol (nouvelle dépendance : flate2 avec son moteur en Rust pur, pour gzip). Les deux méthodes sont en version 2 : un appel dégradé ou anormal exige au moins 5 aéronefs ou navires (le minimum de publication), tout effectif par cellule inférieur à 5 est retenu sous la forme null, et un jour dont le bruit de fond ne peut pas être estimé retient ses appels. Les fichiers de sortie sont nommés <source>-<dataset>-<date>.geojson et ne sont jamais écrasés ; l'entrée est lue en flux ligne par ligne ; l'exposition de route gère l'antiméridien. Les tests n'utilisent que des données synthétiques. Voir docs/INTERFERENCE-MAP.md et l'examen des licences dans docs/data/INTERFERENCE-DATA-SOURCES.md.

Ajouté (flux d'entraînement)#

  • kshana nmea-scenario : NMEA 0183 de passerelle synthétique pour l'entraînement des équipages à la reconnaissance du brouillage et du leurrage GNSS. À partir d'un scénario TOML, il écrit un fichier ou diffuse sur TCP ou UDP (en monodiffusion ou en diffusion générale ; en temps réel, accéléré ou aussi vite que possible) l'ensemble complet de passerelle GGA, RMC, VTG, GSV, GSA, GNS, ZDA, HDT et VBW pour la trajectoire d'un navire avec limites de vitesse de giration, d'accélération et de courant, avec une géométrie de satellites issue des constellations nominales propres au moteur. Événements scénarisés sur une ligne de temps : brouillage, décrochage de position (une position valide qui s'éloigne), leurrage du temps et retard de rejeu, chacun avec des rampes d'apparition et de retour. Un journal d'instructeur (JSON et texte) consigne ce qui a été injecté et quand, avec la vraie trajectoire face à celle qui est signalée. Une bibliothèque dans scenarios/training/ (brouillage en haute mer, décrochage côtier, leurrage du temps à l'approche d'un port, combiné) comporte des notes pour le formateur. La sortie a des sommes de contrôle valides et est déterministe pour une graine donnée ; les tests figent un extrait de référence par scénario et relisent chaque phrase avec le lecteur NMEA de receiver-trust. Texte seulement : aucune sortie RF, IQ ou de forme d'onde ; les flux servent à l'entraînement et aux essais et ne doivent jamais être envoyés aux systèmes de navigation en service d'un navire. Voir docs/NMEA-TRAINING.md.

Intégrations maritimes (0.35.0, volet B)#

  • Greffon Signal K (integrations/signalk/, non publié sur npm) : exécute kshana receiver-trust live ou s'y connecte (l'entrée NMEA propre au serveur, des arguments d'entrée personnalisés, un flux TCP JSON-lines, ou les phrases $PKSHT d'un flux filtré), publie le score de confiance, la bande, les raisons, les alarmes et l'état de la barrière sous navigation.gnss.kshana.* (y compris la position signalée par le récepteur à titre de contexte, jamais navigation.position), et émet une notification Signal K (warn si dégradé, alarm si non fiable, avec des seuils de maintien, d'effacement et de péremption, tous dans le schéma de configuration). Aucune dépendance npm. Testé sur une sortie synthétique enregistrée.
  • OpenCPN : le NMEA en mode barrière est servi directement par kshana receiver-trust live --gate --listen tcp:10110 (recommandé) ; un relais TCP sans dépendance (integrations/opencpn/nmea-tcp-relay.mjs) est l'alternative facultative. Dans les deux cas, OpenCPN voit une position invalide lorsque la confiance s'effondre et $PKSHT dans sa fenêtre de débogage NMEA ; les tests rejouent le flux synthétique filtré à travers une vraie socket TCP et vérifient ce que reçoit un consommateur. Un greffon natif de panneau de score (integrations/opencpn/plugin/, API de greffon 1,18, CMake) lit $PKSHT dans le flux NMEA propre à OpenCPN et alerte sur la bande non fiable ; il se compile, sa logique est testée unitairement, et il a été exécuté dans OpenCPN 5.8.4 sous un affichage virtuel (preuves et script de reproduction dans integrations/opencpn/evidence/) ; il n'est pas empaqueté pour le gestionnaire de greffons.
  • Construction de référence (deploy/reference-build/) : liste de pièces générique, configuration du système d'exploitation, unités systemd pour le moniteur indicatif et la barrière facultative (vérifiées avec systemd-analyze verify par check-units.sh), une option de conteneur, câblage Signal K.
  • Le greffon Signal K accepte le schéma JSON en direct 1,2 (une clé position puis une clé advisory ajoutées ; les clés ajoutées inconnues sont ignorées), vérifié sur une vraie sortie 1,2 et face à un vrai signalk-server.
  • Corrections issues de la relecture : les unités systemd redémarrent toujours et s'exécutent en bac à sable (pas de shell, pas de réseau là où il n'est pas nécessaire), un extrait logrotate, check-units.sh échoue au moindre constat ; le conteneur exécute la barrière à partir de variables d'environnement avec un contrôle de santé et des images de base figées par empreinte ; métadonnées de score Signal K, la notification périmée est remplacée lorsque les données reprennent, les erreurs de processus enfants sont conservées et les arrêts forcés s'intensifient, les inputArgs dangereux sont refusés, et la notification se trouve à notifications.navigation.gnss.kshana.trust ; le relais plafonne une ligne partielle retenue ; les analyseurs $PKSHT rejettent les scores en dehors de 0 à 100 ; une vérification des liens de documentation ; un flux de travail CI (marine-integrations.yml) qui exécute tout cela, y compris le vrai binaire de bout en bout.
  • docs/MARINE-INTEGRATIONS.md. Logiciel à titre consultatif, et non un équipement homologué ; l'opérateur reste responsable. Logiciel seulement : rien n'émet, et aucun chiffre de détection ou de fausse alarme n'est revendiqué.

Ajouté : correspondance compliance et export de banc d'essai#

  • docs/compliance/ et kshana compliance-report. Une correspondance entre les sorties de Kshana et cinq cadres et normes de résilience (le Resilient PNT Conformance Framework v2.0 du DHS américain, les orientations de l'OMI pour les navires, les orientations de l'EASA pour l'aviation, l'article 21 de NIS2, l'EN 16803, une norme payante citée par partie et par les quelques numéros de clauses visibles dans le texte du catalogue), un tableau par cadre : la référence, ce qu'elle demande selon notre paraphrase, les sorties qui apportent des éléments de preuve en faveur de celle-ci, et l'écart. Les versions des sources, les URL et ce qui a été lu ou non sont consignés. kshana compliance-report <result.json>... remplit la correspondance à partir des exécutions données et marque chaque ligne evidenced, partly-evidenced, not-evidenced ou out-of-scope, en Markdown et en JSON, avec l'écart conservé sur chaque ligne. La formulation est « apporte des éléments de preuve en faveur de » ; rien n'est évalué ni approuvé. Les tests utilisent des exécutions synthétiques et échouent lorsqu'un tableau versionné s'écarte du code.
  • kshana bench-export <scenario.toml>. Écrit le mouvement du véhicule et les événements d'un scénario gnss-ins, jamming ou gnss-sim pour un simulateur GNSS de laboratoire : un CSV de mouvement utilisateur avec des référentiels documentés et un fichier de métadonnées associé, du NMEA 0183 GGA/RMC, du texte de points de passage, et les événements en CSV et sous forme de blocs receiver-trust [[events]] (src/interop/testbench.rs). Mouvement et événements seulement : aucun signal n'est écrit. Chaque fichier est relu dans tests/interop_testbench.rs et comparé dans la tolérance qu'il indique. docs/TEST-BENCH.md donne la méthode pour rejouer l'export à travers un simulateur et évaluer le journal du récepteur avec kshana receiver-trust.
  • Ce qui compte comme preuve. Un résultat ne compte pour une capacité que s'il porte les champs que son type de scénario écrit ; une étiquette de type de scénario seule ne compte pour rien. Les types de scénario inconnus, un résultat qui contredit son scénario frère, les empreintes non hexadécimales et les décomptes receiver-trust mal formés sont listés comme non utilisés, avec la raison. Le rapport échappe les cellules Markdown et ne peut pas paniquer sur une empreinte non ASCII. compliance::run_from_text et assess_texts prennent des textes, pas des chemins.
  • Export vers banc d'essai. --epoch est contrôlé en plage (UtcEpoch::parse_iso) ; le fichier de points de passage vérifie chaque intervalle et la commande indique pourquoi lorsqu'il est omis ; la documentation précise que le cap de gnss-ins est le lacet du corps et non la route, les champs de substitution de GGA, et le changement de hauteur propre au scénario. bench-export et compliance-report figurent dans le texte d'usage.
  • fusion::pack::truth_trajectory expose l'historique d'état vrai du profil de conduite gnss-ins (le même pas que celui qu'utilise la vérité propre au type de scénario), et UtcEpoch gagne des champs de date et d'heure NMEA.

Validation de la carte des interférences#

  • La sémantique de décodage et la géométrie de la carte des interférences sont vérifiées face à des implémentations indépendantes sur des entrées synthétiques. Les significations des codes NIC et NACp face au décodage pyModeS de trames ADS-B synthétiques, les valeurs « non disponible » de l'AIS face au décodage pyais de phrases AIVDM synthétiques, l'affectation des cellules de grille face à shapely, la longueur de route par état de cellule face à shapely et GeographicLib, et le masquage des terres face à shapely et pyproj, chacun avec une tolérance fixée avant la première comparaison (tests/fixtures/interference_map_ref/PREREGISTRATION.md). Cela valide la façon dont les codes et les valeurs de champs sont lus et la géométrie, et non qu'une cellule signalée soit une interférence. Le lecteur de polygones de terres referme désormais un anneau qui ne répète pas son premier sommet, qu'il lisait auparavant sans sa dernière arête. La documentation indique les seuils de faible précision NACp et NIC comme la borne que représente chaque code (NACp 6 est une borne d'EPU de 556 m, NIC 5 une borne de confinement de 1 NM).

Ajouté (validation des formats de télémétrie et des paquets de preuves)#

  • Vérifications externes de la cryptographie des paquets de preuves, du vérificateur de paquets et des formats de transmission de la télémétrie. Les vecteurs de test Ed25519 de la RFC 8032 section 7,1 (1, 2, 3 et 1024) et les exemples SHA-256 de FIPS 180-4 passent dans les propres fonctions de signature, de vérification et de hachage du paquet, jusqu'à l'égalité exacte. Un vérificateur écrit en Python à partir de la seule section normative de docs/EVIDENCE-PACKS.md (hashlib et cryptography) concorde avec le vérificateur Rust sur 71 paquets intacts et altérés : verdict, ensemble des échecs, verdict de signature et les deux têtes de chaîne. Notre exposition Prometheus est lue par l'analyseur du client Python officiel et notre JSON OTLP par le message opentelemetry-proto officiel, strictement, et les deux concordent avec l'état dont ils sont issus. CEF et LEEF n'ont pas de validateur ouvert indépendant et restent modélisés. docs/EVIDENCE-PACKS.md a gagné le format normatif de paquet et la procédure de vérification à partir desquels le vérificateur en salle blanche a été écrit ; VerifyReport a gagné signature_valid. Références indépendantes et jeux de test : scripts/gen_ed25519_rfc8032_ref.py, scripts/gen_evidence_pack_ref.py avec scripts/evidence_verify_cleanroom.py, scripts/gen_telemetry_formats_ref.py ; tests evidence_crypto_reference, evidence_pack_reference et telemetry_formats_reference. La CI n'a pas besoin de Python.

Ajouté (validation des événements CEF)#

  • Les événements CEF de télémétrie sont relus correctement par deux analyseurs open source indépendants. pycef 1,11 et le codec CEF de Logstash (logstash-codec-cef 6.2.7 dans Logstash 8.15.3) analysent 157 lignes CEF (chaque changement de bande et chaque époque du flux de télémétrie versionné, plus du texte adverse contenant =, des barres obliques inverses, des barres verticales, des sauts de ligne, des tabulations et du texte multi-octets) et retrouvent chaque champ d'en-tête, la gravité, l'ensemble exact des clés d'extension et chaque valeur exactement. Le codec Logstash lit aussi quatre lignes dont le texte d'en-tête nécessite un échappement, ce que pycef ne sait pas faire. Le seuil a été enregistré avant l'exécution de l'un ou l'autre analyseur (tests/cef_reference.rs) ; jeux de test dans tests/fixtures/cef/, scripts de référence indépendante scripts/gen_cef_ref.py et scripts/gen_cef_logstash_ref.py ; la CI n'a besoin ni de Python ni de Logstash. LEEF n'a pas d'analyseur ouvert maintenu et reste modélisé. Les événements CEF portent désormais le score de confiance et le décalage d'époque dans les champs personnalisés à virgule flottante du dictionnaire CEF (cfp1, cfp2) au lieu des champs entiers cn1 et cn2, qui ne convenaient à aucune des deux valeurs ; CEF est nouveau dans cette version, donc rien de ce qui a été livré ne change.

Modifié#

  • MCP : assess_receiver_log accepte le journal sous forme de text ou de base64 ; l'entrée de l'outil est plafonnée à 4 MiB.
  • Le graphique de brouillage tire lui aussi ses couleurs de la palette. src/jamming.rs était le seul module que la révision de la palette de l'Observatory avait laissé avec ses propres couleurs pendant l'arrivée des travaux sur le Q des brouilleurs ; son *.chart.svg (les scénarios jamming, maritime-strait-jamming et autres du type de scénario jamming) lit désormais src/palette.rs, et la liste d'autorisation dans tests/palette_sync.rs est vide. Couleurs et police seulement : les graphiques jamming-demo et maritime-strait-jamming sont égaux à leurs rendus précédemment enregistrés une fois la couleur, font-family et le pied de page de version normalisés. Aucune valeur tracée n'a bougé. Les copies Studio enregistrées sous web/studio/recorded/ ont été réenregistrées lors des re-portages 0.33.0 et 0.34.0 (marque de version seulement) : elles portent encore l'ancienne peinture du graphique de brouillage, et prendront la peinture de la palette au prochain re-portage.

Corrigé#

  • La borne à 3 sigma de l'ensemble d'horloges couvre désormais le plancher de scintillation, et le contrôle de santé du filtre le voit. Avec un flicker_floor, l'horloge vraie portait du bruit de scintillation de fréquence (flicker FM), mais le filtre à deux états qui fournit la borne d'intégrité n'en portait pas, de sorte que la couverture à 3 sigma du scénario clock-ensemble livré était de 0,41 (classique) et 0,33 (quantique), et le contrôle NIS/NEES, qui tirait sa propre vérité à partir du modèle du filtre, indiquait des valeurs identiques avec et sans le plancher. La borne est maintenant la variance à deux états plus la variance exacte de la phase de scintillation accumulée depuis la dernière synchronisation, calculée à partir du même banc que celui qu'utilise l'horloge vraie ; le contrôle NIS/NEES tire sa vérité du modèle étendu avec ce banc et exécute le filtre étendu correspondant (et le filtre à deux états face à une vérité de scintillation indique consistent = false). Changement de sortie, seulement pour les horloges dont flicker_floor est non nul : integrity sur clock-ensemble passe de 0,40866 / 0,33026 à 0,99970 / 1,0 (classique / quantique) et les NIS/NEES de filter_health incluent désormais le scintillement ; l'erreur de synchronisation, holdover_s et timing_p95_ns sont inchangés, et les scénarios sans plancher sont identiques à l'octet près. scenarios/orbit-gnss-challenged.toml (type de scénario orbit, graine 7, planchers 1e-16 / 2e-11) bouge aussi : fom.integrity classique 0,7734 à 1,0 et quantique 0,9796 à 1,0, et les NIS/NEES de filter_health et leurs bandes changent. Son filter_health.consistent quantique passe de true à false : un événement d'échantillonnage de l'ensemble de scintillation de 16 graines par 60 pas (NIS 0,8815 face à une bande de [0,9125, 1,0914]), et non un défaut. La bande est une bande à 95 %, donc environ 5 % des graines signalent un filtre adapté par construction (40 graines nouvelles de ce scénario : quantique 1 et classique 2 signalés) ; à 64 par 200, la même graine est dans la bande pour les deux horloges (NIS 0,990 et 1,001). Suite connue : le type de scénario fusion présente la même lacune (intégrité classique 0,80 avec un plancher) ; le type de scénario hybrid reste au-dessus de 0,99.

[0.34.1] - 2026-10-10#

Sécurité#

  • Durcissement de l'entrée du serveur MCP. Les outils de scénario du serveur MCP n'acceptent désormais que du contenu en ligne et refusent les champs de source de fichier ; la taille de l'entrée est plafonnée. Avis : GHSA-8wpf-hqg5-6xjr.

[0.34.0] - 2026-10-09#

Rejeu en laboratoire : un moteur de suivi, des moniteurs de détection et un exécuteur de campagnes pour les enregistrements IQ GNSS, avec les conceptions de boucle, les estimateurs de C/N0 et les scores qui les accompagnent. Classe de preuve : tout ce qui suit est MODELLED ou vérifié pour sa cohérence interne face à des formes analytiques et à une simulation à graine fixe ; rien de cela n'ajoute de ligne VALIDATED, et le registre de vérification est inchangé (251 lignes : 124 validées, 123 modélisées, 4 partenaire). C'est une couche logicielle d'analyse : rien ici ne synthétise une forme d'onde de brouilleur ou de leurreur, et rien n'émet.

Ajouté#

  • Rejeu en laboratoire : conditions d'essai, exécuteur de campagnes et évaluation (0.34.0). kshana iq campaign <campaign.toml> rejoue des enregistrements × des chaînes de front-end × des conceptions de boucle (kshana.loop-design/1) et évalue chaque cellule par rapport à un fichier de conditions d'essai propre à chaque enregistrement (kshana.test-conditions/1, TOML ou JSON). Ce fichier indique ce qu'un laboratoire sait de l'enregistrement : les satellites attendus et, pour chaque événement, son étiquette de type, son début et sa fin, les satellites touchés et le profil de J/S ou de puissance de brouilleur indiqué. Ce ne sont que des métadonnées. Les scores par satellite, pour toute l'exécution et par événement, sont :

    • disponibilité, temps jusqu'à la perte d'accrochage et J/S indiqué à la perte ;
    • temps de réacquisition, depuis la fin de l'événement et depuis la perte ;
    • dégradation mesurée du C/N0 par classe de J/S indiqué ;
    • épisodes de faux accrochage par heure d'accrochage (l'indicateur du suiveur, ou le Doppler face à un fichier associé de vérité) ;
    • gigue des discriminateurs PLL et DLL.

    À côté de chaque courbe de dégradation mesurée, une référence analytique de séparation spectrale (jamming::effective_cn0_dbhz avec le Q du type) est tracée et étiquetée MODELLED partout où elle apparaît.

    Les cellules s'exécutent en parallèle dans la machine à états de verrouillage de la session de suivi, et chacune est écrite de façon atomique sous une clé de hachage du contenu. La clé couvre le SHA-256 de l'enregistrement, les empreintes de la condition, du front-end, de la conception, de l'exécution et de l'évaluation, le data_class requis (synthetic | client-confidential) et la version du moteur. Avec run.epochs défini, le flux kshana.track-epoch/1 et les événements d'accrochage de chaque cellule sont aussi conservés, nommés par clé de cellule et intégrés par hachage à la cellule. cell_key et report::digest sont publics, de sorte qu'un consommateur peut redériver chaque clé et le condensé. Une réexécution saute donc les cellules terminées, et les sorties ne dépendent jamais du nombre de processus de travail. L'exécution écrit scorecard.csv/.json, un report.html autonome et un DIGEST. Les seuils de réussite/échec ([scoring.bars], modifiables par enregistrement) sont appliqués à la construction du rapport.

    • [scoring] cn0_estimator = "m2m4" | "nwpr" (par défaut "m2m4", intégré à l'empreinte d'évaluation) choisit le C/N0 qui sous-tend le C/N0 indiqué et la courbe de dégradation. Les deux estimations sont toujours évaluées et indiquées (médianes sur l'ensemble de l'exécution et de la référence de base, et par classe de J/S), et la cellule et la fiche d'évaluation consignent l'estimateur. NWPR lit trop bas d'environ 8 dB × Bn·T sous la gigue propre de la boucle ; M2M4 non.

    Également nouveau :

    • kshana iq campaign report <dir> reconstruit les fiches d'évaluation, le rapport et le condensé à partir des cellules ;
    • kshana iq conditions <file> vérifie un fichier de conditions d'essai par rapport à son schéma ;
    • events_from_sigmf = true importe comme événements les annotations kshana:test_event d'un enregistrement SigMF ;
    • Python gagne iq_test_conditions, iq_campaign et iq_campaign_report ;
    • kshana-mcp gagne iq_campaign, qui est incrémental et reprenable sous le budget d'échantillons par appel, avec chaque fichier confiné au répertoire de travail, et iq_campaign_status.

    Tests : tests/iq_campaign.rs exécute une campagne synthétique de 3 enregistrements × 2 front-ends × 2 conceptions. Ses scènes portent des profils de C/N0 indiqués, et il couvre :

    • chaque métrique vérifiée face à la vérité injectée ;
    • la reprise après une exécution partielle à un seul processus avec une cellule corrompue, identique à l'octet près à une exécution ininterrompue à quatre processus ;
    • les fichiers d'époques par cellule ;
    • une régression de réacquisition de trois satellites sur 20 s : avec reacquire activé, chaque canal est de retour dans les 2 s suivant une interruption de 2 s ; le résultat avec reacquire désactivé est figé ;
    • les seuils rejugés sans nouvelle exécution ;
    • la CLI ;
    • des contrôles de débit et de mémoire en mode release, ignorés par défaut, y compris un enregistrement de 4 Go (5,45× le temps réel, mémoire de pointe de 2 Mo au-dessus du RSS de départ ; mesures sur une seule machine, pas des seuils).

    Logiciel seulement : rien n'émet, et aucune forme d'onde d'interférence ou de leurrage n'est synthétisée. Notes de conception et de réalisation : docs/design/LAB-CAMPAIGN.md.

  • Moteur de suivi pour le rejeu en laboratoire (0.34.0 : B3.1, B3.2, B3.3, B6.1).

    • Fichiers de conception de boucle : TOML kshana.loop-design/1 (docs/design/LOOP-DESIGN-TOML.md ; analyseur iq::track::design). Une ou plusieurs conceptions nommées fixent chaque champ de la boucle :

      • type de porteuse (PLL, FLL ou PLL assistée par FLL), ordres et largeurs de bande ;
      • discriminateurs PLL/FLL/DLL et aide de porteuse ;
      • espacement et intégration ;
      • seuils de verrouillage et fenêtres de C/N0, et synchronisation de bit ;
      • la machine à états de verrouillage ;
      • l'acquisition de passage de relais ("auto" ou explicite).

      Les conceptions peuvent s'extends les unes les autres. Les clés inconnues sont refusées. Chaque conception résolue a une empreinte SHA-256 sur une forme JSON canonique (clés triées à chaque niveau, formatage numérique fixe), de sorte que l'empreinte ne dépend pas de l'ordre des champs ; chaque sortie la consigne. Surfaces :

      • kshana iq track --design <file> [--design-name], où les indicateurs explicites l'emportent sur la conception et sont consignés ;
      • kshana iq sweep --design <file>, qui exécute chaque conception du fichier ;
      • Python iq_track(design=, design_name=, reacquire=), iq_loop_designs ;
      • MCP iq_track design/design_name.
    • C/N0 M2M4 (EpochOutput.cn0_m2m4_dbhz, la colonne cn0_m2m4_dbhz de track-epoch après cn0_beaulieu_dbhz ; dictionnaires d'époque Python). L'estimation par moments d'ordre deux et quatre sur les mêmes fenêtres que NWPR, à partir de la seule puissance du canal prompt : NWPR lit trop bas sous la gigue de porteuse propre à la boucle (environ 8 dB × Bn_PLL·T) et M2M4 non. Sur GPS L2C CM (20 ms, 40 dB-Hz nominal, PLL 1 à 10 Hz), il lit 39,93 dB-Hz à chaque largeur de bande alors que NWPR passe de 39,55 à 38,22 ; sur L1 C/A à 45 dB-Hz, il lit 45,34. NWPR et toutes les autres sorties sont inchangés (un contrôle bit à bit). L'enregistrement binaire reste de 184 octets (la valeur prend le flottant réservé et le bit d'indicateur 6).

    • Prises de corrélateur supplémentaires (multi-corrélateur / SQM). [design.integration] extra_taps_chips = [..] (décalages en chips par rapport au prompt, positifs en avance ; au plus 16, chacun dans ±2) corrèle des répliques supplémentaires en plus de E/P/L et les renvoie sous la forme EpochOutput.extra ((offset, value) dans l'ordre de la conception). Les boucles ne les utilisent jamais. La clé est omise du JSON canonique lorsqu'elle est vide, de sorte que l'empreinte de la conception par défaut et chaque sortie sans prises sont inchangées (kshana.track-epoch/1 reste ; les CSV/JSONL/binaire sans prises sont identiques bit à bit). Avec des prises : colonnes CSV/JSONL, et un enregistrement binaire de 184 + 16 × taps octets dont l'en-tête porte extra_taps_chips, de sorte qu'un ancien lecteur refuse le fichier plutôt que de le mal interpréter. --extra-taps (CLI), extra_taps (Python) et extra_taps_chips (MCP iq_track). Les conceptions d'une même exécution doivent s'accorder sur les prises.

    • Canaux parallèles (iq track / iq sweep --threads <N|auto> ; TrackSession::with_threads en Rust). Les canaux de chaque tronçon s'exécutent sur jusqu'à N fils (std::thread::scope ; wasm32 reste en série). La corrélation et la machine à états de verrouillage d'un canal ne touchent que ce canal ; ses époques et événements sont mis en tampon et écrits vers les puits dans l'ordre des canaux, de sorte que la sortie (CSV, JSONL, binaire, événements, résumé) est identique à l'octet près à l'exécution en série pour tout N. Le défaut reste 1 fil. Mesuré sur un enregistrement de 12 canaux, 4 s, 4,092 MHz sur 4 cœurs : 19,5 s en série, 11,5 s avec 2 fils, 6,3 s avec 4 (3,1× ; l'acquisition initiale est en série).

    • Export de la surface d'acquisition (kshana.acq-surface/1 ; iq::acq_surface, docs/design/ACQ-SURFACE.md). iq acquire --surface <path> (un PRN ; CSV, JSON ou binaire), iq_acq_surface en Python et iq_acquire surface_out en MCP écrivent toute la surface de puissance de corrélation Doppler × phase de code que calcule la recherche (ses cellules sont celles de acquire, bit pour bit) avec le pic et deux affinages fin du Doppler : une estimation parabolique et une recherche fine au 1/16 de case (≈5 Hz à 4 ms de cohérence, contre des cases de 167 Hz). acquire lui-même et chaque valeur par défaut sont inchangés.

    • Sortie des époques en continu (kshana.track-epoch/1 ; iq::track::sink). Chaque mise à jour de boucle contient :

      • les corrélateurs précoce, ponctuel et tardif ;
      • les trois sorties de discriminateur ;
      • les états des NCO PLL/FLL/DLL et la phase de la porteuse ;
      • le PLI et les indicateurs de verrouillage ;
      • les deux estimations de C/N0 et les bits ;
      • l'état de verrouillage.

      Elle est écrite au fil de l'exécution, en CSV, en JSON Lines ou sous une forme binaire versionnée, avec des lecteurs en Rust (BinaryEpochReader) et en Python (iq_read_epochs).

      • iq track gagne --epochs, --events et --summary (kshana.track-summary/1), et iq sweep gagne --epochs et --events. L'outil MCP iq_track gagne epochs_out/events_out et construit sa réponse à partir du résumé à mémoire bornée.
      • Le tas d'une exécution ne croît plus avec la longueur de l'enregistrement : tests/iq_track_memory.rs le mesure avec un allocateur à comptage (6× la longueur, même pic à 64 Kio près), avec un témoin montrant que le chemin en mémoire, lui, croît.
      • La sortie en flux est identique bit à bit au rejeu en mémoire.
    • Machine à états de verrouillage (iq::track::lock, TrackSession) : acquisition progressive (pull-in) → verrouillé → perdu → réacquisition → acquisition progressive, ou retiré dès qu'une perte dépasse reacq_window_s (par défaut 30 s). Les recherches échouées sont retentées toutes les reacq_interval_s (0,1 s), à intervalles réguliers, de sorte que le calendrier de nouvelles tentatives ajoute au plus 0,1 s à un temps de réacquisition mesuré. Un recul facultatif (reacq_max_interval_s au-dessus de reacq_interval_s) est désactivé par défaut, et max_reacq_attempts est un plafond facultatif (0, aucun, par défaut). Une coupure de 2 s sur trois PRN à 4,092 MS/s se termine désormais avec chaque canal réacquis et verrouillé. Avec un budget de 3 tentatives, chaque canal était retiré dans les 0,2 s suivant la perte.

      • Les seuils (loss_dwell_s, pull_in_max_s, la fenêtre Doppler de réacquisition) proviennent de la conception. Chaque transition est un événement avec sa raison.
      • Le contrôle de faux accrochage recherche le Doppler suivi par rapport à son alias FLL/PLL de ±1/(2T). Il détecte le faux accrochage mesuré par la PR #38 (−2400 Hz suivis à 500 Hz d'écart). Avec la réacquisition activée, le canal finit verrouillé sur le Doppler injecté.
      • Une interruption de signal de 0,8 s est déclarée perte et réacquise dans les 0,3 s suivant le retour du signal.
      • --summary final_state (et la colonne du tableau) est l'état après la dernière transition, de sorte qu'un canal retiré après sa dernière mise à jour de boucle indique RETIRED.
      • Assistance FLL seulement pendant l'acquisition progressive ([design.carrier] fll_assist = "pull-in", la valeur par défaut ; "always" conserve le comportement antérieur bit pour bit). La FLL passe la main à la PLL dès que le PLI lissé est resté au moins égal à fll_off_pli (0,8) pendant fll_gate_dwell_s (0,1 s), et revient en dessous de fll_on_pli (0,6). Laissé actif, le chemin FLL de 10 Hz rompait le verrouillage de phase en dessous d'environ 38 dB-Hz sur des signaux propres : à 35 dB-Hz, la fraction en verrouillage de phase était de 10–16 %, avec une erreur de phase vraie de 38–41°. Avec la barrière, la valeur par défaut tient 100 % à 35 dB-Hz avec 4,5°, comme une PLL seule. L'acquisition progressive à partir d'une erreur de passage de relais de 100 Hz est inchangée. Preuves avec seuils préenregistrés : docs/design/evidence/carrier-lock/. Les boucles par défaut ne sont donc pas identiques bit à bit aux exécutions antérieures de la conception par défaut. Utilisez fll_assist = "always" pour les reproduire. Limite connue : à 35 dB-Hz, le passage de relais intervient 1,9–2,6 s après le début du suivi, et à 33 dB-Hz la FLL de 10 Hz maintient le PLI sous le seuil de passage de relais, de sorte que l'acquisition progressive ne s'achève jamais.
      • Nouvelles clés de conception de boucle et API, listées :
        • [design.carrier]: fll_assist, fll_off_pli, fll_on_pli, fll_gate_dwell_s;
        • [design.lock] : reacq_window_s, reacq_interval_s, reacq_max_interval_s, avec max_reacq_attempts passé d'une valeur par défaut de 3 à un plafond facultatif (par défaut 0) ;
        • Rust : LoopConfig.fll_assist (FllAssist, FllGate), LoopCore::set_fll_enabled, EpochOutput.fll_active, ChannelSummary.final_state.
      • L'empreinte de conception porte sur une forme JSON canonique, et l'empreinte de la conception intégrée par défaut est 33261cd171a53803a6c262686e878e01f37d902a93d5918c20a44297b8ef8e80 (figée par un test).
      • Notes de compatibilité des sorties :
        • le tableau de iq track a une colonne finale final_state ;
        • le CSV de iq sweep a une colonne finale design_hash, et son JSON a design_hash et warnings ;
        • le mean_cn0_dbhz du balayage est désormais la moyenne sur chaque mise à jour disposant d'une estimation NWPR (résumé à mémoire bornée), et non plus sur la seconde moitié de l'exécution.
      • La réacquisition est désactivée dans la conception intégrée par défaut, où la machine à états ne fait qu'observer et où les boucles tournent bit pour bit comme sans elle. (Les boucles par défaut elles-mêmes ont toutefois changé : voir l'assistance FLL ci-dessus.) Activez-la par conception ([design.lock] reacquire = true), avec --reacquire, ou avec reacquire=True.
      • Un avertissement commensurate_sampling : lorsque fs est à 1e-6 près d'un multiple de la moitié du débit de chips (iq::track::commensurate_samples_per_chip), iq track/iq sweep (sortie, --summary, JSON de balayage), la réponse MCP iq_track et le résultat Python iq_track avertissent que la gigue et le biais de la boucle de code ne sont pas représentatifs. La cause racine est documentée avec des seuils préenregistrés dans docs/design/evidence/dll-jitter/. À exactement 2 échantillons par chip avec un espacement de 0.5 chip, la courbe en S du DLL est une simple marche et la boucle oscille : ≈ 0,09 chip d'erreur de code efficace (≈ 26 m) à 45 dB-Hz, contre ≈ 0,004 chip à un débit incommensurable. Le C/N0 NWPR trop bas d'environ 2 dB à ce débit a la même cause. À exactement 0 Hz de Doppler de code et 4 échantillons par chip, le code ne franchit jamais la zone morte de ±0.21 chip, de sorte qu'un biais de phase de code allant jusqu'à environ 0,2 chip peut persister sans apparaître dans la gigue (mesuré : un espacement de 0.5 chip donne 2,0× l'erreur de code du témoin avec une moyenne de +0,011 chip ; un espacement de 0.25 chip donne +0,125 chip) ; l'avertissement couvre ce débit.
      • Limite connue : la conception par défaut ne passe pas la main de la FLL à la PLL en dessous d'environ 35 dB-Hz (un plancher d'acquisition progressive d'environ 35 dB-Hz ; voir l'assistance FLL ci-dessus et docs/design/evidence/carrier-lock/).
      • Une recherche de faux accrochage ou de réacquisition qui ne peut pas s'exécuter (un débit sans nombre entier d'échantillons par période de code) n'arrête plus le suivi.
      • Tests : tests/iq_track_engine.rs, tests/iq_cli.rs, iq::track::design::tests, tests/python, et l'aller-retour MCP IQ.
  • Profils de C/N0 dans les scènes synthétiques (0.34.0). iq::channel::cn0_profile planifie un C/N0 variable dans le temps pour chaque satellite dans les propres scènes de Kshana, sous forme de décalages en dB par rapport au C/N0 de la scène. Formes : échelon, rampe, linéaire par morceaux, et évanouissements de Rice de type scintillation à graine fixe avec un S4 et un temps de décorrélation indiqués. Ils sont appliqués par le point d'accroche de canal de scène existant (Cn0ProfileChannel, en composition avec les effets d'ionosphère, de troposphère, de scintillation et de trajets multiples), sans modification du cœur de la scène. Le cn0_dbhz du fichier associé de vérité suit le profil.

    • Surfaces : kshana iq scene … --cn0-profile <toml> et kshana.iq_scene(…, cn0_profile="<toml>").
    • À quoi cela sert : les boucles, les moniteurs et l'évaluation de campagnes peuvent être éprouvés face à une vérité connue. Cela ne modifie que la force des signaux légitimes.
    • Contrôles (tests/iq_cn0_profile.rs). Seuils : intensité moyenne des évanouissements à 5 % de 1, S4 à 8 % de la cible (à S4 = 0,3, 0,7 et 1), corrélation d'intensité supérieure à 0,9 à 0,05 τ et inférieure à 0,05 à 5 τ ; vérité exactement égale au C/N0 indiqué plus le profil ; une baisse du C/N0 NWPR suivi à 0,7 dB près d'un échelon de 6 dB. Mesuré : S4 à 1,3 % de la cible, et une baisse suivie de 6,26 dB.
  • Moniteurs de détection sur le chemin IQ (« Rejeu en laboratoire » 0.34.0). Nouveau module iq::monitor, commande kshana iq monitor et liaison kshana.iq_monitor(path, ...). Ils observent un enregistrement et rapportent des séries temporelles ainsi que des événements signalés (instants de début, d'alarme et de fin, pic, seuil). Ils détectent et mesurent seulement ; rien ici ne génère de signal.

    • Puissance totale / AGC : puissance par bloc et gain qu'appliquerait une AGC idéale ; signale les hausses et les baisses.
    • Spectre avant corrélation : DSP de Welch par bloc face à une référence de base apprise. Le seuil d'excès provient d'une cible de fausse alarme. Aussi le kurtosis complexe et un détecteur d'impulsions. Le détecteur d'impulsions compte les échantillons au-dessus d'un seuil dans chaque bloc et lève un événement lorsque la queue supérieure binomiale exacte de ce décompte est inférieure à pulse_pfa (par défaut 1e-4 par bloc), et non lorsqu'un score z dépasse une limite : aux faibles décomptes attendus des blocs courts, un seul échantillon représente déjà plusieurs sigmas.
    • C/N0 par canal : deux détecteurs de changement CUSUM unilatéraux (baisse et hausse), alimentés par des estimations indépendantes (le pas est fixé à partir de la fenêtre de C/N0 de la boucle).
    • SQM à partir des corrélateurs : delta (I_E − I_L)/I_P et rapport (I_E + I_L)/(2 I_P), plus des tests d'asymétrie à partir de corrélateurs supplémentaires lorsqu'un canal les fournit.
    • Séries d'indicateurs de verrouillage : PLI et un indicateur de verrouillage de fréquence à partir de prompts successifs, comme signaux bruts. Les décisions de verrouillage et de perte d'accrochage restent à la machine à états de verrouillage du moteur de suivi.

    Un seul passage en flux (iq::monitor::run::run_monitors) exécute tout, avec un fichier de paramètres TOML/JSON (MonitorConfig) ; l'exécuteur de campagnes utilise le même point d'entrée. Tout est MODELLED. Chaque statistique est vérifiée face à sa forme analytique par simulation à graine fixe (tests/iq_monitor.rs) :

    • dépassements de puissance par bloc face à la queue de la loi Gamma ;
    • moyenne du kurtosis 2 et dispersion 2/√N ;
    • fraction d'impulsions e^{−t} ;
    • longueurs de séquence du CUSUM face à l'approximation de Siegmund (mesuré 330 et 8,46 échantillons contre 338 et 8,34) ;
    • l'indicateur de verrouillage de phase face à la moyenne de la phase de Rice ;
    • sur un signal C/A suivi, les dispersions du delta et du rapport SQM sont d'environ 6 % par rapport aux formes analytiques du premier ordre (mesuré 5,97 % ; seuil de test 12 %).

    La formule de fausse alarme de l'excès spectral est une approximation ; le taux mesuré valait 1,3× la formule. De bout en bout, les moniteurs signalent :

    • un échelon de C/N0 de 6 dB (instant du changement à une estimation près) ;
    • un trajet réfléchi apparaissant au milieu de l'enregistrement (test de rapport) ;
    • une coupure de signal (le PLI passe de 0,999 à −0,3 et le FLI de 0,93 à 0,03 pendant celle-ci) ;
    • une tonalité à bande étroite et des échantillons épars de forte amplitude (tests spectral, d'impulsions et de kurtosis). Ce sont des entrées de test DSP génériques, et non des modèles d'interférence.

Modifié#

  • iq track/iq sweep passent en flux par la nouvelle session (voir Ajouté).
    • --csv garde ses colonnes de 0,32 mais est désormais diffusé en flux, de sorte que les lignes de plusieurs canaux s'entrelacent dans l'ordre du temps au lieu d'être regroupées par canal. --json garde sa forme de 0,32 et conserve toujours chaque époque en mémoire : utilisez --epochs pour les longs enregistrements.
    • iq sweep mesure la gigue sur les mises à jour de la seconde moitié de la durée de l'exécution (auparavant la seconde moitié du nombre de mises à jour), et son CSV/JSON gagne une colonne design_hash.
    • Le tableau de suivi gagne une colonne final_state.
    • Le texte d'usage ne prétend plus que iq track accepte les indicateurs de front-end ; seul iq acquire les applique.
    • En Python, acq_noncoherent et doppler_max de iq_track valent désormais par défaut None (les valeurs de la conception, 1 et 5000 Hz dans la conception intégrée). Ses époques gagnent les corrélateurs en avance/en retard, carrier_phase_cycles, bit_edge, bit et state, et le résultat gagne design et events.

Corrigé#

  • Le pas d'acquisition par défaut ne laisse plus au suivi de Galileo E1 un résidu que la FLL ne peut pas rattraper. Le pas 2 / (3 · N · T_code) laisse jusqu'à 1 / (3 · N · T_code) d'erreur Doppler au passage de relais, mais la FLL à deux quadrants par défaut ne rattrape que 1 / (4 T_track). Pour chaque code de 4 ms ou plus (N = 1), y compris Galileo E1-B et E1-C, le résidu (83,3 Hz à 4 ms) était en dehors de la plage de rattrapage de 62,5 Hz et le suivi faisait un faux accrochage à +125 Hz, avec un indicateur de verrouillage de phase de 0,97 qui le masquait. Le pas par défaut est désormais aussi plafonné à 0.2 / T_track (kshana::iq::acq::default_step_hz), soit 0,8 de la plage de rattrapage, de sorte que le passage de relais reste dans celle-ci même lorsque la case voisine l'emporte. (0,4 avait été essayé en premier : il faisait un faux accrochage 1 fois sur 42 sur E1-B, et une recherche GPS L1 C/A cohérente sur 1 ms choisissait une case à 350 Hz d'écart et s'accrochait à +500 Hz ; 0,25 et 0,2 n'en avaient aucun dans les mêmes exécutions.) Coût : Galileo E1-B/E1-C passent de cases de 166,7 Hz à 50 Hz, 201 cases sur ±5 kHz au lieu de 61 ; les codes de 1 ms (166,7 Hz, N = 4) sont inchangés. "auto" dans une conception de boucle signifie cela ; un doppler_step_hz ou --doppler-step explicite est utilisé tel quel, et iq acquire (sans passage de relais au suivi) garde le pas des manuels. L'en-tête d'époque et --summary consignent désormais le pas résolu et les largeurs de bande de boucle de chaque canal (resolved). L'empreinte de la conception par défaut est inchangée. Changement de sortie : les détections sur les codes de 4 ms et plus peuvent tomber sur d'autres cases Doppler.

  • GPS L2C CM (mise à jour de boucle de 20 ms) garde le verrouillage avec la conception par défaut. La PLL de 15 Hz et la FLL de 10 Hz par défaut ont un Bn · T de 0,3 et 0,2 à T = 20 ms, et la boucle perdait l'accrochage même à partir d'un départ parfait (PLI −0,08, M2M4 15,8 dB-Hz). La nouvelle clé de conception carrier.bn_t_max (par défaut 0,1) borne les largeurs de bande de bruit de la PLL et de la FLL à bn_t_max / T lorsque le temps de mise à jour de la boucle dépasse 4 ms (Design::loop_config_for) : 5 Hz et 5 Hz à 20 ms, 10 Hz et 10 Hz à 10 ms pour BeiDou B1C ; les codes de 1 ms et 4 ms gardent 15 et 10 Hz. Elle s'applique aussi aux largeurs de bande explicites ; bn_t_max = 0 la désactive. La clé est omise de la forme canonique à sa valeur par défaut, de sorte que l'empreinte par défaut est inchangée ; une conception qui fixe une autre valeur a une empreinte différente. À 45 dB-Hz, L2C CM donne désormais un PLI de 0,996, une erreur Doppler de 0,00 Hz et un M2M4 de 42,71 dB-Hz. Point ouvert connu : le C/N0 NWPR lit 1,76 dB trop bas dans ce cas (et 2,45 dB trop bas sur B1C à 10 ms), de sorte que le T5 de la matrice pour L2C reste un constat ignoré.

  • docs/assets/clock-ensemble-band.svg régénéré : la figure versionnée était périmée par rapport à son propre scénario (un changement de données, pas un simple repeint). Le graphique avait été tracé le 2026-06-02 à partir de scenarios/clock-ensemble.toml ; deux jours plus tard, 67fed19e a fixé les planchers de bruit de scintillation de fréquence dans ce scénario (quantique flicker_floor = 1e-16, CSAC flicker_floor = 2e-11) et la figure n'a jamais été retracée. Elle montrait l'exécution d'avant les planchers : axe y de 0 à 47 ns, p95 de coupure par exécution du CSAC de 10,5 à 47,6 ns (moyenne 25,2 ns), holdover classique de 4050 s en moyenne. Le scénario tel que livré (et tel que l'indiquent déjà le tutoriel et le résumé de la CLI) donne un axe y de 0 à 407 ns, un p95 par exécution du CSAC de 40,8 à 374,0 ns (moyenne 167,0 ns), un holdover classique de 844 s [220 à 2130 s] ; la ligne de spécification de 20 ns se trouve au même 20 ns sur un axe environ neuf fois plus haut. Le moteur est inchangé : le moteur d'aujourd'hui sur le fichier de scénario de juin reproduit exactement l'axe de l'ancienne figure. La figure n'est référencée ni depuis le README ni depuis la documentation.

Limites connues#

  • Le C/N0 NWPR lit trop bas pour un C/N0·T par prompt élevé, et BOC(1 1) à 5 MS/s perd environ 1 dB. NWPR est non biaisé sur des prompts idéaux, mais la gigue propre à la PLL de la boucle coûte environ 8 dB × Bn·T ajustés (une scène, quatre points : −0.24/−0.44/−0.77/−1,58 dB à 1/2.5/5/10 Hz et 20 ms ; environ −1 dB au bn_t_max = 0.1 par défaut) ; M2M4 y est insensible. Les données BeiDou B1C à 5 MS/s perdent aussi environ 1 dB de puissance du prompt à cause de la limitation de bande (utilisez 10 MS/s ou plus). Aucun des deux n'est un défaut de l'estimateur ; les lignes T5 de la matrice des signaux pour GPS L2C et BeiDou B1C restent des constats ignorés avec ces causes.

[0.33.1] - 2026-10-08#

Sécurité#

  • Texte des graphiques et adoption des graphiques par le Studio durcis. Le texte qu'un scénario transporte dans un graphique généré est désormais échappé de façon cohérente par une routine commune, et le Studio n'adopte que le balisage de dessin d'un graphique. Les paramètres d'adresse du Studio, les recherches indexées par type de scénario et les récupérations de scénarios sont restreints à des valeurs connues. Les graphiques fournis, les résultats enregistrés et les chiffres publiés sont inchangés. La mise à jour est recommandée à quiconque ouvre dans le Studio des fichiers de scénario de sources non fiables ou intègre des graphiques générés dans des pages web. Avis : GHSA-h25h-cg9f-v2cg.

[0.33.0] - 2026-10-08#

Documentation#

  • La portée de la couche IQ en matière d'interférence et de leurrage, énoncée avec exactitude. Les entrées 0.31.0 et 0.32.0 ci-dessous disent que la couche IQ n'ajoute « aucune synthèse de forme d'onde d'interférence ou de leurrage ». C'est vrai de la couche IQ elle-même (iq::scene ne génère que des signaux GNSS légitimes), mais cela se lisait comme un énoncé sur le moteur entier, et ce n'en est pas un : depuis 0.29.0, la section [iq] du type de scénario spectrum écrit un instantané SigMF de son modèle analytique avec les brouilleurs configurés (brouilleurs de type bruit case par case, tonalités et chirps sous forme d'ondes), et spoof_capture additionne en mémoire un signal authentique et une réplique de leurreur pour tester la capture de la boucle (le composite n'est jamais écrit). Le moteur embarque aussi un récepteur GNSS logiciel depuis 0.20.0 (sdr : acquisition et suivi ; depuis 0.31.0 aussi iq::acq et iq::track). Rien dans Kshana n'émet ni ne pilote de matériel radio. La ligne d'état du README, docs/POSITIONING.md, docs/SPECTRUM.md et les notes de conception IQ le disent désormais ; les entrées publiées sont laissées telles qu'elles ont été publiées. Aucun comportement ne change.
  • Limite connue : échantillonnage commensurable. À un débit d'échantillonnage multiple entier ou demi-entier du débit de chips, les échantillons tombent sur les mêmes phases de chip dans chaque chip, et le discriminateur de code devient un escalier. Sur un signal GPS L1 C/A synthétique à 45 dB-Hz avec un espacement de 0.5 chip, 2,046 MHz (2 échantillons/chip) donne ≈ 0,09 chip (≈ 26 m) d'erreur de code efficace et un biais de −0,09 chip, contre ≈ 0,003 chip à un débit incommensurable. Le C/N0 NWPR lit ≈ 2,4 dB trop bas dans ce cas. À 4,092 MHz, cela dépend de l'espacement et du Doppler de code. À 0,5 chip, c'est sans conséquence à 1500 Hz de Doppler mais 2× avec un biais de 0,011 chip à 0 Hz, et à 0,25 ou 0,1 chip, c'est 8–10× l'erreur de code. Le suivi de porteuse n'est pas affecté. docs/design/iq-notes/receiver.md contient les mesures.

Ajouté#

  • Couche IQ GNSS sur le serveur MCP (phase B.1). kshana-mcp gagne six outils qui pilotent la couche kshana iq depuis un agent : iq_signals (les noms de signaux acceptés et la configuration IQ), iq_info (décrire un enregistrement), iq_scene (générer une scène à profil indiqué ou à éphéméride diffusée, avec le canal facultatif au niveau du signal), iq_acquire (acquisition par FFT, éventuellement derrière des étages de front-end), iq_track (acquérir, puis le banc DLL/PLL/FLL) et iq_frontend (passe-bande, filtre coupe-bande, blanking, excision, AGC, quantificateur). Les échantillons IQ ne traversent jamais le protocole : chaque outil prend des chemins de fichiers à l'intérieur d'un répertoire de travail défini par KSHANA_MCP_IQ_DIR (non défini, il laisse les outils de fichiers IQ désactivés sans affecter aucun autre outil), refuse les chemins qui se résolvent en dehors de celui-ci et les sorties qui existent déjà sauf si overwrite est défini, applique un budget d'échantillons par appel (KSHANA_MCP_IQ_MAX_SAMPLES, par défaut 50 000 000) avant tout travail, refuse les arguments inconnus, et répond par un résumé JSON compact (détections, C/N0, état de verrouillage, et chaque fichier écrit avec son nombre d'octets). La sortie par époque va uniquement dans les fichiers que nomme l'appelant. Les outils exécutent le même chemin de code que la CLI par une nouvelle interface publique, kshana::iq::cli::execute, qui renvoie le message de la CLI au lieu de l'afficher (stdout est le canal JSON-RPC de MCP) ; iq::cli::build_code et iq::cli::signal_names sont désormais publics eux aussi. Logiciel seulement et additif : la couche IQ n'ajoute aucune synthèse d'interférence ni de leurreur, rien n'est jamais émis, et il n'y a aucune nouvelle dépendance. server.json déclare les deux variables d'environnement. Des tests d'aller-retour dans mcp/kshana-mcp/tests/iq_round_trip.rs génèrent une courte scène à deux satellites et vérifient l'acquisition face au propre fichier associé de vérité de la scène, le verrouillage du suivi et le C/N0, le front-end, la sortie SigMF, le budget, le confinement des chemins et l'état désactivé.

  • La couche IQ GNSS dans le registre de validation. Une vérification croisée préenregistrée face à gps-sdr-sim (un générateur indépendant de bande de base GPS L1 C/A, MIT, commit 28ca29a6) fait désormais partie de la suite de tests toujours active (tests/iq_gpssdrsim_cross_generator.rs). Sa sortie de référence versionnée (tests/fixtures/iq_gpssdrsim_cross_generator/ : 20 ms de l'I/Q 8 bits propre à gps-sdr-sim, sa liste de canaux, et l'état de canal qui la sous-tend, issu d'un banc de test lié à la même construction) est régénérée par scripts/gen_iq_gpssdrsim_ref.sh. Rien au moment du test n'a besoin du réseau ni de l'outil externe. Deux lignes sont ajoutées au registre (251 lignes : 124 validées, 123 modélisées, 4 partenaire) :

    • Géométrie du signal d'une scène IQ GNSS face à un générateur de bande de base indépendant : validé. La vérité de la scène (ensemble visible, pseudodistance, phase de code, Doppler, angles de visée) pour une scène à éphéméride diffusée correspond à l'état de canal de gps-sdr-sim sur les 11 canaux : pire cas 1,6 mm, 5.5e-6 chip, 7.4e-5 Hz, 4e-9 degré, contre des seuils de 0,05 m, 2e-4 chip, 0,02 Hz et 1e-4 degré fixés avant l'exécution.
    • Acquisition IQ GNSS sur des échantillons I/Q générés de façon indépendante : modélisé, avec un constat. iq::acq trouve chaque satellite simulé dans les échantillons de gps-sdr-sim dans les seuils enregistrés (phase de code à 0,195 chip près, Doppler à 72 Hz près). Le seuil enregistré « aucun autre PRN détecté » échoue toutefois : sur la sortie sans bruit de gps-sdr-sim, le seuil de bruit gaussien est franchi par l'intercorrélation des autres satellites pour les 21 PRN absents. Le test strict est conservé, ignoré avec le constat, et un test figé l'enregistre. Aucun code du moteur ni aucune API publique ne change. Les échantillons I/Q ne sont pas comparés échantillon par échantillon : la table de sinus entière de gps-sdr-sim, les gains, la phase de porteuse initiale nulle et les champs LNAV tronqués ne sont pas des grandeurs sur lesquelles un récepteur doit s'accorder. La comparaison est faite sur les observables que mesure un récepteur.

Modifié#

  • iq track passe la main par défaut à partir d'une acquisition de ≈4 ms (changement de comportement). L'acquisition qui initialise chaque canal de suivi intègre désormais ceil(4 ms / T_code) périodes de code de façon cohérente au lieu d'une seule, où T_code est la période complète du code (longueur primaire fois secondaire pour un code à niveaux, l'unité sur laquelle l'acquisition intègre). Les codes de 1 ms sans niveaux (GPS L1 C/A, BeiDou B1I, GLONASS L1OF) recherchent désormais sur 4 périodes (4 ms), de sorte que le pas Doppler par défaut 2 / (3 · N · T_code) vaut ~167 Hz au lieu de ~667 Hz. Chaque code dont la période complète est déjà de 4 ms ou plus garde 1 période : Galileo E1-B (4 ms), BeiDou B1C (10 ms), et les codes à niveaux GPS L5-I/L5-Q, Galileo E5a-I/E5a-Q et E1-C (10 à 100 ms avec leurs codes de recouvrement), ainsi que GPS L2C. Chaque signal intègre donc au moins ~4 ms. Une recherche sur une seule période pouvait passer la main à un canal avec un écart pouvant atteindre ~333 Hz, en dehors de la plage de rattrapage de la FLL, et celui-ci suivait alors un faux accrochage à ~500 Hz tout en indiquant un suivi propre. Sur un balayage à graine fixe de 180 canaux GPS L1 C/A (Doppler sur ±5 kHz, 38 à 47 dB-Hz, la moitié avec des données de navigation ; docs/design/evidence/iq-track-acq-default/, relançable), les faux accrochages passent de 27 sur 180 à 1 sur 180 et les acquisitions manquées de 102 à 11, pour ~40 ms de recherche supplémentaires par PRN sur GPS L1 (11 → 52 ms). L'unique faux accrochage résiduel se produit à 38 dB-Hz, à 36 Hz d'écart. Toutes les surfaces concordent : kshana iq track et kshana iq sweep (--acq-coherent), Python kshana.iq_track (acq_coherent=None vaut désormais auto ; stub mis à jour) et l'outil MCP iq_track. Les utilisateurs qui s'appuyaient sur l'ancien défaut peuvent passer acq_coherent=1 (--acq-coherent 1). Le défaut propre à --coherent de kshana iq acquire reste 1. Nouveaux iq::acq::auto_coherent_periods et iq::acq::AUTO_COHERENT_S publics ; test de régression tests/iq_cli.rs::track_default_handoff_does_not_false_lock_where_one_period_did.
  • Chaque graphique généré suit désormais le thème Observatory du site : les octets de chaque graphique changent. Il s'agit d'une révision délibérée des figures publiées, des couleurs et des polices seulement ; aucune valeur tracée, aucune coordonnée ni aucune étiquette n'a bougé. Le *.chart.svg de chaque scénario (et donc les exports de graphiques du Studio et les graphiques de démonstration du README), le HTML du rapport d'exécution (*.report.html), l'animation de la chronologie (--animate), les pages HTML de résultat de scénario et d'étude, le résumé de validation et les figures et diagrammes de la documentation utilisaient la palette sombre chaude de juillet (fond #0c0b08, or #e0bd84) et un thème de rapport papier chaud. Ils prennent maintenant chaque couleur et chaque police d'un seul module, src/palette.rs, qui reflète web/theme.css : les graphiques sont dessinés en sombre d'instrument sur le fond Observatory (#060A14) avec la pile typographique Geist ; le rapport, le lecteur d'animation et les pages de résultat suivent la préférence clair/sombre du lecteur avec les jetons clair et sombre d'Observatory. Les six domaines de défaillance gardent chacun une couleur (interférence corail, leurrage magenta, synchronisation temporelle bleu, orbites cyan, intégrité citron vert, navigation ambre), et les niveaux de preuve se lisent validé citron vert, modélisé ambre, partenaire magenta. Les rampes de cascade gardent leur ordre perceptuel (inferno), réancrées sur le nouveau fond.
    • tests/palette_sync.rs aligne le module sur web/theme.css dans les deux thèmes, vérifie que docs/assets/palette.json et docs/diagrams/mermaid-config.json (tous deux générés à partir du module, pour les outils de figures Python et mermaid-cli) sont à jour, et échoue si un littéral de couleur hexadécimal apparaît dans src/ en dehors de la palette.
    • tests/published_figures_still_reproduce.rs gagne un troisième diagnostic, « seuls les couleurs et les polices ont bougé », de sorte qu'une révision de palette se distingue d'une valeur tracée qui a bougé. Chaque graphique du README réexécuté a été vérifié égal à son prédécesseur sous ce normaliseur.
    • tools/gen_validation_figures.py lit la palette et génère désormais aussi les trois figures de résultats du README qui n'avaient aucun générateur versionné (domain-coverage-map, scenario-fom, sgp4-regime-bars), avec de vrais éléments de texte, à partir de web/capabilities.json, du résultat clock-holdover et de tests/fixtures/sgp4_comparison.md. tools/gen_readme_assets.py lit la même palette, ce qui corrige sa dérive du thème clair par rapport au site. Les valeurs de sgp4-regime-bars sont la colonne du pire cas kshana↔ref de ce jeu de test (7.31e-9, 8.05e-9, 8.18e-9 et 4.12e-6 km), inchangées par rapport à la figure Matplotlib, et tests/figures_doc_sync.rs échoue désormais si la figure versionnée et le jeu de test divergent.
  • docs/assets/figures/domain-coverage-map actualisé avec les données courantes (un changement de données, pas un repeint). La figure indiquait 28 capacités sur 8 domaines (11 validées, 17 modélisées), périmée par rapport à sa propre source indiquée ; tracée maintenant par son nouveau générateur à partir de web/capabilities.json, elle indique 46 capacités sur 8 domaines (17 validées, 29 modélisées).

Corrigé#

  • Le Q d'un brouilleur CW/à bande étroite vaut désormais 1,0, et non 1,5. La valeur des manuels pour une tonalité sur la porteuse est 1 (une tonalité conserve le pic spectral du signal, κ = T_c, Q = 1/(R_c κ)) ; l'ancienne valeur de 1,5 rendait une tonalité moins pénalisante qu'un bruit à large bande à J/S égal. Changement de sortie : environ −1,8 dB de C/N0 effectif sous des brouilleurs CW/à bande étroite à fort J/S dans les types de scénario jamming, lunar-jamming et d'interopérabilité (la tonalité de l'exemple spectrum fourni : 17,98 dB-Hz d'après le tableau, contre 19,74 auparavant). Le Q à large bande reste 1,0 (prudent, environ 3 dB sous la valeur des manuels d'environ 2) dans l'attente de la revue de 0,34. Définissez q_override pour conserver l'ancienne valeur de 1,5.

  • La sortie entière de kshana iq scene utilise la plage entière. Avec un bruit de puissance unitaire et une échelle d'écriture de 1, les scènes ci8/ci16 sortaient à environ {-1, 0, 1} et les scènes sur 2 bits avaient leurs seuils à 2,8 sigma. Les formats entiers sont désormais mis à l'échelle de sorte que le RMS attendu par composante soit le quart de la pleine échelle (31,75 LSB en ci8, 8191,75 en ci16) ou 2 LSB sur 2 bits. L'échelle et le nombre d'éléments écrêtés sont affichés et écrits dans le fichier associé. La sortie en virgule flottante est inchangée.

  • Huit contrôles de jeux de test dans sept fichiers de test n'échouent plus sur macOS à cause d'écarts sur le dernier bit (partie du ticket #36). Les contrôles qui vérifient que le moteur reconstruit encore les entrées versionnées d'une référence indépendante (jacobiennes, une table d'états, des azimuts de lancement) comparaient bit à bit et échouaient sur macOS arm64 de 2 à quelques milliers d'unités sur le dernier chiffre. Ils comparent désormais à 1e-12 près d'une échelle tirée du jeu de test ; les entiers, les clés et les longueurs se comparent toujours exactement, et un test de mutation montre qu'un changement relatif de 1e-6 échoue toujours. Le contrôle de l'azimut de lancement compare sin az et la branche ascendante/descendante plutôt que l'azimut lui-même, parce que asin amplifie un ulp de son argument à environ 3e-9 rad lorsqu'une inclinaison est égale à la colatitude d'un site. Aucune tolérance de référence indépendante ni aucun seuil préenregistré n'a changé. Deux tests (détermination d'orbite conjointe lunaire, observabilité lunaire) ne sont pas couverts : sur macOS, leurs comparaisons préenregistrées elles-mêmes bougent, et cela est laissé à une suite.

  • kshana iq track et kshana iq sweep appliquent les indicateurs de front-end. Le texte d'usage annonçait --bandpass/--notch/--blank/--excise/--agc/--bits sur track, mais track et sweep ne construisaient jamais la chaîne : les indicateurs étaient ignorés silencieusement, et un indicateur sans valeur tel que --notch avalait l'indicateur suivant. Les deux commandes les analysent désormais comme le fait iq acquire et placent une nouvelle chaîne de front-end devant la passe d'acquisition et la passe de suivi. La sortie est égale à celle de la commande exécutée sur le fichier qu'écrit iq frontend pour les mêmes indicateurs.

  • Les données d'une scène IQ sont placées par signal. kshana iq scene --data (et NavData::Seeded) plaçaient des bits à 50 bit/s sur chaque signal, pilotes compris, et au débit LNAV du GPS sur Galileo et BeiDou. Les données suivent désormais le propre rythme de symboles de chaque signal, indiqué par le nouveau SpreadingCode::data_modulation() (DataModulation, défini par chaque constructeur dans iq::signals). Cela donne 10 ms sur L5-I5, 4 ms sur E1-B, 2 ms sur BeiDou B1I GEO (D2), et des bits de 20 ms avec un méandre de 10 ms sur GLONASS L1OF. Les données sont refusées sur les pilotes, sur GPS L2C en tant que flux unique CM/CL, et NavData::Lnav sur tout autre que L1 C/A. Les codes personnalisés gardent par défaut le rythme précédent de 20 ms. Un Scene programmatique qui demandait NavData::Lnav sur un code autre que L1 C/A, ou NavData::Seeded sur un pilote, générait auparavant silencieusement et renvoie désormais une erreur à la première lecture.

  • Les canaux GLONASS L1OF sont acquis et suivis sur leur propre porteuse FDMA. iq::acq::acquire et les canaux de suivi ramenaient chaque code en bande de base à partir de if_hz seul. Dans un enregistrement GLONASS multicanal, une recherche du canal +3 trouvait donc le signal du canal 0 (tous les canaux partagent un même code de télémétrie) et ne regardait jamais 1,6875 MHz plus haut. Les deux utilisent désormais SampleSpec::baseband_hz(carrier) = if_hz + (carrier − center_hz). Le terme de porteuse est nul pour tout enregistrement centré sur la porteuse propre du signal et est omis lorsque le centre est inconnu, de sorte que le traitement CDMA est inchangé. Si vous aviez contourné l'ancien comportement en intégrant carrier − center dans le if_hz du fichier associé, retirez ce terme : le décalage est maintenant appliqué à partir de la porteuse et du centre, de sorte que le laisser l'applique deux fois. Limite connue, inchangée ici : une scène GLONASS identifie chaque satellite par son canal de fréquence k, et l'identifiant de satellite u32 fait un repli modulo pour un canal négatif. Le fichier associé de vérité écrit k = -7 sous la forme sat_id 4294967289 (k + 2^32). Relisez-le comme k avec une conversion i32.

[0.32.0] - 2026-10-05#

Ajouté#

  • Couche IQ GNSS sur la CLI et Python (0.32.0 phase A). Le module iq existant est désormais utilisable sans écrire de Rust. Cinq nouvelles commandes kshana iq rejoignent le groupe de traitement de données : scene génère dans un fichier une longue scène IQ multi-satellites avec un fichier associé de vérité ; acquire exécute l'acquisition par FFT d'un ou plusieurs PRN sur un enregistrement et rapporte chaque détection (PRN, Doppler, phase de code, statistique, seuil) ; track acquiert puis exécute le banc DLL/PLL/FLL sur un enregistrement et émet une sortie de suivi par époque (CSV/JSON) avec des largeurs de bande de boucle, un temps d'intégration et un espacement de corrélateurs configurables ; sweep rejoue un enregistrement à travers plusieurs conceptions de boucle et rapporte la gigue et les métriques de verrouillage obtenues pour chaque conception ; et labfit ajuste le modèle de perte d'accrochage de la boucle de suivi sur une chronologie receiver-trust. Le même cœur est exposé à Python (kshana.iq_scene, iq_acquire, iq_track, iq_labfit, iq_signals), en renvoyant des listes et des dictionnaires compatibles NumPy. Logiciel seulement et additif : aucune nouvelle dépendance, aucune émission, aucune synthèse de forme d'onde d'interférence ou de leurrage ; le moteur, l'acquisition, le suivi et les conceptions de boucle sont ceux du crate lui-même, de sorte qu'un appelant CLI ou Python obtient les mêmes bits que les tests Rust. Nouveau module iq::cli ; le fichier associé de vérité de la scène est la référence indépendante dans tests/iq_cli.rs (l'acquisition retrouve chaque phase de code et chaque Doppler injectés, le suivi converge vers le Doppler injecté). Aucun nombre publié de types de scénario ni aucune ligne de la matrice de vérification ne change.
  • Capacités restantes de la bibliothèque IQ GNSS sur la CLI iq et Python (0.32.0 phase A.2). S'appuie sur la phase A en exposant le reste de la couche iq sans écrire de Rust :
    • Canal de propagation sur iq scene (et le iq_scene Python) : une ionosphère du premier ordre (--iono-stec/--iono-vtec ou --iono-klobuchar), la troposphère de Saastamoinen/Niell (--tropo), le modèle de scintillation de Cornell (--s4, --scint-tau0, --sigma-phi), un multitrajet spéculaire sur le sol (--multipath-height/--multipath-ground), le canal mobile terrestre à trois états (--land-mobile) et un bloc hors ligne de vue (--nlos) s'appliquent à chaque satellite par un nouveau pont interne au crate (iq::channel::SceneChannelAdapter) qui convertit les trajets absolus des modèles de canal en la forme excès-sur-géométrie de la scène.
    • Sortie SigMF sur iq scene (--format sigmf) : écrit les échantillons sous la forme d'une paire .sigmf-data/.sigmf-meta avec une capture et des annotations par satellite ; acquire/track lisent déjà SigMF, de sorte qu'une scène fait l'aller-retour.
    • DSP de front-end : une nouvelle commande iq frontend <in> <out> et les mêmes indicateurs sur acquire/track (--bandpass, --notch, --blank, --excise, --agc, --bits 1/2/3/8/14) exécutent les étages de iq::frontend (FIR passe-bande, filtre coupe-bande adaptatif, blanking d'impulsions, excision dans le domaine fréquentiel, AGC, quantificateur) ; reflétés en Python sous le nom iq_frontend.
    • Scènes à éphéméride diffusée : iq scene --nav <rinex_nav> --rx-pos lat,lon,alt (avec --start/--window/--prn) place chaque satellite GPS sain à sa vraie géométrie diffusée en utilisant le lecteur RINEX du moteur, de sorte que le fichier associé de vérité porte la vraie distance, le vrai Doppler et la vraie phase de code de chaque satellite ; reflété en Python sous le nom iq_scene_broadcast. Logiciel seulement et additif : aucune nouvelle dépendance, aucune émission, aucune synthèse de forme d'onde d'interférence ou de leurrage (les effets de propagation du canal n'agissent que sur le signal légitime). Chaque affirmation numérique est testée face à une référence indépendante (forme analytique ou vérité injectée) dans les tests unitaires du canal et du front-end et dans tests/iq_cli.rs.

[0.31.0] - 2026-10-04#

Ajouté#

  • Couche IQ GNSS : simulation au niveau du signal et traitement de récepteur logiciel. Un nouveau module iq fait passer Kshana d'un front-end L1 C/A à satellite unique et à blocs courts à une couche complète au niveau du signal, accessible depuis le groupe de commandes kshana iq. Il génère de longues scènes IQ brutes multi-satellites avec un fichier associé de vérité par époque (iq::scene) ; applique la propagation au niveau du signal — ionosphère avec divergence code-porteuse, troposphère, scintillation d'amplitude et de phase (modèle de Cornell), multitrajet de Fresnel et canal mobile terrestre à trois états, avec hors ligne de vue (iq::channel) ; acquiert et suit avec une acquisition par FFT et un banc DLL/PLL/FLL multicanal, en rejouant un même enregistrement à travers de nombreuses conceptions de boucle (iq::acq, iq::track) ; modélise le front-end — filtrage FIR/IIR, quantification de 1 à 14 bits, AGC, filtre coupe-bande, blanking d'impulsions et excision dans le domaine fréquentiel (iq::frontend) ; traite en flux de grands jeux de données enregistrés à mémoire bornée — formats int8/int16/float32/2 bits compactés et FI réelle, SigMF multi-fichiers, rééchantillonnage, un inventaire de jeux de données avec SHA-256 par fichier et un exécuteur par lots (iq::io) ; ajoute des codes d'étalement pour GPS L5/L2C, Galileo E1 (CBOC, vrais codes mémoire de l'ICD) et E5a, BeiDou B1C/B1I et GLONASS L1OF, chacun vérifié face à son document de contrôle d'interface (iq::signals) ; et ajuste le modèle de perte d'accrochage de la boucle de suivi sur le comportement observé d'un vrai récepteur lors d'essais en laboratoire, avec une erreur de jeu réservé en laissant une exécution de côté à chaque fois et une extrapolation étiquetée comme prédiction (iq::labfit). Chaque affirmation numérique est testée face à une référence indépendante (une table de l'ICD, une forme analytique, ou un récepteur indépendant retrouvant la vérité injectée) ; les modèles physiques de canal et de boucle restent MODELLED. C'est une couche purement logicielle : elle écrit des fichiers IQ pour des récepteurs logiciels et ne synthétise ni forme d'onde d'interférence ou de leurrage ni ne pilote de matériel radio. Aucun nombre publié de types de scénario ni aucune ligne de la matrice de vérification ne change. Conception : docs/design/GNSS-IQ-PLAN.md.
  • Confiance du récepteur : évaluer un vrai journal de récepteur GNSS. kshana receiver-trust <scenario.toml> lit un journal u-blox UBX, RINEX 3 (avec un fichier de navigation diffusé facultatif), Android GnssLogger ou NMEA 0183 dans une seule chronologie horodatée et exécute dessus des moniteurs de confiance : baisse de la densité porteuse sur bruit (C/N0), perte d'accrochage, commande automatique de gain (AGC), indicateur de brouillage u-blox, saut de position et, avec RINEX et navigation, le calcul de position à point unique propre au moteur avec surveillance autonome de l'intégrité par le récepteur (RAIM) en parité et le moniteur assisté par horloge. Chaque époque est nominale, dégradée ou non fiable, et le résultat dit quand et pourquoi. Les événements et les baisses de C/N0 prédites indiqués dans le scénario sont évalués par rapport à des tolérances indiquées dans le même fichier : détecté, tardif ou manqué, et concordant ou discordant. Les sorties sont le JSON de résultat, un CSV par époque et un graphique ; le résultat porte le SHA-256 du journal et chaque seuil. Également accessible depuis Python (kshana.receiver_trust), le paquet WebAssembly (receiver_trust, journaux en ligne) et le nouvel outil assess_receiver_log du serveur Model Context Protocol (MCP). Sur les journaux de leurrage JammerTest 2024, le chemin du moteur reproduit la première alarme de la chaîne de référence indépendante préenregistrée à chaque début publié (tests/receiver_trust_jammertest.rs). Guide : docs/RECEIVER-TRUST.md ; exemple : examples/receiver-trust/. Les moniteurs restent MODELLED ; aucune ligne de la matrice de vérification ne change.

0.30.0 - 2026-10-03#

Une version mineure. Les tours de validation 2 et les paquets de la vague 1 font passer la matrice de vérification de 223 lignes (93 VALIDATED) en 0.29.3 à 249 lignes (123 VALIDATED, 122 MODELLED, 4 PARTNER) ; chaque promotion a été vérifiée face à une référence indépendante avec une tolérance fixée avant l'exécution, et chaque désaccord est publié comme constat. Nouveautés : un lecteur natif de noyaux NAIF et un chemin DE440, un chemin de propagation et de temps SGP4 vers ITRS validé, une bibliothèque d'horloges mesurées, un générateur de référence LunaNet AFS, des solveurs en précision étendue et en information de racine carrée, et un vrai traitement IQ lunaire sur les données LuGRE. Les chiffres publiés qui ont bougé sont listés comme révisions ci-dessous.

Vingt-sept lignes de la matrice de vérification deviennent VALIDATED après qu'une référence indépendante a concordé dans une tolérance fixée avant la première comparaison (la règle de promotion de docs/VALIDATION.md) : dix lors d'un premier tour de validation et dix-sept lors d'un second. Cinquante et une lignes MODELLED ont été soumises à une référence externe au premier tour et les lignes routables restantes au second ; chaque désaccord est consigné ci-dessous comme constat plutôt que corrigé par réglage. Trois lignes ont été scindées pour qu'une partie validée ne porte pas un reste non validé, ce qui fait passer la matrice de 223 à 226 lignes ; les paquets de validation intégrés depuis la font passer à 249. Les décomptes sont lus dans le docs/VERIFICATION-MATRIX.md généré.

0.29.0 après le tour 1 Non publié
Lignes de la matrice de vérification 223 223 249
dont VALIDATED face à une référence externe 83 93 123
dont MODELLED 136 126 122
dont PARTNER 4 4 4
Abréviations utilisées dans cette entrée
Abréviation Signification
ADD, ARAIM, MAAST Airborne Design Document (de l'ARAIM) ; surveillance autonome avancée de l'intégrité par le récepteur ; Matlab Algorithm Availability Simulation Tool de l'université Stanford
ADEV, VRW, ARW écart-type d'Allan ; marche aléatoire de vitesse ; marche aléatoire d'angle
ANISE, SPICE, NAIF, PCK une boîte à outils open source d'astrodynamique (Nyx Space) ; la boîte à outils Spacecraft, Planet, Instrument, C-matrix, Events de la NASA, issue de son Navigation and Ancillary Information Facility ; noyau de constantes planétaires
BCRS, TDB, TT Barycentric Celestial Reference System ; temps dynamique barycentrique ; temps terrestre
BIPM, UTC(k) Bureau international des poids et mesures ; la réalisation du temps universel coordonné par un laboratoire
CCSDS, OEM, LTC, TCL Consultative Committee for Space Data Systems ; Orbit Ephemeris Message ; systèmes de temps lunaires écrits dans le champ TIME_SYSTEM du message
CRLB borne inférieure de Cramér–Rao
CW mouvement relatif de Clohessy–Wiltshire
DE440 Éphéméride de développement 440 du Jet Propulsion Laboratory
DOP, PDOP dilution de précision ; dilution de précision de position
EKF, UKF, INS, GNSS, IMU filtre de Kalman étendu ; filtre de Kalman sans parfum ; système de navigation inertielle ; système mondial de navigation par satellite ; centrale inertielle
EMT, VPL, HPL seuil effectif du moniteur ; niveau de protection vertical et horizontal
EOP, IERS, PCC, MAE paramètres d'orientation de la Terre ; International Earth Rotation and Reference Systems Service ; Prediction Comparison Campaign ; erreur absolue moyenne
ERFA, SOFA Essential Routines for Fundamental Astronomy ; Standards of Fundamental Astronomy
GMAT General Mission Analysis Tool de la NASA
NTN, SSB réseau non terrestre (3GPP) ; bloc de signal de synchronisation
IGS, ILRS, ITRF2020 International GNSS Service ; International Laser Ranging Service ; International Terrestrial Reference Frame 2020
ILS, LAMBDA moindres carrés entiers ; Least-squares AMBiguity Decorrelation Adjustment
ISB biais inter-systèmes
LEO orbite terrestre basse
MHSS, PL, TPL séparation de solutions à hypothèses multiples ; niveau de protection ; niveau de protection de synchronisation temporelle
PSD, IQ, SigMF densité spectrale de puissance ; échantillons en phase et en quadrature ; Signal Metadata Format
QPN bruit de projection quantique
RAIM surveillance autonome de l'intégrité par le récepteur
SBAS, WAAS, DFMC, GEO système de renforcement par satellite ; le Wide Area Augmentation System américain ; bifréquence multi-constellation ; un satellite SBAS géostationnaire
RMS, SISRE valeur quadratique moyenne ; erreur de distance du signal dans l'espace
RTKLIB une bibliothèque open source de positionnement GNSS
TCXO oscillateur à quartz compensé en température
VLBI interférométrie à très longue base

Validé#

Chaque ligne ci-dessous nomme son type de référence indépendante (Bibliothèque : une bibliothèque tierce indépendante calculant une grandeur uniquement définie ; Mesuré : données réelles mesurées ; P2 : une bibliothèque numérique indépendante recalculant une grandeur d'algèbre linéaire sur des entrées versionnées), la référence indépendante, la tolérance fixée avant l'exécution et le résultat. Chaque promotion a été réexécutée par un second relecteur, qui a régénéré le jeu de test octet pour octet et a montré qu'une mutation délibérée du moteur fait échouer le test.

  • Fusion de capteurs GNSS/INS (Bibliothèque), limitée à l'EKF d'erreur à 15 états faiblement couplé : NaveGo v1.4 (LGPL-3.0, exécuté sous GNU Octave) sur son propre trajet réel IMU/GNSS Ekinox. Le RMS horizontal, vertical et d'innovation de position de Kshana valent 0,912, 0,940 et 0,861 de ceux de NaveGo (seuil 1,2) et son innovation normalisée moyenne vaut 0,395 (seuil 1,5). Le GNSS est présent pendant tout le trajet, aucune coupure n'est donc testée. L'UKF fortement couplé et le filtre d'horloge couplé restent en dehors de l'affirmation.
  • Budget d'erreur d'attitude et de pointage à 3 degrés de liberté (Bibliothèque), restreint au pic de couple de gradient de gravité : Basilisk 2.9.1 GravityGradientEffector, 40 cas, à 1e-12 près en relatif (pire cas 2.1e-15). Le budget de pointage RSS est une somme de nombres fournis par l'appelant et reste en dehors.
  • Géométrie conjointe lunaire de communications et de navigation (Bibliothèque), restreinte au placement du site, à l'azimut, à l'élévation et à la distance : ANISE 0.10.2, 768 échantillons, à 1e-6 deg et 1 mm près (pire cas 2.2e-12 deg et 5.6e-9 m). Le paramètre de précision de télémétrie est une entrée de conception en dehors de l'affirmation.
  • Dynamique d'attitude d'un corps rigide sans couple (Bibliothèque) : le corps central de satellite Basilisk 2.9.1, 1e4 s sur deux inerties générales, quaternion et vitesses angulaires à 1e-9 près (pire cas 3.3e-11 et 3.4e-12 rad/s).
  • Résolution de l'ambiguïté entière de la phase de la porteuse GNSS (LAMBDA) (Bibliothèque), restreinte à la solution ILS et à ses deux meilleures normes : RTKLIB v2.4.2-p13 lambda(), 300 covariances, 0 désaccord d'entiers, normes à 1e-9 près en relatif (pire cas 5.6e-13). Le taux de réussite par bootstrap reste vérifié en interne seulement.
  • PL de synchronisation temporelle composé, MHSS scalaire (P2) : numpy 2.3.5 et scipy 1.18.1 sur 300 entrées versionnées, PL à 1e-9 près en relatif (pire cas 1.2e-10), sous-ensemble déterminant identique.
  • Blanchiment en mode commun GLS et identité de Mahalanobis (P2) : LAPACK de numpy 2.3.5 sur 201 covariances versionnées, à 1e-12 près en relatif (pire cas 7.9e-16) ; nombres de conditionnement jusqu'à 19,3.
  • Fournisseur d'orientation lunaire des axes principaux DE440 (Bibliothèque) : SPICE pxform sur le PCK binaire à 2 000 époques hors nœud, à 1.7e-5 rad près (pire cas 1.7e-6 rad, environ 3 m à la surface), après la correction listée sous « Corrigé ».
  • Entrée et sortie d'enregistrements SigMF, et spectres de Welch (Bibliothèque), restreintes à la lecture et à l'écriture SigMF et à welch_psd : scipy 1.18.1 signal.welch à 1e-12 près en relatif par case (pire cas 6.0e-14) ; enregistrements de sigmf-python 1.13.0 décodés à l'identique bit à bit ; métadonnées du crate valides face au schéma SigMF v1.2.6. La synthèse IQ et ses comparaisons de modèles restent en dehors.
  • Ajusteur d'éphéméride diffusée LEO et SISRE selon l'intervalle d'ajustement (Mesuré), restreint à l'ajustement képlérien à 16 paramètres et à son SISRE d'orbite seule : orbites précises ITSG de TU Graz pour quatre satellites face aux statistiques de Liu et al. 2025, composantes à moins de 1.5x (0,804 à 1,087) et SISRE à moins de 1.5x (0,716 à 0,809).

Constats#

La référence indépendante a contredit ces lignes, qui restent donc MODELLED. Chaque constat est aussi écrit dans le texte de référence indépendante de la ligne (et donc dans docs/MODELLED-RATIONALE.md), avec un test qui le fige.

  • Estimation de l'état d'horloge embarquée : sur des horloges IGS mises de côté de 11 satellites GPS Block IIF, le filtre à trois états est cohérent à un pas mais trop confiant à une heure sur 9 sur 11 (les termes périodiques et de scintillation ne sont pas dans le modèle).
  • Détection du leurrage : sur JammerTest 2024, aucun moniteur au niveau des observables n'a donné l'alarme dans les 10 s suivant l'un des 8 débuts publiés, et trois fenêtres antérieures aux débuts comportaient de fausses alarmes.
  • Niveau de protection de synchronisation temporelle sous leurrage : l'erreur de temps non détectée mesurée dépasse le TPL à 3 débuts détectés sur 8 (1.9x à 5.3x) ; une calibration d'horloge de 60 s ne couvre pas la dérive du TCXO du récepteur.
  • Fenêtre de lancement et géométrie d'ascension : face à Orekit 12,2, la géométrie concorde aux arrondis près, mais la vitesse du site due à la rotation terrestre dépasse 1e-6 en relatif à 62,9 deg de latitude (1.12e-6, le mouvement du pôle que le modèle sphérique omet). Tour 2 : la vitesse au pôle vrai avec une époque concorde, la vitesse par défaut sans époque dépasse encore (voir ci-dessous).
  • Couloir de rentrée balistique (Allen–Eggers) : la décélération maximale prédite pour la rentrée de Stardust est de 61,8 g contre 32,89 g reconstitués (+88 %, tolérance 15 %).
  • Erreur conjointe d'UT1 et de mouvement du pôle : face à la formule de précision imprimée dans 178 numéros du Bulletin A de l'IERS, le pôle concorde à moins de 1.5x mais pas UT1 (0,48 à 10 jours, 1,59 à 40 jours). Remplacé au tour 2 : la ligne est désormais VALIDATED (voir ci-dessous).
  • Entrée d'orientation terrestre par défaut hors ligne : astropy confirme le décompte des lignes, mais les 12 lignes que le crate appelle prédictions du Bulletin A sont signalées comme mesurées (I), et non comme prédites (P). Les chiffres de concordance de la ligne du prédicteur opérationnel portaient donc sur des lignes mesurées. Remplacé au tour 2 : le moteur classe les lignes d'après l'indicateur et la ligne est VALIDATED.
  • Erreur de prédiction d'orientation terrestre de style opérationnel : l'erreur d'UT1 du prédicteur vaut 2.4x à 12.6x celle du Bulletin A à 1 à 10 jours et 5,32 ms à 10 jours, en dehors de la plage de 0,36 à 3,13 ms de la 2nd EOP PCC.
  • VLBI géodésique lunaire : face aux temps de parcours de la lumière d'ANISE via DE440, aucun retard n'est à 1 ps près ; le plus grand écart est de 24 µs, essentiellement dû au centre analytique de la Lune (à environ 200 km de DE440). Tour 2 : le chemin par noyau est VALIDATED dans une ligne à part ; ce chemin analytique reste MODELLED.
  • Export d'interopérabilité lunaire : Orekit 12,2 refuse les systèmes de temps LTC et TCL, de sorte que l'échange des fichiers OEM lunaires avec un second lecteur n'est pas établi.
  • Mouvement relatif de Clohessy–Wiltshire : face au mouvement non linéaire d'Orekit à 100 m, l'écart est de 1,2 à 6,3 mm, au-dessus de 1 mm ; il évolue comme le terme du second ordre omis, de sorte que la tolérance préenregistrée se situait sous l'erreur de linéarisation. Remplacé au tour 2 : la correction du second ordre est VALIDATED face au même seuil.
  • Croissance de l'erreur en roue libre INS/TRN : face à un Monte Carlo en inertiel libre de NaveGo, les lois de croissance tiennent à 5 % près jusqu'à 600 s et surestiment au-delà (2.2x à 8x à une heure), parce qu'elles omettent la rétroaction de Schuler. Remplacé au tour 2 : le modèle d'erreur de Schuler est VALIDATED.
  • Volume de service lunaire à partir de la vraie géométrie de constellation : 4 des 12 statistiques de disponibilité publiées diffèrent de plus de 2 points de pourcentage (jusqu'à 22,5).
  • Surbornage hétérogène du biais de traçabilité UTC(k) : sur 105 024 lignes du BIPM, le surbornage est dépassé sur 50,8 % des lignes ; l'incertitude publiée borne la mesure du décalage par le BIPM, et non le décalage lui-même.
  • Classification de l'espace nul du datum lunaire : sur la géométrie publiée à cinq réflecteurs, la corrélation est de -0.78 contre -0.97, et la CRLB de l'origine est inférieure de 96 à 98 % à celle de l'article.
  • Substrat de géométrie du datum LLR lunaire : face à 192 points normaux lunaires de l'ILRS de 2024, le RMS des résidus aller simple était de 96 m avec l'ancienne interpolation d'orientation et est de 22,7 m après la correction ci-dessous, toujours au-dessus du seuil de 10 m (coordonnées de station arrondies, pas de mouvement du pôle). La série d'orientation se borne silencieusement en dehors de 2024-2025. Tour 2 : le modèle de distance mesurée est VALIDATED dans une ligne à part (2,81 m) ; la série couvre désormais 2014-2030 et signale une erreur en dehors.
  • Couplage du taux d'horloge relativiste au référentiel : le terme de potentiel propre est supérieur de 3.18e-4 à la valeur publiée (tolérance 1e-4) ; l'article évalue un potentiel différent, de sorte qu'aucune valeur publiée de cette forme analytique n'existe. Remplacé au tour 2 : le potentiel équatorial de degré 2 est VALIDATED face au même article.
  • Constantes physiques de chaque corps du système solaire : 12 des 84 constantes des corps ajoutés diffèrent de NAIF pck00011 et gm_de440 (éléments plus anciens des satellites de Mars ; d'autres solutions de GM pour Uranus, Neptune et Pluton). Tour 2 : les constantes suivent désormais NAIF (une transcription, non comptée), et l'orientation calculée concorde avec SPICE ; la ligne reste MODELLED.
  • Modèles d'éphéméride LEO sélectionnables : l'ajustement à 22 paramètres laisse 1.71x et 1.86x l'erreur le long de la trace publiée sur des arcs de 20 min, au-dessus de 1.5x. Remplacé au tour 2 : le modèle à 22 paramètres et son ajustement sont VALIDATED dans une ligne à part.
  • Positionnement conjoint GNSS et LEO : le biais inter-systèmes concorde avec RTKLIB, mais 93,2 % des époques sont à 3 m de l'ITRF2020 contre 95 % ; RTKLIB lui-même atteint 88,2 % sur les données (93,6 % après la correction du délai de groupe du tour 2).
  • Cécité d'intégrité en mode commun et cartes de couverture et de DOP : les deux comparaisons ont réussi mais ont été écartées à la relecture parce qu'un moteur délibérément faux les réussit aussi (la première ne vérifie qu'une identité interne ; les planchers publiés de la seconde ne peuvent pas voir un PDOP doublé). Tour 2 : la cécité d'intégrité en mode commun est VALIDATED sur des entrées porteuses de parité ; les cartes de couverture restent un constat (voir ci-dessous).

Tour de validation 2#

Le second tour a repris chaque ligne que le premier avait laissée routable, avec de nouveaux préenregistrements versionnés avant que tout jeu de test soit récupéré ou toute référence indépendante exécutée, un second relecteur adverse qui a réexécuté chaque comparaison et une mutation délibérée du moteur qui doit faire échouer chaque test. Le propriétaire a accepté la formulation corrigée de la ligne de borne hors Omega le 2026-10-02 avant sa promotion (son ancien texte contredisait le code).

Promues à VALIDATED (17). Type de référence indépendante entre parenthèses ; tolérance fixée avant l'exécution.

  • Couplage du taux d'horloge relativiste au référentiel (Référence) : L_m d'Ashby et Patla 2024 à 2.8e-6 près (seuil 1e-4) à partir du potentiel équatorial de degré 2 des deux champs que cite l'article ; gravité de degré 350 de pyshtools pour l'entrée radiale (8.3e-5) ; vitesse lunaire DE441 (2.5e-3).
  • Entrée d'orientation terrestre par défaut hors ligne (Bibliothèque) : astropy 8.0.1 et le Bulletin A de l'IERS n° 039 confirment les 30 lignes finales, 54 rapides et 90 prédites de l'extrait retaillé.
  • Erreur conjointe d'UT1 et de mouvement du pôle (Bibliothèque) : les rotations complètes d'astropy et de pyerfa reproduisent la table conjointe (UT1 et pôle à 6e-16 près, la combinaison à 1.9e-7 près) ; les erreurs réalisées du rapport annuel 2019 de l'IERS donnent des rapports de 1,001 à 1,100.
  • Empreinte et couverture d'une charge utile d'observation de la Terre (Bibliothèque) : Orekit 12,2 et GeographicLib 2,1 à chaque seuil préenregistré, avec la régression nodale J2 désormais dans l'espacement des nœuds.
  • Mouvement relatif de Clohessy–Wiltshire (Bibliothèque) : avec une correction du second ordre sous forme analytique, à 1.2e-7 m du mouvement non linéaire d'Orekit contre 1e-3 m ; la matrice linéaire seule reste caractérisée (1,2 à 6,3 mm).
  • Ciblage dans le plan B et assistance gravitationnelle en coniques raccordées (Bibliothèque) : plan B de GMAT R2026a, asymptotes, C3 et éléments héliocentriques ; sbpy 0.6.0 et Kasuga et Jewitt 2019 pour le paramètre de Tisserand.
  • Croissance de l'erreur en roue libre INS/TRN (Bibliothèque) : un modèle d'erreur de Schuler à neuf états à 5 % près des exécutions en roue libre corrigées de NaveGo aux 48 points (pire cas 3,70 %).
  • Cécité d'intégrité en mode commun (P2) : lstsq de numpy sur 1464 entrées porteuses de parité à 1e-12 près (pire cas 1.06e-14).
  • OD et horloge lunaires conjointes multi-techniques (P2) : numpy recalcule chaque pas de Gauss-Newton, sigma et erreur de station sur six réseaux (à 2.4e-11 près) après une correction de la résolution QR.
  • Covariance des coordonnées de station du VLBI lunaire (Bibliothèque) : une jacobienne construite avec SPICE reproduit le calendrier, le spectre, les sigmas et l'espace nul à 1 % et 0,1 deg près ; numpy à 2e-13.
  • Borne de mode commun indétectable avec résidu hors Omega (P2, formulation corrigée par décision du propriétaire) : LAPACK de numpy sur 256 cas à 1e-12 près, six infinis exacts.
  • Classification de l'espace nul invariante par changement de base (P2) : intersection de sous-espaces SciPy et NumPy sur 72 matrices construites, entiers exacts, norme du projecteur à 6.0e-15 près.
  • Services ionosphérique monofréquence et UTC d'un message de navigation LEO (Bibliothèque) : GNSSTk 15.3.1 pour Klobuchar, Az et la dérive UTC ; ERFA pour les trois cas de seconde intercalaire.
  • Borne de positionnement par réseau non terrestre 5G (P1) : bornes à SSB unique de Bachl, Lei et Nabeel 2026 à moins d'un demi-chiffre imprimé ; numpy pour les covariances de position.
  • Modèle de distance mesurée LLR (Mesuré, nouvelle ligne scindée du substrat de datum LLR) : 192 points normaux lunaires de l'ILRS à 2,81 m de RMS contre un seuil de 10 m, avec le temps de parcours de la lumière barycentrique de l'IERS 2010 ; les composantes sous le seuil ne sont pas résolues une à une, et la ligne le dit.
  • VLBI géodésique lunaire, chemin par noyau (Bibliothèque, nouvelle ligne scindée de la ligne VLBI lunaire) : temps de parcours convergés de SPICE à 1 ps près et dérivées partielles à 1e-6 près à des époques proches de J2000 ; le chemin analytique par défaut reste MODELLED.
  • Modèle d'éphéméride LEO à 22 paramètres de Liu et al. 2025 et son ajustement (Mesuré, nouvelle ligne scindée de la ligne des modèles sélectionnables) : de vraies orbites précises à moins de 1.5x des statistiques publiées sur les jours de l'article et les jours mis de côté (0,683 à 1,186) ; la convention d'échelle de n_dot est transcrite et non validée par cette comparaison, et la règle d'arrêt est la règle de convergence des paramètres de Kshana, et non la règle de variation du RMS de l'article. Le polynôme ATOMIC et la table à cinq altitudes restent MODELLED.

Lignes VALIDATED existantes réétayées (aucun changement de nombre).

  • Positions des planètes d'après les éléments de Standish du JPL et temps de parcours de la lumière entre corps du système solaire : les seuils a posteriori de deux fois le nominal sont remplacés par des comparaisons préenregistrées avec JPL Horizons DE441 (RMS au plus égal au chiffre du tableau 8.10.1 de l'Explanatory Supplement, pire cas 0,778, la séparation de la Terre et la rotation ICRF comprises ; temps de parcours à 1e-6 s d'Horizons sur les positions DE441, pire cas 6.7e-9 s). Leurs indicateurs « limite fixée après la comparaison » sont retirés.
  • Intégrité (RAIM/ARAIM/SBAS) : la ligne ne repose plus sur des contrôles de plausibilité. Elle dit désormais : la séparation de solutions à hypothèses multiples de l'ARAIM de l'ADD v4.2 concorde avec Stanford MAAST pour l'ARAIM 2 sur 270 cas réels (pire écart de VPL 2.2e-3 m contre 0,05 m) ; la détection et l'exclusion RAIM instantanées concordent avec raim_fde de RTKLIB sur 2016 décisions sur 2016, avec le niveau de protection de pente à 2.7e-12 m près ; les niveaux de protection L1 SBAS DO-229E concordent avec Stanford MAAST sur de vraies diffusions WAAS (2868 paires à 1.6e-5 m près). Elle indique clairement que les fonctions à sigma uniforme raim::araim_raim et raim::araim_dual_raim ne sont PAS conformes à l'ADD (écarts à entrées appariées de 0.75/4.04 m et 0.39/1.93 m en VPL/HPL, un constat), que la comparaison SBAS L5 DFMC est un constat (308 paires sans GEO en vue sont protégées par Kshana et non par MAAST) et que raim::solution_separation_raim n'a aucune comparaison externe. Son indicateur d'auto-évaluation est retiré.
  • Ajusteur d'éphéméride diffusée LEO : l'orbite vraie intégrée est ajoutée à la partie validée (Orekit 12,2 à 4,55 mm près sur 6 h, seuil 2 cm) ; les polynômes de correction, l'ajustement d'horloge et le compromis sur la période de mise à jour restent modélisés.

Constats et lignes bloquées (restent MODELLED). Le texte de référence indépendante de chaque ligne porte le constat et son test figé.

  • Modulation des signaux de navigation (Betz 2001, Hein 2006) : les spectres et les corrélations concordent ; les lobes latéraux de 24 MHz et chaque biais de multitrajet (11 à 15 % trop bas) non, cause non résolue.
  • Géolocalisation TDOA/FDOA : les bornes correspondent à Ho et Chan et à Ho et Xu, et au code des auteurs à 3e-12 près ; les facteurs d'Ottawa imprimés à partir d'un Monte Carlo diffèrent de 1,3 % et 4,4 %.
  • GNSS terrestre à distance lunaire : les moyennes au zénith de GENESIS concordent avec Montenbruck et al. 2023 sur 5 sur 6 ; les moyennes au nadir sont de 1,0 à 2,4 satellites trop hautes.
  • Cartes de couverture et de DOP : les conceptions terrestres concordent avec Orekit, gnss_lib_py et numpy sur chaque seuil ; les conceptions Lune et Mars dépassent 1e-9 uniquement sur des cellules quasi singulières.
  • Positionnement GNSS conjoint : bifréquence 79,9 % et produits précis 94,2 % à 3 m près contre 95 % (RTKLIB 67,9 % et 94,1 %) ; l'écart d'ISB avec produits précis vient de ce que RTKLIB ignore les décalages d'antenne.
  • Boucles de suivi (GNSS-SDR 0.0.19) : concordance de 35 à 45 dB-Hz ; à 30 dB-Hz PLL +21 %, DLL -32 %, seuils +1,5 dB ; temps de glissement plus courts de 0,5 à 2 décades.
  • Volume de service lunaire (Orekit et Hipparchus) : 155 valeurs sur 160 concordent ; l'exigence du pire échantillon échoue sur la géométrie quasi singulière LNCSS B.
  • Capteur inertiel quantique : le plancher QPN seul est inférieur de 21 à 31 % au bruit mesuré de Gauguet 2009 (seuil 30 %, manqué de 0,5 point).
  • Préréglages d'oscillateurs : les unités mesurées dépassent les préréglages de holdover du rubidium, de court terme du césium et de pire unité du CSAC ; le préréglage OCXO n'a aucun enregistrement mesuré.
  • Densité de météo spatiale : Jacchia 1971 est à un facteur 2 des densités d'accéléromètre au maximum solaire mais environ 1.7x trop dense au minimum de 2008.
  • TEC oblique sans géométrie : 33 arcs sur 36 à 3 TECU de la carte CODE (pire cas 6,84).
  • Détection du leurrage et TPL face au journal officiel JammerTest 2024 : 4 débuts sur 10 détectés à temps ; le TPL est dépassé sur 4 sur 10.
  • Filtre d'horloge sur de nouvelles horloges IGS : deux satellites sur 11 échouent au critère de la somme des innovations.
  • Prédicteur EOP par moindres carrés plus autorégressif : UT1 de 1,73 à 2.11x le Bulletin A à 2 à 10 jours.
  • Surbornage du décalage réalisé UTC(k) : dépassement cumulé de 0,0333 contre 1e-2.
  • Datum du référentiel lunaire à partir d'une campagne : la branche SPICE concorde ; la branche P2 à stations estimées manque 1e-9 sur un problème de conditionnement 2.1e8.
  • Datum du référentiel lunaire à partir de vrais LLR : 15 chiffres sur 16 concordent avec SPICE ; le sigma de la translation en z est trop haut de 1,03 % contre 1 %.
  • Rentrée (Allen-Eggers) : la solution à masse ponctuelle concorde avec les reconstitutions d'agences (une simple vérification croisée) ; la comparaison avec l'accéléromètre est bloquée faute d'une source Hayabusa2 lisible.
  • Masques ITU-T : les valeurs de l'exemple imprimé concordent ; les limites de classe G.8273.2 n'en ont pas (bloqué).
  • Géométrie de la fenêtre de lancement : la vitesse du site au pôle vrai avec une époque concorde avec Orekit (4.9e-8) ; la vitesse par défaut sans époque dépasse encore (1.12e-6). Non promu ; suite en attente.
  • Constantes physiques de chaque corps : désormais 0 sur 84 diffèrent de NAIF (une transcription), et l'orientation calculée concorde avec SPICE à 1.4e-10 rad près. Non promu ; suite en attente.
  • Bloqué en attente d'une décision de périmètre du propriétaire, chacun avec sa comparaison concordante versionnée : observabilité absolue d'une station lunaire, DOP de balises de surface, l'export hors axe, puissance de détection intermodale, la statistique de cohérence en mode commun et couverture LEO polaire.
  • Bloqué en attente de données : budget d'erreur du transfert de temps (nécessite une réduction de données réelles), C/N0 de JammerTest (position de l'antenne et répartition de puissance non documentées).

Révisions (chiffres publiés qui ont bougé, ancien -> nouveau).

  • Les niveaux de protection de snapshot_raim sont désormais dans le plan local géodésique au lieu du plan radial : jusqu'à 0,31 m de HPL et 0,14 m de VPL à ABMF (16 deg N) ; aucune référence figée (golden) n'a bougé, mais le résumé enregistré du tutoriel gnss-sim passe d'un HPL moyen de 22,1 m / VPL de 40,0 m à 22,2 m / 39,9 m (docs/tutorials/scenarios/gnss-sim.toml).
  • Valeurs par défaut du couplage taux-référentiel lunaire : d_alpha/d_scale 3.139807e-11 -> 3.138801e-11 ; d_alpha/d_radial 1.807187e-17 -> 1.806185e-17 par mètre.
  • Exécution EOP par défaut hors ligne (realtime-frame-eop, cellules listées dans docs/revisions/M035-default-eop-recut-cell-changes.md) : predicted_rows 12 -> 90 ; plancher du pôle 0,06776 -> 0,05550 mas ; eop_term_m 14,01601 -> 14,01583 ; total_m 20,09759 -> 20,09746 ; total_time_ns 67,03834 -> 67,03790 ; les lignes du tableau 2 de tests/golden/realtime-frame-eop.csv ; concordance du prédicteur opérationnel 0.256/0.695/1.252/3.885 ms -> 0.133/0.421/0.839/2.786 ms.
  • docs/LEO-NAVMSG.md liu22 SISRE orbite/avec horloge : 60 s 0.011/0.046 -> 0.014/0.046 cm ; 300 s 0.068/0.139 -> 0.074/0.142 cm ; 600 s 0.269/0.299 -> 0.258/0.290 cm.
  • Table d'altitudes de Liu, Kshana (rapport) : GRACE-A 5,40 (0,61) -> 4,25 (0,48) ; GRACE-C 4,12 (0,66) -> 2,87 (0,46) ; Sentinel-2A 2,95 (1,03) -> 2,20 (0,77) ; HY-2A 2,38 (1,13) -> 1,25 (0,59) ; Sentinel-6A 0,70 (0,94) -> 0,51 (0,67).
  • Message de navigation LEO, échelle de nDot 2^-60 -> 2^-58 (non préenregistré, divulgué ; en dehors de la comparaison d'ajustement) ; le CRC de la trame d'exemple liu22 0x62373A -> 0xDED99C.
  • Tableau de vérification de docs/LEO-NAVMSG.md : la ligne Liu et ATOMIC est scindée en une ligne VALIDATED à 22 paramètres et une ligne MODELLED ATOMIC et à cinq altitudes.
  • Texte de la ligne d'orientation lunaire des axes principaux DE440 : portée 2024-2025 / 731 lignes -> 2014-2030 / 6 209 lignes ; « se borne silencieusement » -> erreur en dehors de sa portée.
  • Scénario eo-coverage : equatorial_ground_track_spacing_km 2756,37 -> 2752,17 km ; nouveaux champs inclination_deg (98,19) et nodal_period_min (98,893).
  • constellation-multi-gnss-coverage (l'horloge de référence TDOP/GDOP est désormais la constellation de plus petit numéro en vue) : GDOP global max 2,2236 -> 2,1205, moyenne 1,122 -> 1,131, médiane 1,115 -> 1,125, p90 1,255 -> 1,265, p95 1,305 -> 1,315, p99 1,41 -> 1,42, et la carte de GDOP par cellule ; mean_visible_by_constellation sommé en entiers (environ 1e-12 en relatif, invisible à 4 décimales).
  • Position GNSS conjointe monofréquence après la correction du délai de groupe diffusé : 93,2 % -> 93,6 % à 3 m près ; médiane d'ISB -0.351 -> -0.114 ns.
  • tracking-loop jitter_table log10_mean_time_to_cycle_slip_s (boucle de Costas SNR rho/4) : au seuil de 25,47 dB-Hz 11,58 -> 2,10 ; à 25 dB-Hz 9,55 -> 1,60 ; à 22 dB-Hz 2,24 -> -0.14.
  • ins-trn-coast : chaque sortie bouge avec le modèle d'erreur de Schuler ; le pic TRN du scénario livré 52,932679 -> 44,711834 m (tests/conflict_resilience_architecture_guard.rs).
  • Rapport de lunar-vlbi : nouvelle clé geometry_path (« analytic » à l'exécution par défaut, aucune valeur numérique n'a changé) ; nouveaux champs facultatifs planetary_kernel_path, earth_orientation_kernel_path et moon_orientation_kernel_path, avec epoch_partials sur le chemin par noyau ; la description du type de scénario est réécrite. La référence indépendante de la ligne de vérification pour le chemin par noyau est SPICE (0,06 ps) ; ANISE (0,12 ps) devient une vérification croisée de l'évaluation du noyau.
  • Constantes des corps : GM de Phobos 7.087e5 -> 7.087546066894452e5 ; Deimos 9.62e4 -> 9.615569648120313e4 ; Uranus 5.7939506103e15 -> 5.793951256527211e15 ; Neptune 6.83509997e15 -> 6.835103145462294e15 ; Pluton 8.69326e11 -> 8.696138177608748e11 (m^3/s^2) ; rayon équatorial de Phobos 13,1 -> 13,0 km ; pôle et méridien origine de Phobos et Deimos d'après pck00011 ; le prime_meridian_deg du système solaire inclut désormais les termes quadratique et périodiques.
  • europa-surface-pnt (body-pnt sur Europe), à partir de l'orientation complète d'Europe de pck00011 (7cfd66b4 ; l'orientation concorde avec le pxform de SPICE à 1.4e-10 rad près), ce qui déplace l'atterrisseur dans l'espace inertiel : disponibilité relais seuls / avec la portée Terre 0,485 / 0,725 -> 0,480 / 0,719 (83 -> 82 époques sur 171 avec relais seuls), PDOP médian 5,266 -> 5,360, erreur RMS de position 129,516 / 100,983 m -> 112,742 / 86,147 m, sigma formel médian 5,266 / 4,272 m -> 5,360 / 4,239 m. Le tableau de docs/SOLAR-SYSTEM.md et le contrôle figé de mcp/kshana-mcp/tests/round_trip.rs suivent ; mars-orbit-pnt est inchangé.
  • space-weather (f107 180, f107a 165, kp 4), le facteur calibré remplacé par Jacchia 1971 : activity_density_kg_m3 à 300/400/500/600/800 km 2.602e-11 -> 3.608e-11, 4.176e-12 -> 6.929e-12, 8.136e-13 -> 1.618e-12, 1.769e-13 -> 4.189e-13, 1.544e-14 -> 3.781e-14 ; activity_factor 1.076/1.121/1.168/1.216/1.320 -> 1.492/1.860/2.322/2.881/3.232 ; reference_exospheric_temperature_k retiré, mean_exospheric_temperature_k ajouté (1186,7 K) ; tests/space_weather_reference.rs : l'amplitude du cycle solaire à 800 km est désormais de 10.4x (NRLMSISE-00 13.6x) et l'assertion d'altitude suit la hausse de NRLMSISE jusqu'à 500 km et sa baisse à 800 km.
  • ntn-5g-positioning toa_median_sigma_3d_m : NR 5 MHz 2,0903959 -> 2,0903962 m ; NB 200 kHz 25,938613 -> 25,938839 m (texte du résumé inchangé à 2,09 / 25,94 m).
  • lunar-joint-od-clock (résolution QR) : with_vlbi.station_pos_err_m 3,541344 -> 3,541350 m ; without_vlbi.station_pos_err_m 2183,119 -> 2183,558 m.
  • docs/field-units-schema.json réémis pour les champs nouveaux et supprimés ci-dessus.

Paquets de validation#

D12, précision étendue et solveur en racine carrée (deux nouvelles lignes VALIDATED : 226 -> 228 lignes, 110 -> 112 validées).

Partie 1, référence indépendante en précision étendue :

  • Datum du référentiel lunaire avec les stations estimées : une référence indépendante mpmath en précision étendue à 50 chiffres (préenregistrée 804662d5, seuils mis à l'échelle du conditionnement d'après une formule d'erreur inverse a priori) concorde sur une nouvelle date de campagne (2026-03-18) et sur le scénario d'origine du 2024-01-01 ; nouvelle ligne VALIDATED sous P2. Elle tranche le désaccord antérieur en double précision : les sigmas du datum du moteur sont erronés jusqu'à 9.7e-6, les voies inverse et propres de NumPy jusqu'à 6.2e-6, et ses voies Cholesky et QR d'environ 1e-8. Le moteur est dans sa borne d'erreur mais environ mille fois moins précis qu'une voie par factorisation.
  • Environnement de la référence indépendante : mpmath 1.3.0 ajouté.
  • Révisions : aucune. Aucun fichier de référence figée (golden) ni chiffre publié ne change ; la ligne « Datum du référentiel lunaire à partir d'une campagne d'observation » reste MODELLED (décision du fondateur 2026-10-02, option A : elle n'emprunte pas le statut de la ligne distincte) ; le texte de ses tests cite le nouveau test et son constat.

Partie 2, solveur de datum en information de racine carrée :

  • Nouveau solveur facultatif en information de racine carrée (linalg_sr ; solver = "srif" dans le scénario lunar-frame-campaign) : QR de Householder, marginalisation par le facteur triangulaire, une SVD de Jacobi pour le spectre, et produits compensés à partir des seules opérations correctement arrondies. Face à la référence indépendante à 50 chiffres (préenregistrée b41908c9), ses sigmas du datum concordent à 3e-13 près sur une nouvelle date (2026-06-09) ; sur les entrées du 2026-03-18 et du 2024-01-01, le solveur par défaut est erroné jusqu'à 1e-5. Nouvelle ligne VALIDATED sous P2. Le solveur par défaut et sa sortie sont inchangés. Les seuils préenregistrés n'établissent des erreurs qu'au-dessus d'environ 2e-7 en relatif : ils rejettent le solveur par défaut mais pas un signe de Householder inversé, un produit scalaire non compensé ou un inverse final spectral, et la ligne le dit.
  • Chemins facultatifs en racine carrée à côté des valeurs par défaut inchangées : fim::crlb_srif, batch_ls::gauss_newton_srif, orbit_determination::determine_orbit_batch_srif, lunar_combination::formal_covariance_srif, precise_od::fit_srif et cislunar_srif::srif_cross_validation_sqrt, sur les nouveaux linalg_sr::weighted_lstsq et covariance_from_sqrt_information. Chacun concorde avec son défaut là où les deux sont précis (un contrôle interne, pas de ligne ; aucune validation n'est revendiquée pour eux). precise_od::fit délègue désormais à une routine partagée ; sa sortie et la sortie par défaut de chaque scénario sont inchangées.
  • Décisions de rang de la campagne de référentiel lunaire : un contrôle préenregistré en précision étendue sur 40 jours confirme chaque décision décidable de bloc de stations et de Helmert de rang plein. La borne a priori ne peut pas établir les 20 jours de Helmert à rang déficient ; en arithmétique exacte, leur défaut est géométrique, avec le seuil de 1e-9 à l'intérieur de la plage naturelle de la campagne pour les rapports de valeurs propres. Aucune ligne.
  • L'affirmation de la ligne de la campagne en précision étendue est restreinte à « dans la borne du pire cas », et son contrôle de direction la plus faible à stations fixes mesure désormais un vrai angle (6.6e-16 rad ; le comparateur est passé d'acos à une corde, le seuil non).
  • Révisions : aucune. Aucun fichier de référence figée (golden) ni chiffre publié ne change ; la ligne « Datum du référentiel lunaire à partir d'une campagne d'observation » est inchangée et reste MODELLED (décision du fondateur 2026-10-02, option A).

D4, colonne vertébrale des éphémérides par noyaux JPL, phase 1 (quatre nouvelles lignes VALIDATED : 228 -> 232 lignes, 112 -> 116 validées).

  • Le lecteur de noyaux NAIF a sa propre ligne. naif_kernel (conteneur DAF, SPK de type 2, PCK binaire de type 2) concorde avec le SPICE Toolkit (CSPICE N0067 via spiceypy 8.2.0) et avec ANISE 0.10.6 sur les 600 états DE440 et les 200 rotations d'orientation lunaire d'une grille aléatoire tirée du propre hachage du commit de préenregistrement (abcd9133), dans des seuils dérivés au préalable de l'évaluation de Tchebychev en double précision (pire cas 0,6 % du seuil, 1.95e-3 m). La ligne affirme que le moteur lit correctement les noyaux JPL, et non que DE440 ou la série analytique est exacte (tests/naif_reader_spice_oracle.rs).
  • ephem_provider::KernelEphemeris : positions DE440 (ou de tout SPK de type 2) par le lecteur propre au moteur, avec des époques TDB en deux parties et le SHA-256 du noyau conservé pour les rapports ; il ne substitue jamais un barycentre de système à une planète. LunisolarSource permet à un chemin de géométrie de choisir la série analytique (par défaut) ou un noyau.
  • Lune par noyau facultative pour lunar-llr-datum et lunar-vlbi-fim : une clé planetary_kernel_path lit le centre géocentrique de la Lune dans le noyau ; rien d'autre ne change, et le rapport gagne un bloc moon_ephemeris nommant le noyau et son SHA-256. Sans la clé, les deux rapports sont identiques à l'octet près à ceux d'avant.
  • Covariance d'un point de la surface lunaire sur le chemin par noyau (nouvelle ligne VALIDATED) : avec toutes les stations fixées et la balise sur la Lune DE440, la covariance de la balise concorde avec une jacobienne de temps de parcours de la lumière de SPICE (pire cas 1.7e-3 face à un seuil de 1 %) et un inverse NumPy (4e-14 face à 1e-9), préenregistré 4a51256 (tests/lunar_vlbi_surface_point_spice_oracle.rs). La ligne du chemin analytique reste MODELLED : sur la Lune analytique, son plus petit sigma de balise est inférieur de 3,9 % à la référence indépendante.
  • Datum du référentiel lunaire à partir d'une vraie campagne, centre de la Lune par noyau (nouvelle ligne VALIDATED) : sur 447 points normaux inédits de 2019-Q2, préenregistrés 830d945a avant qu'aucun soit récupéré, la covariance du datum sur le chemin par noyau concorde avec la référence indépendante SPICE et NumPy inchangée à 7.6e-5 face à des seuils de 1 % et 2 % (tests/validate_llr_datum_kernel_moon_fresh.rs). Le fondateur a décidé que cette ligne n'est promue que sur des points inédits ; le diagnostic sur données déjà vues (c51f8b2) est un constat, pas une preuve. Le seuil ne discrimine pas les modèles de Lune : la Lune analytique le franchit aussi sur la même tranche (pire cas 3.8e-3), la mutation prévue (la Lune par noyau en retard d'une heure) n'a pas été détectée, et au repli, un centre de la Lune erroné d'environ 4 650 km (la Lune prise autour du barycentre Terre-Lune) l'a aussi franchi. La ligne affirme la covariance sur ce chemin, et non le centre de la Lune, et le dit.
  • Positions du Soleil, de la Lune, de Mercure et de Vénus d'après DE440 à des époques UTC (nouvelle ligne VALIDATED) : KernelEphemeris::relative_position_utc concorde avec Skyfield 1,54 sur 600 positions entre 1973 et 2026, pire cas 2,96 m, dans un seuil préenregistré (0bfafe6d) fixé par la série à deux termes TDB − TT (tests/kernel_ephemeris_skyfield_oracle.rs). Les positions des planètes reçoivent maintenant cette nouvelle ligne par noyau ; la ligne de Standish et la ligne des lunes planétaires sont inchangées, et les lunes attendent un scénario qui en a besoin (décision du fondateur).
  • Constats : le seul écart de la comparaison du datum LLR (sigma de la translation en z de 1,025 % contre 1 %) tombe à 0,049 % lorsque seul le centre de la Lune est lu dans DE440, sur des données déjà vues (tests/validate_llr_datum_kernel_moon.rs) ; sur la tranche inédite de 2019, la Lune analytique la franchit aussi, de sorte que l'écart de 2015 était marginal par rapport à la géométrie de ce trimestre. Les lignes analytiques « Datum du référentiel lunaire à partir d'une campagne d'observation RÉELLE » et « Covariance des coordonnées d'un point de la surface lunaire … distincte de celle d'une station terrestre » restent MODELLED ; leurs textes de référence indépendante renvoient désormais aux lignes du chemin par noyau.
  • lunar_ephemeris ne dit plus que le moteur n'a pas de lecteur de noyaux binaires ; il renvoie à la ligne du lecteur et explique pourquoi les noyaux de véhicules spatiaux (types 13 et 21) passent encore par Horizons.
  • Révisions : aucune. Aucun fichier de référence figée (golden), chiffre publié ni valeur de test existante ne change ; les rapports analytiques lunar-llr-datum, lunar-vlbi-fim et lunar-vlbi-fim à toutes stations fixées sont identiques à l'octet près à ceux d'avant (préfixes SHA-256 des résultats 9927aac2, cf1d2671, 25c357e4).

D9, bibliothèque d'horloges mesurées « Clock Atlas » (trois nouvelles lignes, dont une VALIDATED : 232 -> 235 lignes, 116 -> 117 validées).

  • Bibliothèque d'horloges mesurées (clock_library). Fiches d'appareils (bruit blanc de phase, bruits blanc, de scintillation et de marche aléatoire de modulation de fréquence, une dérive de fréquence linéaire et, facultativement, des termes de phase de une à quatre fois par révolution) ajustées sur un enregistrement d'horloge mesuré nommé et évaluées sur des données mises de côté ; variances d'Allan et d'Hadamard tenant compte des trous ; un détecteur de conditionnement qui consigne chaque trou, valeur aberrante de phase, saut de phase, rafale et saut de fréquence et ne connaît rien des limites de fichier ou de jour ; conversion d'une fiche en modèle de bruit de synchronisation de créneau, en modèle d'horloge de Kalman étendu et en niveaux de bruit du moniteur de leurrage. Lecteurs pour les fichiers d'horloge RINEX et IGS, les fichiers par laboratoire du BIPM et la section 1 de la Circular T (realdata::clk) ; un surbornage de vieillissement hiérarchique et cumulé pour UTC(k) (utck_bound, pas encore évalué).
  • Identification du bruit par autocorrélation de retard 1 (allan::lag1_noise_id, Riley et Greenhall 2004), nouvelle ligne VALIDATED (Bibliothèque) : concorde avec autocorr_noise_id d'allantools 2024,6 sur 140 cas, entiers identiques, pire écart 9.6e-13 face à un seuil de 1e-9 (préenregistré 2ec76864 ; tests/clock_library_lag1_noise_id_allantools.rs).
  • Fiches d'appareils mesurées avec prédiction sur données mises de côté, nouvelle ligne MODELLED (un constat) : ajustement sur un tiers, prédiction de l'écart-type d'Allan des deux autres tiers à un facteur 1,5 près (préenregistré 2ec76864). GPS Block IIF sur une nouvelle fenêtre IGS (du 2026-03-01 au 14) : 10 sur 11 ; G27 est optimiste à l'échelle de deux heures (pire facteur 1,510). Césium (dedans, 1,070), OCXO (dehors, 2,348) et strontium (dedans) sont rapportés, non en aveugle. La fiche du récepteur JammerTest et celles du maser Galileo et de la Deep Space Atomic Clock sont bloquées. Une classe de modèles de TCXO de récepteur ZED-F9P sur 12 stations statiques de Wroclaw (Zenodo 6488497) échoue : 1 station sur 11 en aveugle dans une réexécution corrigée divulguée (tests/clock_library_device_cards_oracle.rs, tests/clock_library_f9p_cards_oracle.rs).
  • Fiches GPS Block IIF avec termes par révolution, nouvelle ligne MODELLED (un constat) : sur une seconde nouvelle fenêtre (du 2026-04-01 au 14), 9 sur 11 dans le seuil ; G03 (1,947) et G25 (1,581) sont optimistes parce que leurs enregistrements mis de côté sont plus bruités que leurs tiers d'ajustement ; retirer les termes périodiques échoue pour les 11 (préenregistré fb475550 ; tests/clock_library_periodic_cards_oracle.rs).
  • M002, estimation de l'état d'horloge embarquée, tour 3 (un constat, reste MODELLED) : après le détecteur de conditionnement figé, le filtre étendu du tour 2, le réglage et les critères inchangés satisfont (a) et (c) sur les 11 satellites pour la première fois ; (b) échoue sur G09 (0,894) et G26 (0,876) (préenregistré fb475550 ; tests/clock_state_ext_igs_conditioned_oracle.rs).
  • M010, détection du leurrage, tours 3 à 4b (reste MODELLED) : tour 3 bloqué (167 époques d'apprentissage issues des autres sessions de l'unité JammerTest contre 3600) ; avec une fiche de classe de modèle ZED-F9P (tours 4 et 4b), le moniteur d'horloge ne lève aucune fausse alarme avant le début aux 10 débuts consignés (tour 2 : 86) et 6 débuts sur 10 sont détectés dans les 10 s (tour 2 : 4) ; les quatre mêmes restent tardifs (tests/clock_library_tcxo_card_jammertest_oracle.rs).
  • M083, surbornage UTC(k), tour 3 : préenregistré de façon prospective (fb475550) sur les numéros de la Circular T à partir de 465, pas encore exécuté (tests/utck_bound_prospective_oracle.rs).
  • Environnement de la référence indépendante : l'enregistrement ZED-F9P de Wroclaw est conditionné par les données sous $KSHANA_ORACLES/data/wroclaw_f9p (CC BY 4,0, environ 1,5 Go) ; les jeux de test d'horloges IGS sont intégrés (produits IGS, avec attribution).
  • Révisions : aucune. Aucun fichier de référence figée (golden), chiffre publié ni valeur de test existante ne change ; M001 (réancrage du holdover) n'est pas traité parce qu'aucune classe d'horloge n'a été promue.

D8, un chemin validé de propagation, de référentiel et de temps (trois nouvelles lignes VALIDATED et M131 promue : 235 -> 238 lignes, validées 117 -> 121).

Les types de scénario d'orbite terrestre qui portaient leurs propres modèles à deux corps, à J2 séculaire ou à temps sidéral seul partagent désormais un seul chemin : des jeux d'éléments SGP4/SDP4 avec des dates juliennes en deux parties, portés jusqu'au GCRS et à l'ITRS (International Terrestrial Reference System) par la chaîne IAU (Union astronomique internationale) 2006/2000A, avec des paramètres d'orientation de la Terre facultatifs.

  • Nouveaux sgp4::MeanElementSet, sgp4::SgpOrbit, sgp4::Eop, sgp4::teme_to_itrs_matrix[_eop] et sgp4::gcrs_to_itrs_matrix[_eop] ; Sgp4::new_at et Sgp4::propagate_at prennent des époques en deux parties. Nouveaux jd2::Jd2::from_utc_calendar (convention dtf2d de SOFA pour les jours à seconde intercalaire), jd2::utc_to_tai, tai_to_utc, utc_to_ut1 (via TAI, comme utcut1 de SOFA), tai_to_tt et un jd2::earth_rotation_angle en deux parties.
  • Le mode polaire de leo-pvt propage par SGP4 au 2026-01-01T00:00:00 UTC sur la chaîne IAU (leo_fusion::polar::latitude_sweep_at accepte toute époque) ; le générateur Walker SGP4 passe au référentiel terrestre par la chaîne IAU.
  • Le type de scénario passes exécute un nouveau prédicteur de passages apparents (passes::predict_passes_apparent, apparent_look_angles) : SGP4 sur la chaîne IAU, réfraction ITU-R P.834-9 et temps de parcours de la lumière en liaison descendante (nouveaux commutateurs refraction et light_time, activés par défaut), paramètres d'orientation de la Terre (ut1_minus_utc_s, xp_arcsec, yp_arcsec, par défaut 0), franchissements résolus à 1e-7 s et culmination par recherche par section dorée. Le passes::predict_passes géométrique est inchangé.
  • tests/no_private_models.rs empêche les noyaux de géométrie, de temps et de propagation du paquet de porter une propagation képlérienne privée, des taux de J2 séculaires ou une rotation à temps sidéral seul ; les niveaux rapides nommés et la physique qui fait l'objet d'une ligne sont des tolérances motivées.
  • Nouvelle ligne VALIDATED « Dates juliennes en deux parties et secondes intercalaires sur le chemin de temps des orbites terrestres » : dtf2d/utctai/taiutc de pyerfa 2.0.1.5 sur 224 instants autour des 27 secondes intercalaires, à 1e-6 s près (préenregistré e947e69d) ; pire cas 1.9e-11 s.
  • Nouvelle ligne VALIDATED « Un seul chemin d'orbite terrestre » : positions TEME de 232 jeux d'éléments face à python-sgp4 2,24 (le SGP4 de référence de Vallado) à 6.1e-8 m près (seuil 1 cm), et rotations GCRS -> ITRS et TEME -> ITRS face à c2t06a, pnm06a et ee06a d'ERFA à 2.9e-6 mas et 0,41 mas près (seuils 0,1 et 2 mas), avec des paramètres d'orientation de la Terre (préenregistré 72ea9eb0). Divulgué : la première exécution a échoué au 2016-12-31T23:59:59,5 d'une seconde de rotation ; UT1 avait été pris à partir de la date quasi julienne UTC un jour à seconde intercalaire, le moteur passe désormais par TAI, et la seconde exécution concorde aux mêmes seuils inchangés.
  • M131 « Couverture LEO et dilution de précision pour les utilisateurs polaires et arctiques face au GNSS MEO » devient VALIDATED : Orekit 13.1.8 prend les états GCRS du moteur, les fait tourner et calcule la visibilité et le DOP (NumPy pour les groupes multi-horloges) ; positions à 6.8e-5 m près (seuil 0,2 m), nombres de satellites en vue identiques sur 4040/4040 échantillons, DOP médian à 2.3e-11 près en relatif.
  • Nouvelle ligne VALIDATED « Prédiction apparente des passages sur une station au sol avec réfraction et temps de parcours de la lumière » : Orekit 13.1.8 propageant les mêmes jeux d'éléments dans un TEME qu'il construit selon la définition indiquée, avec la réfraction ITU-R P.834 et son modèle de mesure du temps de parcours de la lumière, sur 60 cas de stations au niveau de la mer : 1210 passages, franchissements à 3.4e-6 s près (seuil 5 ms), élévation maximale à 5.5e-7 deg près, direction apparente à 8.8e-7 deg près (seuil 1e-4 deg).
  • Constats, conservés figés : les premières comparaisons à affirmation complète avec Orekit de bout en bout ont manqué leurs seuils de position et de direction, non à cause du moteur mais parce que le SDP4 d'Orekit 13.1.8 s'écarte du SGP4 de référence pour les orbites d'espace lointain circulaires (e = 0) (jusqu'à 67 m) et que son TEME par défaut repose sur la nutation de l'IERS 1996 (IAU 1980), à environ 72 millisecondes d'arc de la chaîne IAU 2006/2000A (2,7 m en LEO). Le coefficient ITU-R P.834 d'Orekit pour h*theta0^2 est 0,011380 là où la Recommandation imprime 0,01380 ; la comparaison est au niveau de la mer, où ce terme s'annule, et l'écart au-dessus est figé.
  • « Prédiction des passages sur une station au sol (segment sol) » reste VALIDATED, son affirmation étant restreinte au passes::predict_passes géométrique ; le type de scénario passes relève de la nouvelle ligne.
  • Environnement de la référence indépendante : Orekit 13.1.8 avec Hipparchus 4.0.3, pyerfa 2.0.1.5, python-sgp4 2,24 (xval/d8-orekit13/setup.sh).
  • Révisions : scenarios/passes.toml fourni, accès total 1675 s -> 1659 s (cinq passages comme avant ; meilleure élévation maximale 73,25 deg -> 70,08 deg), et chaque sortie de passes bouge avec le nouveau chemin (la ligne imprimée dans docs/examples/multi-tool-pipeline.md et l'entrée passes de docs/CAPABILITY.md le disent désormais) ; VDOP GNSS de polar-arctic-leo-coverage fourni à l'équateur 1,19669 -> 1,19710, à 89,9 deg 1,50645 -> 1,50590, VDOP fusionné à 89,9 deg 1,14388 -> 1,14250 (les chiffres publiés à deux décimales 1,20, 1,51 et 1,14 sont inchangés). Aucun fichier de référence figée (golden) ne change.
  • Pas encore routés : leo_pass, les modes doppler, joint et timing de leo-pvt et l'orbite de vérité de leo_navmsg (leurs modèles se trouvent dans leo_link::geometry et leo_fusion::geom), et les conceptions terrestres dans constellation-design (un niveau rapide à deux corps nommé).

D6, générateur de référence LunaNet AFS, LSIS V1.0 (quatre nouvelles lignes, dont deux VALIDATED : 238 -> 242 lignes, validées 121 -> 123).

  • Générateur de référence LunaNet Augmented Forward Signal (AFS) (lunar_afs), figé sur le LunaNet Signal-In-Space Recommended Standard (LSIS) V1.0 du 29 janvier 2025 et nommant cette version dans chaque sortie : la porteuse de 2492,028 MHz ; le canal de données BPSK(1) AFS-I à 500 symboles par seconde avec son code de Gold de 2046 chips ; le pilote BPSK(5) AFS-Q avec son code primaire de Weil de 10230 chips et ses codes secondaire de 4 chips et tertiaire de 1500 chips ; la trame d'identifiant 0 (motif de synchronisation, sous-trame 1 BCH (51, 8), CRC-24, sous-trames LDPC de rendement un demi 2 à 4, entrelaceur par blocs de 60 par 98) avec un décodeur exhaustif de sous-trame 1 et un décodeur LDPC min-sum écrit à partir de la seule matrice de contrôle de parité ; et une synthèse IQ en bande de base avec étiquettes de vérité écrite sous forme d'enregistrement SigMF. Les codes sont générés à partir des registres à décalage et des constructions de Legendre/Weil de la norme. Rien de ce qui est copié de la norme n'est redistribué (elle ne comporte aucune condition de réutilisation) : les indices primaires AFS-Q viennent de IS-GPS-800J, et ce que seules les pièces jointes de la norme définissent (retards G2 de l'AFS-I, codes tertiaires, sous-matrices LDPC) est lu à l'exécution depuis un cache local que xval/lunar-afs/fetch_lsis.sh remplit à partir du PDF hébergé par la NASA, chaque fichier étant vérifié face à un SHA-256 figé (lunar_afs::lsis). Le modèle est une référence de correspondance avec la norme, et non un modèle de canal, de propagation ou de bilan de liaison.
  • sigmf::meta_to_json_with_extensions et sigmf::annotation_extension_fields : un enregistrement peut porter des champs d'extension à espace de noms déclarés dans core:extensions.
  • Nouvelle ligne VALIDATED « Rendu en bande de base LunaNet AFS face à un générateur indépendant, son état de canal étant donné » : face à LANS-AFS-SIM (BSD-2-Clause, commit 480c6bf3, version bande S), zéro écart de chips sur les codes des PRN 1 à 210, zéro écart de symboles sur les trois trames de l'exécution, et une corrélation complexe normalisée de 0,999990 sur 23,9 s de ses propres échantillons (pire bloc de 2 ms 0,999948), dans des seuils fixés avant la comparaison (préenregistré 986ac280). Elle pilote le moteur de rendu avec l'état de canal propre au simulateur et ne couvre ni la répartition de puissance à partir de la densité porteuse sur bruit, ni l'écriture SigMF et 8 bits.
  • Nouvelle ligne VALIDATED « Codage de canal des trames LunaNet AFS, FID 0 » : les trames de 6000 symboles sont égales à celles de LANS-AFS-SIM symbole par symbole (préenregistré 986ac280) ; le code de la sous-trame 1 reproduit l'exemple traité de la figure 8 du LSIS et le CRC-24 la valeur de contrôle du catalogue CRC-24/LTE-A.
  • Les deux lignes promues sont conditionnées par les données du cache LSIS : leur test de référence indépendante est ignoré avec un avis tant que xval/lunar-afs/fetch_lsis.sh n'a pas été exécuté.
  • Constat (nouvelle ligne MODELLED), « Génération des codes d'étalement LunaNet AFS » : sur 2 937 232 chips et bits générés comparés aux tables de la norme et aux fichiers de l'annexe 3, un seul diffère, les « 24 derniers chips » que la table E-5 imprime pour le PRN tertiaire 147, qui duplique la cellule du PRN 151 alors que le propre fichier de l'annexe 3 de la norme concorde avec le générateur. Le critère de zéro écart n'est pas atteint.
  • Constat (nouvelle ligne MODELLED), « Décodabilité en boucle fermée de LunaNet AFS » : trois exécutions préenregistrées face à PocketSDR-AFS ; la troisième a atteint ses seuils de suivi et de décodage en totalité mais pas sa garde selon laquelle une version du récepteur qui ne fait qu'imprimer reproduit le journal de la version figée, car deux exécutions du récepteur non modifié diffèrent déjà dans leurs enregistrements d'acquisition.
  • Corrigé : la porteuse par défaut de lunar_service (export_antenna.carrier_hz), lunar_jamming et attack_surface était un 2,4 GHz arrondi ; c'est désormais la porteuse AFS du LSIS-020, 2492,028 MHz. Avec l'ancienne valeur par défaut, la perte en espace libre était sous-estimée de 0,327 dB.
  • Révisions : aucune. Chaque scénario fourni nomme sa porteuse, et les résultats des 138 fichiers de scénario sont identiques à l'octet près à ceux de la branche principale précédente.

D7, vrai IQ lunaire et LNAV GPS (sept nouvelles lignes, aucune VALIDATED : 242 -> 249 lignes, validées 123 inchangé).

  • portable_math::FftPlan : une transformée de Fourier rapide (FFT) à base mixte dont la sortie est la même, bit pour bit, sur toutes les plateformes ; un contrôle SHA-256 figé des transformées de 8000 et 24000 points passe sur x86_64 et sur wasm32-wasip1 (exécuteur dans xval/portable-fft-wasm/).

  • acquisition : recherche parallèle de phase de code sur IQ échantillonné (pcps_acquire, pcps_grid) avec repliement cohérent, accumulation non cohérente, un seuil du khi-deux pour une probabilité de fausse alarme sur toute la recherche et une statistique à moyenne par cellule pour un bruit à bande limitée ; refine, prompt_series avec Doppler de code, et les estimateurs de densité porteuse sur bruit (C/N0) M2M4 et pic de grille.

  • gps_lnav : un encodeur du message de navigation historique (LNAV) d'IS-GPS-200 pour les sous-trames 1 à 3, avec la parité du tableau 20-XIV et un décodeur de champs.

  • realdata::ion_sdr : un lecteur du ION GNSS SDR Metadata Standard (.sdrx) et de ses fichiers d'échantillons, avec to_mid_rise pour les niveaux en complément à deux.

  • realdata::lugre : l'en-tête de lot IQS, la télémétrie RAW, ACQ et NAV et les fichiers CLK de LuGRE (Lunar GNSS Receiver Experiment), et un contrôle qui liste où les métadonnées .sdrx contredisent l'en-tête binaire.

  • antenna::GainPattern2D et, dans earth_gnss_lunar, le référentiel du corps à pilotage en lacet, l'azimut d'émission et les angles hors nadir, et transmit_side_db pour le C/N0 relatif avec des diagrammes mesurés.

  • Encodage du message de navigation GPS LNAV (nouvelle ligne, reste MODELLED après la vérification a posteriori de l'intégrateur) : sur le fichier de diffusion IGS du 2 mars 2025, analysé et décodé par RTKLIB v2.4.2-p13, les 960 mots passent la parité, les 96 sous-trames se décodent et les 608 entiers diffusés sont égaux à ceux de Kshana (tests/gps_lnav_rtklib_integer_oracle.rs), mais le préenregistrement (d4d9eb9d) a atteint la branche publique deux secondes après le commit contenant le résultat, de sorte que l'ordre « enregistré avant la récupération du fichier » ne peut pas être démontré et que la ligne n'est pas promue.

  • realdata::ion_sdr remplit les mots à partir du bit de poids fort (I dans le quartet haut d'un octet LuGRE ; la lecture précédente produisait le signal conjugué), conserve l'ancienne lecture sous le nom SdrLayout::fill_lsb_first, et lit des échantillons plus larges qu'un mot.

  • acquisition::refine_doppler_coherent : affinage Doppler cohérent en phase (0,2 Hz de RMS à 30 dB-Hz sur 200 ms en simulation).

  • GPS L1 C/A face à gps-sdr-sim : chips et parité exacts au bit près ; 230 des 1152 champs LNAV diffèrent d'une unité parce que gps-sdr-sim tronque là où l'entier diffusé exige un arrondi.

  • LNAV décodé par RTKLIB : toute la parité et toutes les sous-trames passent et chaque paramètre est à moins d'un demi-quantum ; 41 valeurs mises à l'échelle diffèrent de quelques unités sur le dernier chiffre à cause de la constante décimale 2^-43 de RTKLIB, au-dessus du seuil enregistré.

  • Acquisition LuGRE face à GNSS-SDR 0.0.19 : 266 décisions sur 266 concordent, 250 situées sur la même cellule ; la plupart des positifs sont des artefacts d'une moyenne de −0,5 dans les niveaux bruts sur 4 bits ; la branche du C/N0 n'avait pas de données de vol contemporaines. Deux lots (OP5, OP12) ont été exclus à tort : leurs métadonnées concordent avec leurs en-têtes, mais le lecteur ne pouvait alors pas lire un échantillon plus large qu'un mot.

  • Acquisition LuGRE face au Doppler prédit par l'orbite : avec la décision sur la puissance des échantillons, chaque recherche franchit le seuil sur du bruit à bande limitée ; avec la décision à moyenne par cellule, les paires les plus fortes concordent en grandeur avec le signe inversé, ce qui montre que l'ordre I/Q enregistré est le conjugué de celui des données.

  • Acquisition à l'aveugle sur les lots de surface lunaire : quatre lots acquièrent chacun un satellite (prédit visible, aucune fausse alarme à 1e-7), aucun deux, de sorte que le seuil sur la différence de Doppler n'a aucune paire à évaluer.

  • C/N0 relatif à distance lunaire (M039 reformulée) : 15 enregistrements de Block IIR/IIR-M et une paire, trop peu pour le seuil enregistré.

  • Révisions : aucune ; aucun chiffre publié, fichier de référence figée (golden) ni figure de la documentation n'a changé.

  • La ligne M039 « GNSS terrestre à distance lunaire » reformule son affirmation à distance lunaire comme le C/N0 relatif entre satellites à une même époque plus la visibilité (le C/N0 absolu n'est pas revendiqué) ; elle reste MODELLED. Le NOTICE de premier niveau porte l'attribution CC BY 4,0 de LuGRE.

Corrigé#

  • L'orientation lunaire des axes principaux DE440 est désormais interpolée le long de la géodésique entre nœuds quotidiens. L'ancienne interpolation élément par élément était erronée jusqu'à 2.0e-4 rad (340 m à la surface lunaire) près des quarts de chaque jour, et non « environ 14 m » comme l'indiquait la ligne. Ses utilisateurs (géométrie de télémétrie laser lunaire, datum lunaire, observabilité des failles lunaires) obtiennent l'orientation corrigée.
  • Corrections moteur du tour 2, chacune réexécutée face à sa tolérance préenregistrée inchangée : le millésime IERS d'une ligne EOP est lu dans ses indicateurs I/P plutôt que dans un bloc Bulletin B vide ; snapshot_raim utilise le plan local géodésique ; le couplage taux-référentiel lunaire utilise le rayon équatorial, J2 et la rotation ; l'ajustement liu22 démarre à zéro correction sans a priori et utilise le taux de mouvement moyen de l'article ; l'espacement des nœuds EO porte la régression nodale J2 ; le temps de glissement de cycle de Costas utilise rho/4 ; la position conjointe applique le délai de groupe diffusé de la paire ; la résolution conjointe lunaire utilise un pas QR ; la borne NTN est évaluée à la vraie position ; l'horloge de référence de la conception de constellation est la plus petite constellation en vue ; la série d'orientation DE440 couvre 2014-2030 et signale une erreur en dehors au lieu de borner.

Ajouté#

  • leo_navmsg::truth::TruthOrbit::from_ecef_states, une orbite de vérité construite à partir d'états tabulés dans le référentiel terrestre, utilisée par la comparaison d'ajusteur sur orbite réelle.
  • Les fichiers de test et jeux de test des comparaisons ci-dessus, chacun avec son générateur et un NOTICE.md indiquant la source, la licence, la date de récupération et le SHA-256.
  • Tour 2 : araim_reference::add_v42_protection_levels et _ecef (détection de défaut ADD v4.2, d'après Stanford MAAST pour l'ARAIM 2, mention BSD-3 dans la source) ; raim::snapshot_raim_fde ; cw_dynamics::second_order_correction et propagate_second_order ; le modèle d'erreur INS à neuf états inertial::coast::ErrorDynamics ; dérivées partielles de lunar_vlbi::KernelGeometry et entrées lunar-vlbi du chemin par noyau ; naif_kernel, un lecteur de noyaux SPK de type 2 et PCK binaires ; lunar_llr_geometry::llr_bcrs_one_way_m avec stations ITRF2020 ; densité de Jacchia 1971 ; solar_system::link_on sur tout fournisseur d'éphémérides ; launch::site_rotation_speed_at ; eo_payload::j2_nodal_period et ground_track_spacing_equator_j2 ; batch_ls::gauss_newton_qr ; precise_products (lecteurs RINEX clock, ANTEX et DCB).

[0.29.3] - 2026-10-01#

Une version corrective sur 0.29.2. Kshana Studio est reconstruit autour de deux vues : une vue Simple qui donne d'abord la réponse et l'explique en termes courants, et une vue Avancée avec le tableau de bord complet. Deux petites corrections sur kshana.dev l'accompagnent. Le moteur ne change pas : chaque scénario fourni donne un résultat identique octet pour octet à 0.29.2, à la marque de version près.

Modifié#

  • Kshana Studio a une vue Simple. C'est celle sur laquelle le Studio s'ouvre.
    • La réponse vient d'abord : un scénario s'ouvre sur son résultat, énoncé en une phrase simple. Chaque scénario fourni a sa propre phrase, écrite pour ce que ce scénario mesure.
    • Cinq réglages au plus sont affichés, ceux qui changent le plus la réponse. Les autres sont sous « Réglages avancés », repliés jusqu'à ce que vous les ouvriez.
    • « Comment c'est calculé » explique la méthode en quelques lignes, et « Pour les chercheurs » donne les chiffres propres au moteur, le fichier du scénario et les preuves derrière le résultat.
  • Le tableau de bord complet est la vue Avancée. Chaque panneau, graphique, export et rapport du Studio précédent s'y trouve.
  • Un commutateur passe d'une vue à l'autre et garde votre position. Le scénario, la vue où vous étiez et les réglages que vous avez modifiés sont conservés. Le Studio se souvient de la dernière vue utilisée. Les liens du site et de la documentation ouvrent la vue Simple ; un lien avec view=advanced ouvre la vue Avancée, et chaque lien Studio antérieur ouvre toujours le même scénario et la même vue.
  • Une première vue plus rapide sur les connexions lentes. La réponse enregistrée d'un scénario est affichée avant le chargement du reste du Studio ; sur une connexion mobile lente, la réponse apparaît en environ deux secondes au lieu d'environ neuf.
  • Une meilleure recherche. Une recherche liste désormais en premier les scénarios dont le domaine ou le titre correspond aux mots, avant les scénarios qui ne les mentionnent que dans le nom du fichier ou dans le texte.

Corrigé#

  • Le globe de la page d'accueil ne devient plus vide quand la réduction des animations est activée. Lorsque le réglage système de réduction des animations était activé, le redimensionnement de la fenêtre pouvait laisser le globe principal vide jusqu'au défilement de la page. Le globe se redessine maintenant dans la même image que le redimensionnement.
  • La console en bande L de la page d'accueil explique sa bande vide. Dans « Watch a jammer take the band », le panneau GPS L5 / Galileo E5a restait sombre pendant toute la minute, ce qui pouvait passer pour une panne. Aucun brouilleur n'émet dans cette bande dans ce scénario, et les signaux des satellites sont sous le plancher de bruit : rien n'y dépasse donc ce plancher. Une étiquette discrète l'indique maintenant dans tout tronçon de panneau où rien n'est au-dessus du plancher (le panneau L5 / E5a, et le panneau L2C avant le démarrage de son brouilleur de bruit), avec le C/N0 et l'état d'accrochage de chaque bande issus de la même exécution. Elle n'est placée que là où rien n'est au-dessus du plancher, si bien qu'elle ne recouvre jamais l'énergie d'un brouilleur.

0.29.2 - 2026-10-01#

Une version corrective sur 0.29.1. Elle supprime du code dupliqué dans les modules de message de navigation, de fusion et de spectre LEO, ajoute un thème clair à kshana.dev, déplace Kshana Studio à sa propre adresse, rend le site lisible par les moteurs de recherche et les assistants d'IA, corrige plusieurs petits défauts dans le Studio, et permet aux publications npm de se faire sans jeton stocké. Aucune sortie du moteur ne change : chaque scénario fourni donne un résultat identique octet pour octet à 0.29.1, à la marque de version près.

Ajouté#

  • Un thème clair pour kshana.dev. Chaque page peut être lue en clair ou en sombre. Le site suit le réglage système du lecteur et propose un commutateur pour le changer.
  • Les moteurs de recherche et les assistants d'IA peuvent lire le site. Chaque page a maintenant son propre titre, sa description, son adresse canonique, ses balises de carte sociale et des données structurées schema.org, ainsi qu'un texte brut pour les sections qu'un script dessine. Le site publie robots.txt, un sitemap.xml avec la date du dernier changement de chaque page, llms.txt et llms-full.txt (un guide en texte brut, court et complet, pour les assistants d'IA), et une clé IndexNow pour qu'un déploiement puisse indiquer aux moteurs de recherche ce qui a changé.
  • Les publications npm peuvent se faire sans jeton stocké. La tâche npm exécute maintenant Node 24 et npm 11.5.1 ou plus récent, qui prennent en charge la publication de confiance npm : npm échange l'identité GitHub de la tâche de publication contre un identifiant de courte durée. Le secret NPM_TOKEN fonctionne toujours et est utilisé tant qu'il est défini ; rien ne change donc tant que la publication de confiance n'est pas activée pour le paquet sur npmjs.com. docs/RELEASING.md énumère les étapes.

Modifié#

  • Le titre de la page d'accueil est lisible sur le globe. Un voile doux se place maintenant derrière le titre et son texte, estompant les lignes d'orbite et les points de satellites du globe animé là où ils le croisent.

  • Kshana Studio a sa propre adresse : https://kshana.dev/studio/. Chaque lien du site et de la documentation y mène. L'ancienne adresse, /playground/, fonctionne toujours et redirige vers la nouvelle en conservant le scénario, la vue et les autres réglages du lien.

  • Corrections du Studio. Le fichier du moteur est téléchargé une fois au lieu de deux. Pendant son téléchargement, le Studio affiche aussitôt le résultat enregistré du scénario, indiqué comme enregistré, au lieu d'un écran vide. Sur un téléphone, l'en-tête tient sur une seule rangée compacte. Les chiffres clés passent à la ligne deux par deux, de sorte qu'aucun n'est caché hors de l'écran. Les libellés de champs utilisent les mots propres du scénario, avec le nom du champ à côté, et la recherche trouve les champs par l'un ou l'autre.

  • Moins de code dupliqué. Le tableau des unités du message de navigation LEO écrivait les mêmes dix lignes de statistiques SISRE pour quatre synthèses d'ajustement. Une macro les écrit maintenant une seule fois. Les deux graphiques en cascade du spectre partagent un même axe du temps, une même barre de couleur et un même panneau de barre C/N0. Le sous-échantillonnage de la grille principale réutilise downsample_grid, et l'intégrale de Simpson réutilise navsignal::simpson. Les deux points d'entrée du type de scénario de passage LEO partagent une même étape de préparation. leo_link::geometry importe les fonctions d'aide vectorielles de leo_fusion::geom au lieu de les copier. Le rapport avancé importe l'échappement HTML du rapport de l'API au lieu de le copier. Chacun des 139 fichiers de scénario de scenarios/ a été exécuté sur 0.29.1 et sur ce code, et chaque fichier de sortie est identique octet pour octet.

  • Les tableaux d'unités de leo-navmsg et de leo-pvt ont leurs propres fichiers. Ils sont sortis de modules qui contiennent aussi de la logique, vers src/leo_navmsg/units.rs et src/leo_fusion/pvt_units.rs. PVT_UNITS garde son chemin public. Seuls ces deux fichiers de tableaux rejoignent les exemptions de détection de copier-coller pour les catalogues déclaratifs dans sonar-project.properties, que tests/sonar_cpd_exclusions_are_justified.rs vérifie.

Corrigé#

  • Le badge CI du README montre le résultat des pushes sur main. Le badge comptait les exécutions de tous les événements sur main, si bien qu'il pouvait afficher « failing » alors que chaque exécution de push était verte ; il ne demande maintenant que les exécutions de push (event=push).

0.29.1 - 2026-10-01#

Une version corrective sur 0.29.0 : le chiffre de couverture mesuré, la ligne du nom du projet sur kshana.dev, une tâche de couverture plus rapide et un README remis à jour. Aucune sortie du moteur ne change : chaque scénario donne le même résultat que sur 0.29.0.

Révisions de chiffres publiés#

  • Couverture de lignes : ~96 % → ~95 %. La tâche de couverture a mesuré à nouveau le code publié 0.29.0 (commit db796dd, exécution CI 36809850252, 2026-10-01) : 95.35 %, 55 970 lignes sur 58 697 dans src/. Le chiffre publié était 95,63 % (37 697 lignes sur 39 419), mesuré sur b1d350d avant 0.28.0 ; il s'arrondissait à ~96 %. Le nouveau chiffre s'arrondit à ~95 %, de sorte que chaque surface que tests/coverage_figure_doc_sync.rs épingle bouge ensemble : docs/COVERAGE.md, le badge du README, la ligne Evidence et le tableau CI, les badges crates.io, PyPI et npm, le rapport technique et la page de couverture de kshana.dev. Le plancher de 85 % est inchangé.

Ajouté#

  • La ligne du nom sur kshana.dev. « Kshana · क्षण · the precise instant » ouvre maintenant le bandeau d'accueil et figure sous la marque dans le pied de page de chaque page. kshana.dev ne fait toujours aucune requête vers un autre hôte : le devanagari est un sous-ensemble auto-hébergé de Noto Sans Devanagari pour les trois lettres de क्षण (1 692 octets, web/fonts/, avec le texte de sa licence SIL Open Font License et son SHA-256 dans web/fonts/FONTS.json). web/tools/fetch_third_party.py a appris à enregistrer un sous-ensemble Google Fonts text= sous un nom de fichier adressé par son contenu.

Modifié#

  • Les liens du site arrivent là où ils pointent, à des adresses propres. Un lien vers une section place maintenant cette section juste sous l'en-tête, sur un téléphone comme sur un ordinateur : un lien vers un secteur de Missions ouvre ce secteur avec son panneau en haut ; les liens de Capabilities et d'Editions gardent leur place pendant que les graphiques au-dessus se dessinent ; Editions n'ajoute plus un second décalage d'en-tête ; et un lien vers une partie repliée d'une page de documentation l'ouvre. Chaque page est liée par son adresse propre (/evidence#research, /docs/changelog, / pour l'accueil), et les liens canoniques, le plan du site et les redirections des anciennes adresses nomment les mêmes ; les adresses .html fonctionnent toujours. Research a son propre lien dans l'en-tête, entre Evidence et Developers, et dans le pied de page. La documentation ne montre plus la feuille de route (ROADMAP.md reste dans le dépôt) : le groupe Project est Changelog, Licensing, Security, Contributing, Governance et Code of conduct, et le Glossary est passé dans Get started.
  • La tâche de couverture est plus rapide. Sur 0.29.0, elle a pris 143 minutes contre des 91 normales, à
    1. Le fuzzer tests/property.rs, la cause la dernière fois, en a pris 4. Le corpus fourni est passé de 74 à 139 scénarios, et trois binaires de test le parcouraient en entier, un fichier à la fois (determinism deux fois, advanced_report et animation une fois) : 37 minutes ensemble sous instrumentation de couverture, contre 3 sur 0.27.2. Ils partagent maintenant tests/support/corpus.rs, qui exécute le travail de chaque scénario sur tous les cœurs et rend les résultats dans l'ordre trié ; chaque scénario et chaque assertion subsistent. Sur un portable arm64, en build de débogage : determinism prend 143 s sur 14 cœurs contre 612 s avec KSHANA_CORPUS_THREADS=1 (l'ancien parcours en série).
  • Le README, remis à jour. Il s'ouvre sur la même ligne de nom que le site ; les captures d'écran du Studio sont refaites à partir du Studio 0.29.1, avec une nouvelle du Studio sur un téléphone et de sa barre d'étapes du bas ; une nouvelle bande « The site » montre trois pages de kshana.dev issues du build 0.29.1 (tools/capture_site_shots.mjs, composées par tools/readme_shots.py et consignées dans docs/assets/readme/site/SHOTS.json) ; le chiffre de couverture indique ~95 % ; et le texte alternatif de la figure de recherche, qui répétait celui de la figure d'architecture, décrit maintenant les articles. Les badges de l'en-tête sont plus petits et plus courts (18 px de haut ; « ~95% », « 83/223 », « quality », « AGPL-3.0 », « zenodo.20528627 »), si bien que les onze tiennent sur deux lignes ; chaque lien et chaque texte alternatif gardent tout leur sens.
  • La tâche de l'image de conteneur dispose de 90 minutes. À v0.29.0, la construction linux/arm64 émulée de l'image kshana-mcp a atteint l'ancienne limite de 45 minutes pendant la compilation de son dernier crate, si bien que l'image, l'entrée du registre MCP et la vérification du canal n'ont pas été publiées. La limite est maintenant de 90 minutes ; l'image est inchangée.
  • Huit littéraux flottants regroupés autrement dans src/ephem.rs et src/sgp4.rs (0.323_273_64 → 0.323_273_640) : SonarQube Cloud lisait un dernier groupe de _64 ou _32 comme un suffixe f64 ou f32 manquant (règle S7454). Les valeurs sont les mêmes nombres, de sorte que chaque résultat est inchangé.

0.29.0 - 2026-10-01#

Douze nouveaux types de scénario et trois nouvelles façons de lire une exécution. Le moteur couvre maintenant le spectre radioélectrique, tout le système solaire, des constellations autour de n'importe quel corps, des campagnes qui enchaînent des scénarios en une seule mission, et le positionnement, la navigation et synchronisation temporelle (PNT) depuis l'orbite terrestre basse (LEO), du signal jusqu'au point. Chaque exécution peut aussi être écrite sous forme d'animation, de rapport complet et d'un ensemble de fichiers d'interopérabilité pour d'autres outils.

Autour du moteur : un kshana.dev repensé (un site à plusieurs pages, et un nouveau tableau de bord Kshana Studio qui exécute chaque capacité dans le navigateur), un README réécrit, quatorze outils sur le serveur du Model Context Protocol (MCP), une version pour navigateur qui donne les mêmes nombres que la version native, et une page publique pour Kshana Pro.

0.28.0 0.29.0
Types de scénario 63 75
Fichiers de scénario (plus un manifeste de suite) 77 138, dont 132 sont fournis pour kshana example
Lignes de la matrice de vérification 174 223
dont VALIDATED face à une référence externe 66 83
dont MODELLED (modèle énoncé, vérifié pour sa cohérence interne) 104 136
dont PARTNER (nécessite le matériel ou les données d'un partenaire) 4 4

D'où vient la croissance :

Domaine Types Fichiers de scénario Lignes de la matrice (vérifiées + modélisées)
Spectre 1 1 3 (1 + 2)
Système solaire et positionnement autour de n'importe quel corps 2 3 6 (2 + 4)
Conception de constellation 1 3 3 (2 + 1)
Campagnes 1 5 3 (0 + 3)
Scénarios maritimes, routiers et ferroviaires 0 5 0
Animation, rapports, exports d'interopérabilité 0 0 0
Conceptions de signaux LEO et spectre multibande 1 4 4 (2 + 2)
Passage LEO et bilan de liaison 1 6 9 (6 + 3)
Message de navigation LEO 1 5 9 (3 + 6)
Positionnement, synchronisation temporelle et fusion LEO 3 8 8 (1 + 7)
Chaîne de bout en bout LEO 1 3 1 (0 + 1)
Scénarios LEO de résilience, de domaine ciblé et d'utilisateur final 0 18 3 (0 + 3)
Total ajouté 12 61 49 (17 + 32)

La capacité LEO est indépendante de tout système : elle s'exécute sur des paramètres génériques et énoncés et n'a besoin d'aucun système nommé. Les systèmes nommés sont des préréglages facultatifs, chacun dans son propre fichier avec sa source publique. Un préréglage, Celeste IOD (démonstration en orbite), utilise des chiffres présentés à l'atelier LEO-PNT de l'ESA NAVISP, 2026 (l'ESA est l'Agence spatiale européenne ; NAVISP est son Programme d'innovation et de soutien à la navigation) ; il se trouve dans un seul fichier, src/celeste_iod.rs, avec ses cinq scénarios réservés au dépôt, de sorte qu'il peut être retenu sans modification de source, et aucun de ses chiffres d'atelier n'est repris dans ce journal des modifications.

Lisez « Révisions de chiffres publiés » avant de mettre à jour. Une sortie du moteur change (les colonnes du référentiel inertiel du type de scénario ephemeris, après une correction de signe dans la matrice de nutation), et l'audit de la documentation a corrigé des chiffres que des documents antérieurs avaient imprimés.

Abréviations utilisées dans cette entrée

Statuts : VALIDATED signifie vérifié par rapport à une référence externe indépendante (une table publiée, le logiciel d'un autre groupe ou des données mesurées) ; MODELLED signifie un modèle énoncé vérifié uniquement pour sa cohérence interne ; PARTNER signifie que la vérification nécessite le matériel ou les données d'un partenaire.

Abréviation Signification
3GPP, 5G, NTN 3rd Generation Partnership Project ; réseau mobile de cinquième génération ; réseau non terrestre
AD, BC ères du calendrier (anno Domini, avant Jésus-Christ)
AIAA American Institute of Aeronautics and Astronautics
AltBOC, BOC, BPSK, MBOC porteuse à décalage binaire alternative ; porteuse à décalage binaire ; modulation par déplacement de phase binaire ; porteuse à décalage binaire multiplexée (modulations de signal)
ATOMIC Autonomous Time and Orbit Determination for Microsatellite Constellations (un modèle d'éphéméride LEO publié)
C/A, L1, L2, L2C, L5 code grossier/d'acquisition et noms des porteuses et des signaux civils du Global Positioning System
C/N0 rapport densité de puissance de porteuse sur bruit
CIO Celestial Intermediate Origin (origine intermédiaire céleste)
CLI interface en ligne de commande
CRC-24Q contrôle de redondance cyclique sur 24 bits (polynôme Qualcomm)
CSAC horloge atomique à l'échelle de la puce
CSS, HTML, SVG, XML Cascading Style Sheets ; HyperText Markup Language ; Scalable Vector Graphics ; Extensible Markup Language
CSV, JSON, PDF, TOML, URL valeurs séparées par des virgules ; JavaScript Object Notation ; Portable Document Format ; Tom's Obvious Minimal Language ; adresse web (uniform resource locator)
CW onde continue
CZML, KML, GeoJSON Cesium Language ; Keyhole Markup Language ; Geographic JSON (formats de cartes et de globes)
DE441 Development Ephemeris 441 du Jet Propulsion Laboratory
DOI identifiant d'objet numérique
DOP, GDOP, PDOP, HDOP, VDOP dilution de précision : géométrique, en position, horizontale, verticale
E1, E5, E5a, E5b noms de signaux Galileo
E3F un nom d'emplacement dans la table de constellation du Global Positioning System
ECEF centré sur la Terre et fixe par rapport à elle
EE équation des équinoxes
EGM2008 Earth Gravitational Model 2008
EIRP puissance isotrope rayonnée équivalente
ERFA, SOFA Essential Routines for Fundamental Astronomy ; Standards of Fundamental Astronomy (bibliothèques d'astronomie de référence)
ESA, NAVISP Agence spatiale européenne ; son Programme d'innovation et de soutien à la navigation
FDMA accès multiple par répartition en fréquence
GCRF, GCRS Geocentric Celestial Reference Frame (référentiel céleste géocentrique) ; Geocentric Celestial Reference System (système de référence céleste géocentrique)
GLONASS le système mondial de navigation par satellite de la Russie
GNSS, GPS système mondial de navigation par satellite ; Global Positioning System
IAU Union astronomique internationale
ICD, OS SIS ICD, OS SDD document de contrôle d'interface ; Galileo Open Service Signal-In-Space Interface Control Document ; Galileo Open Service Service Definition Document
ICRF International Celestial Reference Frame (référentiel céleste international)
IMO Organisation maritime internationale
INS, MEMS système de navigation inertielle ; système micro-électromécanique
IOD démonstration en orbite
IQ en phase et en quadrature
IS-GPS-200 la spécification d'interface du Global Positioning System
ISS Station spatiale internationale
ITRF, ITRS, PEF, TEME International Terrestrial Reference Frame (référentiel terrestre international) ; International Terrestrial Reference System (système de référence terrestre international) ; pseudo-fixe par rapport à la Terre ; équateur vrai, équinoxe moyen (référentiels)
ITU, ITU-R Union internationale des télécommunications ; son Secteur des radiocommunications
J/S rapport brouilleur sur signal
J2 à J6, J2000 harmoniques zonales du champ de gravité ; l'époque 2000-01-01 12 :00
JPL Jet Propulsion Laboratory
LEO, MEO orbite terrestre basse ; orbite terrestre moyenne
MBSE ingénierie des systèmes fondée sur les modèles
NEES erreur d'estimation normalisée au carré
NeQuick-G le modèle d'ionosphère de Galileo
OEM, SP3, TLE Orbit Ephemeris Message ; Standard Product 3 (orbites précises) ; jeu d'éléments à deux lignes
PNT, PPP positionnement, navigation et synchronisation temporelle ; positionnement précis par point
PSD, SSC densité spectrale de puissance ; coefficient de séparation spectrale
RAIM, SQM surveillance autonome de l'intégrité par le récepteur ; surveillance de la qualité du signal
RINEX, RTCM Receiver Independent Exchange Format ; Radio Technical Commission for Maritime Services
RMS valeur efficace (racine de la moyenne des carrés)
RTKLIB une bibliothèque libre de positionnement GNSS, utilisée ici comme référence indépendante
SGP4 Simplified General Perturbations 4 (le modèle d'orbite des jeux d'éléments à deux lignes)
SHA-256 Secure Hash Algorithm, 256 bits
SigMF Signal Metadata Format
SISRE erreur de distance du signal dans l'espace
SPS PS Standard Positioning Service Performance Standard
SRTM Shuttle Radar Topography Mission
STK Systems Tool Kit (son format de fichier d'éphéméride .e)
STL Satellite Time and Location
SVID identifiant de véhicule spatial
T/P/F le nombre total de satellites, de plans et le phasage d'une constellation Walker
TEC contenu électronique total
UHF ultra haute fréquence
UTC temps universel coordonné
WGS 84 World Geodetic System 1984
X1, X5 noms de signaux du système Xona Pulsar

Révisions de chiffres publiés#

Un chiffre publié qui change est une révision et est consigné, jamais corrigé en silence. Cette version comporte une révision d'une sortie du moteur et plusieurs révisions de chiffres imprimés dans la documentation.

Sortie du moteur

  • La réduction TEME→GCRS tournait de 2·Δψ : la matrice de nutation avait le signe de Δψ inversé. nutation::numat construisait Rx(−(ε̄+Δε))·Rz(Δψ)·Rx(ε̄) là où le iauNumat de SOFA construit Rx(−(ε̄+Δε))·Rz(−Δψ)·Rx(ε̄), de sorte que nutation_matrix, nutation_matrix_2000a, teme_to_gcrs et gcrs_to_teme tournaient du double de la nutation en longitude, environ 25 secondes d'arc. Chaque vérification de la chaîne était un test de propriété (rotation propre, aller-retour, contribution de nutation non nulle) qu'une erreur de signe laisse passer ; le test de bout en bout de Vallado couvrait TEME→PEF, TEME→ITRF et GCRS→ITRS, mais pas TEME→GCRS. Sur l'exemple de Vallado (AIAA 2006-6753, 2004-04-06), la chaîne manquait le GCRF publié de 1 145 m ; elle tombe maintenant à 0,11 m de lui, et la matrice est égale au numat d'ERFA à 1e-14 près. tests/frame_reference_vectors.rs::teme_to_gcrs_matches_vallado_gcrf et nutation::tests::nutation_matrix_matches_erfa_numat échouent tous deux avec l'ancien signe. Le test de cohérence du CIO (Celestial Intermediate Origin) dans src/cio.rs avait attribué le désaccord résultant d'environ ~130 m à « ≈ 2·EE » ; le résidu est maintenant de 5 cm et sa borne est resserrée de 250 m à 1 m. Cela déplace des chiffres publiés, consignés ici comme une révision : les colonnes gcrs_r_m et gcrs_v_m_s du type de scénario ephemeris (environ 0,8–1,0 km pour le scénario ISS (Station spatiale internationale) fourni ; ses colonnes TEME, référentiel terrestre, trace au sol, angles de visée et Doppler ne changent pas), et Propagator::position_in_frame / state_gcrs pour les référentiels GCRS et ITRS. Aucune ligne de synthèse, aucun graphique ni aucun hachage de référence d'un scénario fourni ne lit ces colonnes. Les nouveaux exports d'interopérabilité utilisent la chaîne corrigée : la position CZML du premier satellite orbit-sgp4-gps concorde avec une réduction ERFA du même TLE (propagé par le paquet Python sgp4) à 2,3 cm près.
  • Le type de scénario leo-navmsg, en natif et dans la version pour navigateur. Le type de scénario calcule désormais chaque fonction transcendante par une seule bibliothèque mathématique portable, de sorte que sa trame a les mêmes octets sur toutes les plateformes et dans toutes les versions (sous Fixed). Chaque chiffre de leo-navmsg bouge avec lui, ainsi que l'étape navmsg de leo-pnt-chain. Le type de scénario est nouveau dans cette version, donc rien d'une version antérieure ne bouge, mais des chiffres imprimés avant la correction bougent : la valeur de contrôle de docs/LEO-NAVMSG.md pour le scénario d'encodage et de décodage était 0x110315 et est 0x19105F, et son SISRE du message décodé est de 0,129 cm. Sur kshana.dev, la carte Missions de leo-navmsg-fit-interval-trade montrait une erreur de distance maximale de 1,6 mm avec un ajustement de 60 s et 40,3 mm avec un ajustement de 900 s ; le site est maintenant construit à partir du moteur de cette version et montre 1,8 mm et 46,6 mm.
  • La carte de l'empreinte de brouillage sur kshana.dev (Missions). Chacune de ses 875 cellules est une exécution de maritime-strait-jamming où seule la position du récepteur change. Les cellules sont maintenant calculées à partir des mêmes coordonnées à trois décimales que le lien « open this run » de la cellule donne à Kshana Studio, de sorte qu'une cellule montre exactement ce que son lien reproduit. Le rapport brouilleur sur signal (J/S) moyen de 30 cellules bouge de 0,1 dB, à la hausse ou à la baisse ; la disponibilité de poursuite d'aucune cellule ne change. Le moteur donne des résultats identiques pour chaque cellule dans 0.28.0 et 0.29.0.
  • Rééchantillonnage à graine fixe dans le paquet WebAssembly (WASM). La version pour navigateur tirait d'autres indices de bootstrap et de brassage que la version native à partir de la même graine (sous Fixed). L'intervalle quantum-anomaly-detect de l'aire sous la courbe dans le navigateur était [0.9901265, 0.9938305] et est maintenant l'intervalle natif [0.99035875, 0.993861]. Aucun nombre natif ne bouge.

Chiffres imprimés dans la documentation

La documentation a été auditée mot à mot par rapport à des exécutions du moteur de cette version. Lorsqu'un chiffre imprimé ne correspondait pas à l'exécution, le document a été corrigé, et chaque correction est listée ici, ancien → nouveau. Dans chacun des cas ci-dessous, la sortie du moteur n'a pas changé ; c'est le document qui l'avait mal lue, mal arrondie ou qui lui avait survécu.

  • Audit de la documentation des pages sur le spectre, les constellations, les campagnes, l'animation, les rapports et l'interopérabilité, et un nouveau docs/SOLAR-SYSTEM.md. Chaque chiffre a été réexécuté avec ce moteur. Deux nombres publiés bougent : docs/CONSTELLATION-DESIGN.md donnait le test de couverture à 5 000 satellites comme « environ 0,13 s en build de débogage » ; cela ne s'est pas reproduit (1,24 s sur un portable chargé), de sorte que la page donne maintenant la part du préfiltre que le test affiche (9,9 % de 19 440 000 tests de paires) et les 0,14 s du binaire de publication pour le leo-pnt-mega-shell fourni. La même page donnait le franchissement de E3F comme « décalé de 0,050 deg » ; aucun test n'affiche ce chiffre, de sorte que la page n'énonce plus que le seuil de 0,06 deg que le test impose et la dérivation 7,30 contre 7,36 deg qui le sous-tend. Aucune sortie du moteur ne change.
  • Documents LEO-PNT : chiffres publiés révisés (réexécutés sur le moteur de cette version). Arbitrage de bandes dans docs/LEO-SIGNAL.md : le retard ionosphérique au premier ordre de generic-s est de 3,24 m (imprimé 3,25 m) et celui de generic-c-wide de 0,77 m (imprimé 0,78 m). Encodage et décodage dans docs/LEO-NAVMSG.md : le SISRE du message décodé était imprimé à 0,119 cm alors que l'exécution donnait 0,122 cm ; la page imprime maintenant 0,129 cm, le chiffre après la correction d'indépendance de plateforme sous Fixed plus bas. Passage LEO contre GNSS dans docs/LEO-PASS.md : 32 dB de perte en espace libre en moins au sommet du passage (imprimé « 26 à 32 dB »). Pour les chiffres de signal et de passage, la sortie du moteur n'a pas changé ; les documents l'avaient mal lue ou mal arrondie.
  • Les tutoriels, l'exemple de chaîne de traitement et la commande /kshana-run, audités par rapport au moteur de cette version. Révisions de chiffres publiés, ancien → nouveau : les types de scénario qui écrivent <scenario>.table.csv sont six, et non quatre (leo-navmsg et telecom-timing manquaient ; docs/tutorials/README.md, commands/kshana-run.md) ; le franchissement ½bT² à atomes froids du tutoriel 3 est de 18 443 s, et non de 18 440 s ; l'erreur d'aller-retour de oem-interop dans docs/examples/multi-tool-pipeline.md est de 4.88e-7 km mesurés, et non « ~1e-7 km » ; la plage de holdover de la CSAC du tutoriel 2 est celle de 2000–3200 s que le test affirme, et non « ~2600–4400 s » ; le tutoriel 1 cite les lignes SP3 et le bloc de géométrie à la précision où le moteur les écrit. Aucune sortie du moteur n'a changé.
  • Pages de validation, quantique, SGP4, animation, affirmations et intégrité. docs/VALIDATION.md : le seuil imposé sur l'écart-type d'Allan simulé à une seconde d'une horloge à bruit blanc de fréquence est de 20 % (imprimé 25 % ; le seuil de 25 % est celui de la courbe à 1, 10 et 100 s) ; la ligne de la marche aléatoire de vitesse énonce maintenant son seuil imposé de 20 % à côté des environ 12 % observés ; et la disponibilité de l'horloge atomique à l'échelle d'une puce dans orbit-gnss-challenged est d'environ 0,73 (imprimée environ 0,83). docs/QUANTUM.md : le bruit par tir limité par les vibrations dans l'exemple d'atomes froids de la page est d'environ 46 fois son plancher de bruit de grenaille (« ~45× » ; 46,49 recalculé), et la plage « 1–50 µg/√Hz » pour les dispositifs déployés, qui contredisait un dispositif que la page cite elle-même, est remplacée par les chiffres publiés des deux dispositifs cités. docs/SGP4-VALIDATION.md : l'écart de position le plus grand est de 4,12 mm (imprimé « ≈ 4 mm »), avec le satellite nommé. docs/ANIMATION.md : l'exemple de l'encodeur vidéo lisait les images à 24 images par seconde à 12 ; il utilise maintenant 24, la cadence que le manifeste des images indique. docs/CLAIMS-VS-REALITY.md : le modèle de brouillage a 10 tests (imprimé 8), et le « 2,97 m contre 48,8 m » du filtre couplé est remplacé par ce que son test affirme (l'erreur de position couplée sous 0,6 fois la découplée, gagnante dans au moins 90 essais sur 100). docs/INTEGRITY.md : la marque « Today » indiquait v0.22.0 ; elle nomme maintenant cette version, et deux capacités construites depuis (le mode de panne à l'échelle de la constellation et le message d'appui à l'intégrité) quittent sa liste de lacunes.

Ajouté#

Spectre

  • Type de scénario spectrum : un modèle de spectre en bande L et une cascade (src/spectrum.rs, src/sigmf.rs, docs/SPECTRUM.md). Toute la bande L du GNSS comme une seule densité spectrale de puissance (PSD) : GPS L1 code grossier/d'acquisition (C/A) et L2 civil (L2C) (BPSK(1)), Galileo E1 (porteuse à décalage binaire multiplexée, MBOC(6,1,1/11), ou BOC(1 1)), GPS L5 et Galileo E5a (BPSK(10)), un plancher de bruit kT avec un facteur de bruit de récepteur, et des brouilleurs à onde continue (CW), à bande étroite, à balayage (chirp) et à bruit adapté sur une chronologie scriptée. Chaque brouilleur est évalué par bande selon son coefficient de séparation spectrale (SSC), ce qui donne le rapport brouilleur sur signal (J/S) et le rapport densité de puissance de porteuse sur bruit (C/N0) effectif par bande et par ligne. Le graphique est une cascade SVG avec des barres de C/N0 ; result.json porte la grille moyennée par blocs en puissance. L'option [iq] dessine le modèle sous forme d'échantillons IQ, écrit et lit un enregistrement Signal Metadata Format (SigMF) (cf32_le, ci16_le) et compare une estimation de Welch au modèle ; l'option [recording] estime un fichier SigMF réel. Exemple fourni scenarios/l-band-waterfall-jamming.toml : un chirp prend L1 C/A et E1 à 10 s, un ton CW sur la porteuse L1 maintient C/A à 17,98 dB-Hz après l'arrêt du chirp tandis que E1, dont le spectre a un zéro à cet endroit, se rétablit ; L5 et E5a ne sont pas touchés.
    • Nouvelle ligne VALIDATED : les PSD et les SSC des signaux, par rapport au lobe principal de BPSK(n) de 2n x 1,023 MHz, aux lobes de BOC(1 1) centrés à +/-1.023 MHz, aux formes closes de Parseval derrière les SSC publiés de -61.8 / -64.8 / -67.8 dB/Hz, et aux Q = 1 (CW) et 1,5 (adapté) des manuels. Le maximum de la PSD de BOC(1 1) est à +/-0.759 MHz, et non au centre du lobe ; le test fixe les deux.
    • Deux nouvelles lignes MODELLED : la cascade et la chronologie de C/N0, qui se réduisent exactement à la chaîne du type de scénario jamming (recoupées dans chaque rapport), et le codec SigMF et l'estimateur de Welch. Aucun enregistrement de tiers n'est dans le dépôt.
    • navsignal : une variante MBOC et spectral_separation_coeff_offset.
    • Le rapport imprime le C/N0 que donnerait la table Q représentative du type de scénario jamming à côté de celui dérivé du spectre ; pour un ton CW sur la porteuse C/A, ils diffèrent de 1,8 dB. Trois nouvelles lignes de la matrice : une vérifiée (spectres de signaux et coefficients de séparation spectrale) et deux modélisées.

Système solaire

  • Éphéméride du système solaire et positionnement autour de n'importe quel corps. Deux nouveaux types de scénario.
    • solar-system : le Soleil, les huit planètes, Pluton, la Lune, Phobos, Deimos, Io, Europe, Ganymède, Callisto et Titan à une époque : position et vitesse héliocentriques dans l'International Celestial Reference Frame (ICRF), paramètre gravitationnel, rayons, J2 (le deuxième harmonique zonal) lorsqu'il est publié, rotation sidérale, le pôle et le méridien origine de l'Union astronomique internationale (IAU), une trace d'orbite sur une révolution, et le temps de lumière, la distance aller simple et aller-retour, le retard de Shapiro solaire et la séparation du Soleil depuis un corps observateur et pour toute liaison supplémentaire. Les planètes viennent des éléments képlériens du Jet Propulsion Laboratory (JPL) de Standish et Williams (tableau 1, 1800 AD à 2050 AD ; tableaux 2a/2b, 3000 BC à 3000 AD) ; les lunes, des éléments moyens du JPL avec la vitesse de rotation synchrone de l'IAU, et Titan, du modèle de rotation de l'IAU. Exemple : scenarios/solar-system-tour.toml.
    • body-pnt : un orbiteur ou un atterrisseur de surface autour de l'un de ces corps, qui navigue avec des pseudodistances d'une constellation Walker autour du corps et une mesure de distance aller-retour sans horloge depuis la Terre ; dilution de précision, incertitude formelle et points par moindres carrés à graine fixe avec et sans la liaison avec la Terre. Exemples : scenarios/mars-orbit-pnt.toml, scenarios/europa-surface-pnt.toml.
    • Body gagne Mercure, Vénus, Jupiter, Saturne, Uranus, Neptune, Pluton et les sept lunes, une recherche par nom et une fiche physique ; AnalyticSolarSystem donne n'importe quel corps par rapport à n'importe quel autre par la jointure EphemerisProvider existante.
    • VALIDATED par rapport à JPL Horizons (Development Ephemeris DE441 ; données de test et requêtes dans tests/fixtures/solar_system/) : Mercure à Saturne et la Terre d'après le tableau 1 à moins de deux fois l'erreur nominale indiquée (au pire 1,87 fois), les huit planètes d'après les tableaux 2a/2b (au pire 1,71 fois), et le temps de lumière de la Terre à Mars et à Jupiter. MODELLED : Uranus et Neptune d'après le tableau 1, qui dépassent l'erreur indiquée par rapport à DE441 (2,0 et 5,2 fois), Pluton, les lunes, les constantes des corps et les résultats de body-pnt.
    • Constat : la série lunaire de Montenbruck & Gill dans src/ephem.rs est déjà rapportée à l'équinoxe J2000 par son propre terme de précession (0,05 degré d'écart avec Horizons), elle est donc utilisée sans rotation de précession supplémentaire. Six nouvelles lignes de la matrice : deux vérifiées (positions des planètes, temps de lumière) et quatre modélisées.

Constellations autour de n'importe quel corps

  • Conception de constellations à grande échelle (type de scénario constellation-design, src/constellation.rs). Motifs Walker delta et Walker star (T/P/F), listes d'éléments explicites et conceptions à plusieurs couches, plusieurs constellations par exécution, autour de la Terre, de la Lune, de Mars ou de toute autre planète, de Pluton ou d'une lune majeure, à partir des constantes de corps ajoutées par le type de scénario solar-system. Préréglages issus d'éléments nominaux publiés : la référence de base du Global Positioning System (GPS) et la constellation extensible à 24 emplacements (Standard Positioning Service Performance Standard, SPS PS, 2020), Galileo Walker 24/3/1 (Open Service Service Definition Document, édition 1,1), BeiDou en orbite terrestre moyenne Walker 24/3/1 plus des satellites géostationnaires et géosynchrones inclinés (Open Service Performance Standard 3,0) et GLONASS 24/3/1 (Interface Control Document 5,1). Couverture et dilution de précision (DOP) sur une grille de latitude/longitude : satellites en vue, GDOP, PDOP, HDOP et VDOP (géométrique, en position, horizontale, verticale) et disponibilité par cellule, globalement et au pire site, avec une horloge de récepteur par constellation. Un préfiltre de visibilité (demi-angle de couverture plus une bande de latitude du sous-satellite, exact sur un corps sphérique) traite 5 000 satellites sur une grille de 10 deg en environ 0,13 s en build de débogage.
    • VALIDATED : le générateur Walker reproduit le tableau 23 du Galileo OS SDD et la formule d'emplacement du GLONASS ICD ; le préréglage GPS reproduit la colonne de franchissement de l'équateur du SPS PS (35 emplacements sur 36 à moins de 0,0108 deg ; E3F à moins de 0,06 deg, la ligne propre du tableau étant incohérente) ; la distribution mondiale du HDOP de la référence de base GPS concorde avec l'annexe B du SPS PS (médiane 0,940 contre 0,94, 95 % 1,255 contre 1,25, moyenne 0,965 contre 0,96 ; seuil 0,03).
    • MODELLED : conceptions arbitraires, autres corps, phase BeiDou et nœuds géosynchrones inclinés, orbites à deux corps avec J2 facultatif, géométrie seulement.
    • Scénarios : constellation-multi-gnss-coverage (102 satellites, disponibilité 100 %, PDOP médian 0,95, 31,0 en vue au-dessus de 10 deg), leo-pnt-mega-shell (5 000 satellites, disponibilité 99,22 % à un PDOP de 3 ou moins au-dessus de 20 deg, 0 % aux calottes polaires, le préfiltre garde 11,5 % des tests de paires), lunar-relay-constellation (14 satellites autour de la Lune, disponibilité 21,33 % au total et la plus élevée sur la région polaire sud). Les trois sont fournis pour kshana example. Notes : docs/CONSTELLATION-DESIGN.md. Trois nouvelles lignes de la matrice : deux vérifiées (générateur Walker et préréglages GNSS, DOP mondial du GPS) et une modélisée.
  • Une campagne pilotée par le modèle de spectre, et des constellations autour de n'importe quel corps. scenarios/campaign-spectrum-holdover-integrity.toml enchaîne le type de scénario spectrum avec un holdover d'horloge et un moniteur d'intégrité (un chirp prend L1 C/A et E1 ; un ton CW maintient ensuite C/A à la baisse pendant que E1 se rétablit et que le récepteur se rabat sur un ciel Galileo seul), calé sur l'exemple de cascade autonome de tests/campaign_composition_reference.rs. constellation-design résout maintenant son corps central par Body::by_name, de sorte qu'une constellation peut être posée autour de n'importe quelle planète, de Pluton ou d'une lune majeure avec les constantes qu'utilise le type de scénario solar-system.

Campagnes

  • Campagnes : de nombreux scénarios composés en une seule exécution. Un nouveau type de scénario campaign (src/campaign.rs, documenté dans docs/CAMPAIGNS.md) exécute des membres de types de scénario existants par le même aiguillage que la ligne de commande et relit des nombres dans leurs résultats. Quatre sections, dans toute combinaison :
    • [[phases]] : une mission enchaînée sur une seule chronologie. Des préréglages par type de scénario lisent l'erreur de temps d'horloge par rapport à sa garde, le rapport densité de puissance de porteuse sur bruit (C/N0) effectif moyen par rapport au plancher de poursuite, le niveau de protection vertical par rapport à la limite d'alerte, l'erreur de position, les satellites en poursuite et les indicateurs d'alarme, ramenés sur une grille commune avec les frontières de phase et les événements. L'état est transmis par carry, handoff et end_at.
    • [sweep] : une à trois clés pointées de n'importe quel type de scénario, éventuellement avec un ensemble à graine fixe à chaque nœud.
    • [monte_carlo] : réalisation k à la graine de base + k, avec moyenne, dispersion, percentiles et intervalle de confiance bootstrap à 95% à graine fixe.
    • [compose] : des valeurs partagées liées à plusieurs membres, avec une synthèse combinée du meilleur et du pire cas. Chaque résultat porte un hachage de campagne et une empreinte sur tous les résultats des membres. Quatre scénarios fournis : campaign-jam-spoof-holdover-integrity (nominal, brouillage, leurrage terminé à la détection du moniteur d'horloge à 370 s, holdover portant le décalage leurré de 37,0 ns avec une centrale inertielle en roue libre, une alarme d'intégrité, rétablissement), campaign-sweep-jammer-power, campaign-shared-jammer-sea-road et campaign-monte-carlo-clock-holdover. tests/campaign_composition_reference.rs fixe les identités de composition : une campagne à une phase reproduit l'exécution autonome bit pour bit sur trois types de scénario, un ensemble à graine fixe est stable octet pour octet, et sur une horloge à bruit blanc de fréquence la moyenne de l'ensemble se situe dans l'intervalle rapporté, avec la dispersion dans l'intervalle du khi-deux de sqrt(q_wf * tau) = 16,459 ns. Trois nouvelles lignes de la matrice, modélisées.

Animation

  • Export d'animation (--animate svg|html|frames|all, src/animation.rs, docs/ANIMATION.md). Toute exécution dont le résultat porte une série temporelle peut maintenant être écrite sous forme de fichier Scalable Vector Graphics (SVG) animé (images clés Cascading Style Sheets, sans script : les tracés se dessinent derrière un curseur de temps mobile), d'un lecteur HyperText Markup Language (HTML) unique et autonome (lecture et pause, défilement, vitesse, chaque panneau sur un même curseur synchronisé, repères d'événements qui se positionnent au clic ; aucune ressource externe), ou d'une séquence numérotée d'images SVG avec un manifest.json indiquant les images par seconde, la durée et les instants des images pour un encodeur vidéo. Une campagne se joue par ses phases avec ses alarmes marquées ; une exécution de spectre anime sa cascade ligne par ligne. Le lecteur suit prefers-color-scheme, et sous prefers-reduced-motion le SVG comme le lecteur montrent l'image terminée au lieu de bouger. --animate-fps et --animate-duration règlent la lecture ; kshana::api::animate_toml et kshana::animation::animate_result sont les points d'entrée de la bibliothèque, et result.json gagne un bloc animation seulement quand --animate s'exécute. La sortie est une fonction pure du résultat et des options, identique octet pour octet à la réexécution, sans horodatage. Un type de scénario sans axe du temps échantillonné est refusé avec « no time series to animate » et rien n'est écrit. L'exporteur dessine les propres échantillons de l'exécution et n'ajoute aucun nombre, il est donc MODELLED (cohérence interne) et ne porte aucune ligne de la matrice de vérification ; aucun nombre publié ne change. Tests : tests/animation.rs (déterminisme, nombre d'images, aucune adresse externe, XML bien formé, le chemin de réduction des animations, et chaque scénario fourni avec une série temporelle s'animant).

Rapports

  • Rapports d'exécution avancés (src/advanced_report.rs, docs/REPORTS.md). Chaque exécution en interface en ligne de commande (CLI) écrit maintenant <scenario>.report.html, un rapport HyperText Markup Language (HTML) imprimable, et <scenario>.report.json, le même contenu sous forme de document JavaScript Object Notation (JSON) lisible par machine. Sections : un résumé exécutif ; chaque entrée du scénario avec son unité, lue dans le schéma des unités de champ (le bloc units du résultat), sinon dans le suffixe du nom du champ, sinon indiquée comme non indiquée ; les résultats avec le graphique de l'exécution, chaque scalaire et une synthèse de chaque colonne numérique ; pour une campagne, le tableau des nœuds du balayage, la moyenne, l'écart-type, les 5e / 50e / 95e percentiles et l'intervalle de confiance bootstrap de Monte Carlo avec un histogramme par métrique, le tableau des phases de la chaîne, ou les membres et la synthèse combinée de la composition (et la grille d'une exécution sweep ou sweep-nd) ; une chronologie des événements ; l'étiquette VALIDATED / MODELLED / PARTNER, la référence indépendante et les preuves de test de chaque ligne de la matrice de vérification que les types de scénario de l'exécution exercent, lues dans la matrice par une table de correspondance entre type de scénario et ligne (une ligne qui évalue un seul chemin d'entrée, comme le chemin Simplified General Perturbations 4 (SGP4) de orbit ou le chemin d'enregistrement mesuré de slot-timing, n'est listée que lorsque l'exécution a pris ce chemin, et la ligne du lecteur Shuttle Radar Topography Mission (SRTM) n'est listée pour aucun type de scénario, puisqu'aucun champ de scénario ne lit une tuile SRTM) ; les énoncés de ce qui n'est pas modélisé et les hypothèses, chacun cité avec sa source ; et un enregistrement de reproductibilité (version du moteur, le commit source lorsque le build définit KSHANA_GIT_COMMIT, empreintes Secure Hash Algorithm 256 bits (SHA-256) du fichier de scénario et du document de résultat, graine, plateforme et la commande exacte). Le rapport ne lit aucune horloge : le même scénario, la même graine et le même build du moteur donnent un rapport identique octet pour octet, et le seul horodatage qu'il peut montrer est celui que --study-name écrit déjà. Une feuille de style d'impression s'adapte à l'A4 et au US Letter, répète les en-têtes de tableau et garde les lignes et les figures entières d'une page à l'autre ; un fichier Portable Document Format (PDF) s'obtient avec « Enregistrer au format PDF » du navigateur. Il n'y a pas d'option --report pdf, car le rendu des graphiques dans un PDF exigerait une nouvelle dépendance lourde. Tests : tests/advanced_report.rs rapporte chaque scénario fourni (aucune section vide, aucun texte de remplissage, étiquettes égales à la matrice, empreinte du scénario égale à celle du fichier, identique octet pour octet à la réexécution) et tests/advanced_report_cli.rs réexécute la commande enregistrée dans un répertoire neuf et exige un result.json identique octet pour octet. Aucun nombre publié ne change, et les nombres de types de scénario, de fichiers de scénario et de lignes de la matrice sont inchangés.
  • Le rapport, l'animation et les exports fonctionnent ensemble. Le rapport avancé gagne une section « Animation and exports » : le dessin animé de l'exécution intégré comme image inerte (ou la raison pour laquelle il n'y en a pas), des liens vers les fichiers d'animation et d'export écrits à côté, et chaque format d'interopérabilité avec son applicabilité, la raison s'il ne s'applique pas, et sa spécification ; report.json porte le même bloc companions. Le lecteur d'animation HTML liste les fichiers d'export écrits à côté. L'interface en ligne de commande (CLI) produit maintenant les exports avant d'écrire le rapport, de sorte que les deux peuvent nommer les fichiers.

Exports d'interopérabilité

  • Exports et imports d'interopérabilité (--export, src/interop/, docs/INTEROP.md). kshana <scenario.toml> --export <format> écrit la géométrie du scénario en CZML (le Cesium Language), en KML (Keyhole Markup Language 2,2, une norme de l'Open Geospatial Consortium, avec des pistes horodatées gx:Track), en GeoJSON (Internet Engineering Task Force Request for Comments 7946) et en éphémérides Ansys STK (Systems Tool Kit) .e (EphemerisTimePosVel, mètres, un fichier par objet mobile), et l'instantané IQ (en phase et en quadrature) synthétisé du type de scénario spectrum sous forme de paire SigMF (Signal Metadata Format) par le src/sigmf.rs existant. --export all écrit tous les formats applicables et indique pourquoi les autres ne le sont pas ; --export list rend compte sans exécuter. Les objets mobiles sont écrits dans le Geocentric Celestial Reference System (CZML INERTIAL, STK ICRF) et en longitude, latitude et hauteur WGS 84 (World Geodetic System 1984) fixes par rapport à la Terre (KML, GeoJSON) ; les sites fixes en CZML sont FIXED. Le type de scénario jamming ajoute deux empreintes de brouilleur à partir de ses propres équations de liaison. --import-route <file.geojson> écrit un LineString GeoJSON dans les entrées de trace de terrain-nav, terrain-slam, gravity-map et combined-altpnt. Les exports sont déterministes à l'octet près et ne portent aucun horodatage. tests/interop_formats.rs valide chaque export par rapport à sa spécification publiée, compare les états de satellites exportés à ceux du moteur à 1 mm près, et fait passer chaque scénario fourni par chaque format, chacun s'exportant ou indiquant pourquoi il ne le fait pas (le tableau de docs/INTEROP.md). Aucun nombre publié ne change : la synthèse IQ du type de scénario spectrum est passée dans une fonction partagée et son document de résultat est identique octet pour octet, et PassesScenario gagne propagator() et epoch_calendar() utilisés par sa propre exécution. Les nombres de types de scénario, de fichiers de scénario et de lignes de la matrice de vérification sont inchangés. Un scénario d'orbite ou d'intégrité sans epoch est daté par les données propres de ses satellites : t = 0 est la plus ancienne époque de TLE (jeu d'éléments à deux lignes), d'éphéméride diffusée ou de SP3 (Standard Product 3), et chacun de ces satellites est tourné dans les référentiels GCRS et fixe par rapport à la Terre à son propre instant ; 2000-01-01T00:00:00Z n'est utilisé que lorsqu'aucun satellite ne porte d'époque. Les exports SP3 et OEM (Orbit Ephemeris Message) gardent leur étiquette 2000-01-01. Pour cela, Sgp4::epoch_jd_utc, Sp3Interpolator::jd_ut1 et Propagator::own_jd_utc sont ajoutés ; rien de ce qui existait ne les lit.

Navigation en orbite terrestre basse : signal

  • Conceptions de signaux LEO-PNT et spectre multibande. Un nouveau type de scénario leo-signal et un type de scénario spectrum qui va au-delà de la bande L : un type de scénario, quatre fichiers de scénario (trois fournis ; le fichier Celeste IOD est réservé au dépôt) et quatre lignes de la matrice (deux VALIDATED, deux MODELLED).
    • leo-signal : des conceptions paramétrées de signaux de positionnement, navigation et synchronisation temporelle (PNT) en orbite terrestre basse (LEO) pour n'importe quel système (bande, largeur de bande d'émission, attribution UIT ; composantes d'acquisition, de données et pilote avec des spectres BPSK(n), BOC(m,n), MBOC ou plats, parts de puissance, sous-porteuses FDMA, longueurs de code et débits de données), à partir de fichiers de préréglages publics compilés sous data/leo-signals/ (Xona Pulsar X1/X5, Iridium STL, un signal d'opportunité Starlink, CentiSpace, une conception représentative en bande C et des conceptions représentatives UHF/L/S/C/C large, chacune citant l'URL de sa source) ou écrites en ligne. Par signal : la PSD limitée en bande et les fractions de puissance dans la bande, la largeur de bande de Gabor, la gigue de poursuite de code avance-retard limitée en bande en fonction du C/N0 et de l'espacement (Betz & Kolodziejski 2009) et la précision de mesure de distance, l'espace de recherche d'acquisition, la probabilité de détection et le temps moyen d'acquisition série et parallèle sur le code, le SSC vers et depuis GPS L1 C/A, Galileo E1, GPS L5, Galileo E5a, E5b et AltBOC avec la perte de C/N0, la tolérance J/S CW, à large bande et adaptée issue du code SSC du type de scénario de spectre, un arbitrage de bandes (retard ionosphérique, perte en espace libre, mesure de distance à C/N0 égal et à EIRP égale, tolérance au brouilleur), et des contrôles de forme facultatifs par rapport à une mesure décrite. Exemples : scenarios/leo-band-trade.toml, scenarios/xona-pulsar-signals.toml, scenarios/celeste-iod-classical-pilot-signals.toml (les bandes et la configuration de signal Celeste IOD présentées à l'atelier LEO-PNT de l'ESA NAVISP, 2026 ; retenues avec le préréglage Celeste IOD, voir « LEO-PNT end to end » plus bas). Notes dans docs/LEO-SIGNAL.md.
    • spectrum : les bandes peuvent maintenant être une conception de signal prédéfinie (chaque composante dessinée, limitée en bande, C/N0 et J/S rapportés à la composante poursuivie) ou une porteuse et une modulation personnalisées ; [[panels]] ajoutent des cascades sur d'autres plages de fréquences sur une même chronologie ; un brouilleur wideband (barrage) rejoint les quatre formes d'onde. Le rapport ajoute bands[].tracked_power_dbw, bands[].design et panels, et une entrée not_modelled. Les bandes simples donnent les mêmes nombres qu'avant. Exemple : scenarios/multi-band-jamming-waterfall.toml.
    • navsignal gagne l'intégrale du sinus, les formes closes de la puissance dans la bande de BPSK et de la largeur de bande de Gabor limitée en bande, la gigue avance-retard limitée en bande pour n'importe quel spectre et sa borne de Gabor, la forme close du SSC de BPSK décalé, le spectre AltBOC(15 10) de Galileo E5 et un analyseur d'étiquettes de modulation ; Modulation::label imprime BPSK(1/3) sous forme de fraction.
    • Quatre lignes de la matrice : formes closes limitées en bande VALIDATED (90,3 % de la puissance de BPSK dans le lobe principal, la gigue se réduisant à la forme cohérente de Kaplan & Hegarty, 0,0039564 chip à 45 dB-Hz, B_L 1 Hz, d 1 chip, T 20 ms, et à sa borne de Gabor, et l'auto-SSC de BPSK 2/(3 R_c) ; la forme close de Gabor et le SSC décalé par rapport à sa forme de Parseval sont indiqués comme des recoupements internes) ; Doppler LEO maximal VALIDATED (Xona X1 33,2 kHz dans la plage publiée de 32 à 34 kHz, Iridium à 0,5 kHz de 36 kHz) ; MODELLED leo-signal ; spectre multibande MODELLED.
  • Passage LEO-PNT et bilan de liaison par bande : le type de scénario leo-pass. Le LEO-PNT est le positionnement, la navigation et la synchronisation temporelle à partir de satellites en orbite terrestre basse (LEO). Un utilisateur (au sol, maritime, aérien ou en intérieur, statique ou mobile) et un ou plusieurs satellites LEO issus d'un passage conçu, d'éléments explicites, d'un jeu d'éléments à deux lignes (TLE) par SGP4, ou d'une constellation Walker du code constellation-design. Par satellite, bande et époque : angles de visée, distance, vitesse de distance et accélération de distance en forme close (vérifiées à chaque exécution par des différences centrales), Doppler et taux de Doppler, perte en espace libre, EIRP (puissance isotrope rayonnée équivalente) avec un diagramme de satellite isoflux, à faisceau gaussien ou plat, une antenne d'utilisateur patch, l'atténuation gazeuse UIT-R P.676, l'atténuation due à la pluie UIT-R P.838/P.618, la scintillation troposphérique P.618, la perte de pénétration dans les bâtiments UIT-R P.2109 pour un utilisateur en intérieur, le désaccord de polarisation, la température de bruit du système et le C/N0 (rapport densité de puissance de porteuse sur bruit) ; le retard ionosphérique au premier ordre par bande à partir d'un TEC oblique (contenu électronique total) de Klobuchar ou de TEC vertical sous le satellite, et des paires de bandes sans ionosphère avec leur amplification du bruit. Des satellites Galileo ou GPS sont évalués avec le même récepteur à partir des puissances reçues de leurs documents d'interface, de sorte que le passage LEO en cloche et les porteuses MEO (orbite terrestre moyenne) plates partagent un même graphique. Une section [iot] donne le temps avant le premier point, l'énergie par point et l'autonomie de la batterie en fonction du rapport cyclique (MODELLED).
    • Indépendant de tout système : le moteur n'a besoin d'aucun préréglage. Des préréglages facultatifs, chacun dans son propre fichier et marqué PUBLIC (avec URL), REPRESENTATIVE ou WORKSHOP : multibande générique (UHF, L, S, C), bande C générique, Xona Pulsar X1/X5 (arXiv 2509,19551), Iridium STL, Starlink comme signal d'opportunité à Doppler seul, CentiSpace, et Celeste IOD (démonstration en orbite), dont les paramètres de signal ont été présentés à l'atelier LEO-PNT de l'ESA NAVISP, 2026, et se trouvent dans src/celeste_iod.rs pour pouvoir être retenus (voir « LEO-PNT end to end » plus bas).
    • Des briques publiques dans src/leo_link/ (geometry, antenna, itu, iono, energy, presets) que d'autres modules peuvent appeler.
    • Scénarios : leo-pass-vs-gnss-cn0, leo-indoor-uhf, leo-iot-energy, leo-pass-xona-pulsar, leo-pass-iridium, leo-pass-celeste-iod-multiband.
    • Neuf lignes de la matrice. VALIDATED (6) : coefficients UIT-R P.838-3 par rapport à son tableau 5 ; atténuation due à la pluie et scintillation P.618-14 par rapport aux exemples de validation du groupe d'études 3 de l'UIT-R ; perte de pénétration dans les bâtiments P.2109 par rapport au classeur du groupe d'études 3 ; mise à l'échelle ionosphérique au premier ordre par rapport au rapport de retards de groupe de l'IS-GPS-200, avec la perte en espace libre ; le Doppler maximal d'un utilisateur statique sur une orbite circulaire par rapport au tableau 1 d'arXiv 2509,19551. MODELLED (3) : le passage et le bilan de liaison, les préréglages et le budget de point à basse énergie. Un type de scénario et six fichiers de scénario. Notes dans docs/LEO-PASS.md.

Navigation en orbite terrestre basse : message de navigation

  • Message de navigation LEO (type de scénario leo-navmsg, src/leo_navmsg/). Le message d'éphéméride et d'horloge diffusé d'un satellite de positionnement, navigation et synchronisation temporelle (PNT) en orbite terrestre basse (LEO), pour n'importe quelle orbite, porteuse et modèle ; les préréglages nommés sont des données facultatives et chaque capacité fonctionne sans eux. Un type de scénario, cinq fichiers de scénario et neuf lignes de la matrice (trois VALIDATED, six MODELLED). Voir docs/LEO-NAVMSG.md.
    • Contenu du message : SVID, âge des données, bande et état du signal ; semaine, temps de la semaine et polynôme d'horloge du second ordre ; l'éphéméride dans l'un de quatre modèles — le jeu képlérien à 16 paramètres du Galileo OS SIS ICD, ce jeu plus des polynômes de correction le long de la trace, transversale et radiale, le modèle à 22 paramètres de Liu et al. 2025 (doi 10.3390/rs17162894), ou le polynôme ECEF à horloge nulle d'ATOMIC — et un jeu de Klobuchar, des coefficients NeQuick-G avec le niveau d'ionisation effectif, et des paramètres du temps système vers l'UTC avec les cas de seconde intercalaire de l'ICD.
    • Ajusteur : une orbite de vérité intégrée avec la gravité zonale J2–J6 ou EGM2008 et la traînée, une horloge à graine fixe libre ou pilotée, un ajustement de Levenberg–Marquardt sur des éléments non singuliers, puis des polynômes de correction par moindres carrés linéaires et une horloge ajustée nette du terme relativiste de l'utilisateur.
    • Quatre analyses et scénarios : leo-navmsg-fit-interval-trade (erreur de distance du signal dans l'espace (SISRE) en fonction de l'intervalle d'ajustement et de la période de mise à jour), leo-navmsg-model-comparison (quatre modèles, bits, et l'ajustement à 22 paramètres de Kshana aux altitudes de Liu et al. à côté des chiffres publiés, MODELLED), leo-navmsg-midpass-update (continuité à chaque changement de message dans un passage) et leo-navmsg-encode-decode (la propre trame binaire documentée de Kshana avec CRC-24Q et un budget de quantification, un bloc de style RINEX-4 indiqué comme extension de Kshana, et un tableau CSV).
    • VALIDATED : les poids du SISRE moyen global par rapport au tableau publié d'orbite moyenne et géostationnaire de Montenbruck et al. 2018 ; l'algorithme utilisateur de Galileo par rapport à RTKLIB sur quatre éphémérides diffusées réelles de Galileo (tests/leo_navmsg_reference.rs) ; le CRC-24Q par rapport à la valeur de contrôle du catalogue et à la trame d'exemple RTCM 10403 1005.
    • Préréglages, un fichier chacun avec ses sources : Xona Pulsar et Pulsar-0, Iridium, Starlink, CentiSpace, un système représentatif en bande C, ATOMIC, et Celeste IOD (le seul préréglage utilisant du matériel présenté à l'atelier LEO-PNT de l'ESA NAVISP, 2026, conservé dans src/celeste_iod.rs avec ses scénarios pour pouvoir être retenu).

Navigation en orbite terrestre basse : fusion

  • Positionnement, navigation et synchronisation temporelle fusionnés MEO + LEO : leo-pvt, leo-ppp et ntn-positioning. Trois nouveaux types de scénario dans src/leo_fusion/, indépendants de tout système : chaque constellation est faite de couches Walker, de jeux d'éléments ou d'un préréglage GNSS, chaque signal est une porteuse, une cadence de chips et une enveloppe de rapport densité de puissance de porteuse sur bruit (C/N0), chaque budget d'erreur est un écart-type explicite, et les systèmes nommés en orbite terrestre basse (LEO) sont des préréglages facultatifs, un fichier chacun avec leurs sources marquées publiques, d'atelier ou dérivées (Xona Pulsar X1/X5, Iridium Satellite Time and Location (STL), signaux d'opportunité de Starlink, CentiSpace, un système représentatif en bande C, le modèle d'éphéméride à horloge nulle d'ATOMIC, et un préréglage de démonstration en orbite ESA Celeste dont les paramètres issus de l'atelier se trouvent dans src/celeste_iod.rs pour pouvoir être retenus).
    • leo-pvt a quatre modes : positionnement Doppler (moindres carrés par lots sur la vitesse de distance avec des états de dérive d'horloge et de vitesse, un mode de signaux d'opportunité à Doppler seul, la précision d'un seul passage le long de la trace et transversale, et l'enveloppe du Doppler, du taux de Doppler et de la secousse) ; moindres carrés pondérés conjoints GNSS + LEO avec une horloge par système (le biais inter-systèmes) ou un décalage connu, des écarts-types par mesure comme entrées, et le DOP en fonction du nombre de satellites LEO ; couverture polaire et arctique en fonction de la latitude ; et transfert de temps LEO vers le temps universel coordonné (UTC) en fonction du C/N0 et de l'oscillateur du récepteur avec l'expression du temps système vers l'UTC de l'IS-GPS-200.
    • leo-ppp : un filtre de Kalman étendu de positionnement précis par point (PPP) flottant sur le code et la phase sans ionosphère, GNSS seul et avec augmentation LEO, avec son temps de convergence et un test de cohérence NEES (erreur d'estimation normalisée au carré) de Monte Carlo. Le scénario fourni donne 7,4 min avec quatre systèmes MEO et 4,8, 3,2, 2,7 et 2,3 min avec 60, 96, 192 et 288 satellites LEO, à côté des 9,6, 7,0, 3,2, 2,1 et 1,3 min de Li et al. (J. Geod. 93 :749, 2019) comme comparaison MODELLED de la tendance.
    • ntn-positioning : positionnement par réseau non terrestre (NTN) 5G dans la bande S satellite mobile n256 du 3GPP à partir de la borne de Cramér-Rao sur le temps d'arrivée et le Doppler.
    • Scénarios : leo-doppler-positioning, starlink-sop-doppler-positioning, meo-leo-fused-pvt, leo-ppp-convergence, ntn-5g-positioning, polar-arctic-leo-coverage, leo-timing-utc (fournis) et celeste-iod-fused-pvt (réservé au dépôt, retenu avec le préréglage Celeste IOD).
    • Huit lignes de la matrice : l'enveloppe Doppler LEO VALIDATED par rapport aux chiffres publiés d'Iridium (±36 kHz : 35,9 kHz, à 5% près) et de Xona Pulsar X1 (32 à 34 kHz : 33,6 kHz depuis la couche à 97 deg, sans élargissement) (tests/leo_doppler_reference.rs) ; le positionnement Doppler, le positionnement conjoint par pseudodistances, la convergence du PPP, les bornes NTN, la synchronisation temporelle LEO, la couverture polaire et les préréglages sont MODELLED. Trois types de scénario et huit fichiers de scénario. Documentation : docs/LEO-PNT-FUSION.md.
  • LEO-PNT de bout en bout : le type de scénario leo-pnt-chain, et les étapes LEO câblées ensemble. Un système de positionnement, navigation et synchronisation temporelle (PNT) en orbite terrestre basse (LEO) suivi de sa conception de signal à la position de l'utilisateur, chaque étape étant le propre type de scénario du moteur sur sa propre table de scénario, avec des valeurs transmises dans le code (docs/LEO-PNT.md) :
    • Les bandes de leo-pass peuvent nommer une conception leo-signal (signal = "xona-x5") : la bande reprend le centre de la conception, sa largeur de bande d'émission et la cadence de chips de la composante poursuivie, répartit son EIRP (puissance isotrope rayonnée équivalente) entre les composantes de la conception, et rapporte à chaque époque le C/N0 (rapport densité de puissance de porteuse sur bruit) de la composante poursuivie et la gigue de poursuite de code limitée en bande (l'erreur de mesure de distance ; le bruit de la paire iono_free l'utilise aussi). Une bande sans conception donne la même sortie qu'avant.
    • leo-pnt-chain enchaîne signal -> passage -> message de navigation -> point conjoint fusionné leo-pvt -> leo-ppp facultatif. Chaque système LEO de l'étape de positionnement qui les laisse non définis prend une droite de C/N0 en sin(élévation) ajustée au passage, l'erreur de distance du signal dans l'espace du message (SISRE : son erreur de représentation à l'orbite du satellite du passage, avec un terme de détermination d'orbite od_sisre_m indiqué, en somme quadratique), ainsi que la porteuse et la cadence de chips de la conception ; les cas de positionnement précis par point (PPP) prennent le SISRE. Chaque transmission est listée avec sa valeur et son unité, et tests/leo_pnt_chain.rs vérifie que chacune est égale à la sortie en amont et que les changements en amont déplacent les chiffres en aval. LeoNavmsgScenario::broadcast_sisre est le nouveau point d'entrée du message.
    • Scénarios : leo-pnt-end-to-end (une constellation générique à 1080 km et le signal représentatif generic-l), xona-pulsar-end-to-end (le signal public X5), tous deux fournis, et le scénario facultatif celeste-iod-end-to-end, réservé au dépôt.
    • Les préréglages Celeste IOD (démonstration en orbite) des domaines du passage, du message et du positionnement fusionné se trouvent maintenant dans un seul fichier, src/celeste_iod.rs, que build.rs ne compile que s'il existe (l'indicateur de configuration kshana_celeste). Ses cinq scénarios (scenarios/*celeste-iod*.toml) sont réservés au dépôt : supprimer ce fichier et ces scénarios retient donc chaque nombre présenté à l'atelier LEO-PNT de l'ESA NAVISP, 2026, sans modification de source ; tests/workshop_preset_isolation.rs vérifie quels fichiers peuvent nommer le préréglage ou porter les nombres de son plan de bandes.
    • Chaque type de scénario LEO dans la table de correspondance du rapport avancé, avec ses lignes propres à un chemin listées seulement lorsque l'exécution a pris ce chemin (un taux de pluie, un bâtiment, une analyse ou un mode qui s'est exécuté). Les fenêtres Doppler de leo-pvt gagnent t_s et les cas de leo-ppp gagnent t_min, de sorte que les deux s'animent ; leo-pass et leo-pnt-chain exportent des éphémérides CZML, KML, GeoJSON et STK, et les autres types de scénario LEO indiquent pourquoi un format ne s'applique pas.

Navigation en orbite terrestre basse : résilience, domaines ciblés et scénarios d'utilisateurs finaux

  • Résilience LEO-PNT, un scénario par domaine ciblé d'expérience et un par secteur d'utilisateur final, et docs/LEO-PNT.md comme vue d'ensemble de chaque type de scénario et de chaque scénario LEO. Chaque scénario s'exécute sans aucune donnée Celeste et est fourni.
    • leo-pass gagne une section [spoofer] : un leurre contrefait, de façon cohérente en distance et en vitesse de distance, les signaux d'une position annoncée qui saute et/ou est écartée de la position réelle après un début (par bande LEO, et le signal GNSS MEO), avec ou sans l'ionosphère. Deux moniteurs fonctionnent à une probabilité de fausse alarme indiquée : cohérence du Doppler et de la géométrie du passage (vitesses de distance mesurées par rapport à celles prédites à partir des orbites et d'une position et d'une vitesse a priori indépendantes ; un khi-deux des moindres carrés généralisés sur une fenêtre, sur les canaux GNSS, LEO et tous les canaux, bruit de la boucle à verrouillage de fréquence issu du C/N0) et cohérence entre bandes (le saut de la combinaison sans géométrie, corrigée du modèle, de chaque paire de bandes LEO). Le résultat donne les statistiques par époque (il s'anime donc), chaque paire, et le moment où chaque moniteur détecte. Briques dans leo_link::spoof. Section absente, sortie inchangée.
    • Chaque paire de bandes de leo-pass rapporte aussi le contenu électronique total (TEC) oblique que sa combinaison sans géométrie restitue au sommet du passage et l'écart-type de bruit de code de cette estimation (sondage de l'ionosphère). Cela ajoute deux champs à chaque résultat leo-pass multibande ; aucun nombre existant ne change.
    • Le mode de synchronisation temporelle de leo-pvt accepte trace = true : chaque ligne rapporte alors son erreur de temps et son écart-type prédit à chaque époque, avec les mêmes tirages, de sorte que les statistiques des lignes sont inchangées et que l'exécution s'anime et s'enchaîne dans une campagne.
    • Une campagne exporte maintenant chaque scénario membre qui a une géométrie (exécutions de phases, scénarios de base du balayage et de Monte Carlo, membres composés avec leurs valeurs partagées liées) comme son propre jeu de fichiers, l'étiquette du membre figurant dans le nom du fichier ; auparavant, une campagne n'exportait rien. Le tableau d'interopérabilité de docs/INTEROP.md change en conséquence.
    • Une clé de balayage de campagne peut indexer un tableau de tables par position (system.2.sisre_m).
    • Scénarios de résilience : leo-resilience-multiband-diversity (un brouillage en barrage de 50 MHz en bande L5 balayé en puissance : tous les signaux de la bande L tombent, les signaux LEO UHF, en bande S et en bande C gardent leur C/N0), leo-resilience-js-margin (marge J/S à partir de la puissance reçue : GPS L5, Galileo E5a et Xona X5 perdus à -105, -100 et -95 dBW, un signal LEO générique à -135 dBW poursuivant encore à -90 dBW), leo-resilience-spoof-doppler (un saut de 30 m manqué par le test Doppler GNSS seul et détecté par le test sur tous les canaux 105 s après le début), leo-resilience-spoof-monitors (quatre leurres contre les deux moniteurs) et leo-resilience-gnss-jammed-leo-carries (GNSS brouillé, couche LEO en bandes S et C poursuivie, la surveillance autonome de l'intégrité par le récepteur sur la seule couche LEO donnant l'alarme à 2 époques sur 30).
    • Scénarios de domaines ciblés : leo-focus-ppp-altitude, leo-focus-ntn-bandwidth, leo-focus-iot-eirp, leo-focus-science-iono-sounding, leo-focus-data-services, leo-focus-indoor-uhf, leo-focus-fused-pnt-sisre (la résilience en L, S et C est leo-resilience-multiband-diversity).
    • Campagnes sectorielles, chacune animée et exportant ses passages LEO : leo-vertical-autonomous-vehicle, leo-vertical-rail-maritime (les scénarios maritime et ferroviaire fournis plus LEO), leo-vertical-critical-infrastructure-timing, leo-vertical-polar-arctic, leo-vertical-5g-network-timing, leo-vertical-asset-tracking-iot. Résultats en une ligne dans docs/LEO-PNT.md.
    • Trois lignes MODELLED de la matrice : le moniteur de leurrage par le Doppler et la géométrie du passage, le moniteur de leurrage entre bandes et le sondage de l'ionosphère. tests/leo_resilience_verticals.rs vérifie les moniteurs (silencieux avant le début, la statistique Doppler quadratique en fonction d'un saut, le saut ionosphérique d'un leurre au sol et aucun pour un leurre conscient de l'ionosphère), l'identité du sondage, la trace de synchronisation temporelle par rapport aux statistiques des lignes, et que l'export d'une campagne est égal à celui de chacun de ses membres.
    • La page leo-pass passe à docs/LEO-PASS.md ; docs/LEO-PNT.md est la vue d'ensemble.

Scénarios maritimes, routiers et ferroviaires

  • Scénarios maritimes, routiers et ferroviaires. Cinq exemples fournis sur des types de scénario existants, de sorte que les navires, les véhicules routiers et les trains ont chacun un cas travaillé. Chaque chiffre est MODELLED ; aucun n'est validé par rapport à des données mesurées.
    • scenarios/maritime-strait-jamming.toml (jamming) : un brouilleur à large bande de 50 W sur un mât de 30 m, à 30 km en eau libre d'un navire. Le rapport brouilleur sur signal (J/S) moyen est d'environ 48 dB, et la disponibilité chute de 1,00 à 0,00.
    • scenarios/maritime-port-approach-coast.toml (ins-trn-coast) : un système de navigation inertielle (INS) de qualité navigation à 12 nœuds, avec le GNSS perdu et sans aide. Il franchit 10 m après 281 s et 100 m après 833 s, les chiffres d'approche de port et d'eaux océaniques de la résolution A.1046(27) de l'Organisation maritime internationale (OMI), utilisés ici comme budgets.
    • scenarios/maritime-spoof-position-push.toml (spoof-detect) : un leurre de +2 dB, non aligné sur la porteuse, qui pousse quatre satellites pour écarter un navire de 500 m. Le moniteur fusionné le détecte (score 0,70 pour un seuil de 0,50) par la surveillance autonome de l'intégrité par le récepteur (RAIM) et la surveillance de la qualité du signal (SQM) ; la seule surveillance de puissance le manque.
    • scenarios/automotive-urban-canyon.toml (gnss-ins) : une voiture traversant un passage inférieur de 15 s et une panne de 60 s due à un brouilleur en bord de route, face à un budget d'une demi-voie de 1,5 m. L'erreur quadratique moyenne (RMS) fusionnée pendant la panne est de 1,9 m pour une unité micro-électromécanique (MEMS) de classe automobile et de 0,7 m pour un comparateur de qualité tactique ; en roue libre, l'unité MEMS dérive jusqu'à 850,8 m.
    • scenarios/rail-tunnel-coast.toml (ins-trn-coast) : un INS de qualité tactique sur un train à 160 km/h dans un tunnel. Il franchit 2 m (discrimination de voie) après 35,8 s, à environ 1,6 km, et 20 m après 107,3 s. C'est de l'INS seul : le moteur n'a pas de modèle d'odomètre, c'est donc la borne pessimiste. Le nombre de fichiers de scénario du README passe de 77 à 82. Les cinq sont fournis pour kshana example et listés dans le bac à sable du navigateur.

Serveur du Model Context Protocol

  • Le serveur du Model Context Protocol (MCP) atteint chaque type de scénario et chaque vue d'une exécution : sept nouveaux outils, quatorze au total. run_scenario aiguillait déjà chaque type de scénario ; ce qui manquait à un agent, c'était un moyen d'obtenir un scénario valide d'un type de scénario, et les trois sorties que la ligne de commande écrit à côté d'un résultat. Nouveaux outils :

    • list_example_scenarios et get_example_scenario servent les scénarios de référence fournis (le tableau kshana example), chacun avec son type de scénario et la première phrase de son propre en-tête, octet pour octet le fichier sous scenarios/. Un scénario qui est dans le dépôt mais n'est pas fourni est refusé avec la raison. Chaque type de scénario sauf lunar-llr-datum (dont la tranche de données n'est livrée qu'avec le dépôt) a au moins un exemple.
    • report_scenario renvoie le rapport de l'exécution en JSON (JavaScript Object Notation) ou comme page HTML (HyperText Markup Language) imprimable (docs/REPORTS.md).
    • animate_scenario renvoie la série temporelle de l'exécution sous forme de dessin SVG (Scalable Vector Graphics) animé, de lecteur HTML ou d'images numérotées, après un résumé JSON de ce qui a été dessiné (docs/ANIMATION.md). Une réponse porte 120 images au plus ; la ligne de commande en écrit de n'importe quelle longueur.
    • list_export_formats, export_interop et import_route servent les exports d'interopérabilité et l'import de parcours GeoJSON (docs/INTEROP.md) : CZML (Cesium Language), KML (Keyhole Markup Language), GeoJSON, l'éphéméride STK (Systems Tool Kit) .e et SigMF (Signal Metadata Format), avec un index JSON des fichiers (suffixe, taille et SHA-256, l'empreinte Secure Hash Algorithm sur 256 bits) et le fichier binaire d'échantillons SigMF en base64.

    La bibliothèque gagne une fonctionnalité bundled-scenarios désactivée par défaut qui expose la table des scénarios de référence sous le nom kshana::bundled_scenarios ; seul le serveur MCP l'active, de sorte que la roue Python et le module WebAssembly ne portent toujours pas le texte des scénarios. Les suites d'étude (--study) restent réservées à la ligne de commande, parce qu'une suite nomme des fichiers sur disque et que le serveur n'en lit aucun. Les tests d'aller-retour exécutent chaque nouvel outil sur des scénarios fournis et vérifient les nombres du moteur : spectre, système solaire, constellations autour de la Lune et d'Europe, balayage de campagne, et les types de scénario de signal, de passage, de message de navigation, de positionnement fusionné, de positionnement précis par point, de réseau non terrestre et de bout en bout en orbite terrestre basse (LEO). Chaque surface qui indique le nombre d'outils MCP ou liste les outils dit maintenant quatorze, sauf la page du bac à sable sous web/, qui est remplacée par le site.

kshana.dev, Kshana Studio et le README

  • Un kshana.dev repensé. La page unique du bac à sable est remplacée par un site à plusieurs pages : Home, Missions, Capabilities, Evidence, Developers, Editions et Docs, avec Kshana Studio à un clic. Chaque graphique, carte et nombre qui s'y trouve est une exécution enregistrée du moteur de cette version, avec le scénario et un lien qui rouvre la même exécution dans le Studio ; la construction du site refuse un enregistrement fait par un autre commit du moteur. Les pages de documentation sont générées à partir du docs/ du dépôt, et les options d'installation à partir de ses canaux. Les polices et les bibliothèques de scripts sont servies par kshana.dev lui-même, de sorte qu'aucune page ne demande quoi que ce soit à un hôte tiers. Les anciennes adresses (/#playground, /#ledger, liens de partage /#s=<scenario>, liens d'intégration /?embed=1&… et le reste) redirigent vers leur nouvel emplacement, et une adresse inconnue obtient une page 404.
  • Kshana Studio, un tableau de bord pour chaque capacité. Le Studio s'ouvre sur un écran de départ avec des tuiles de domaines et de bonnes premières exécutions, puis fait passer une exécution par cinq étapes numérotées : Choisir un scénario, Régler ses paramètres, Exécuter le moteur en local dans le navigateur, Lire les résultats (les chiffres clés d'abord, chacun avec une pastille PASS ou FAIL lorsque l'exécution énonce un seuil, puis les panneaux) et Partager ou exporter. Une seule zone de recherche trouve les scénarios, les domaines et les champs qu'ils contiennent et saute vers le contrôle ; les exécutions peuvent être épinglées et comparées ; un fil d'Ariane indique où vous êtes ; sur un téléphone, les étapes deviennent une barre d'étapes. Chaque type de scénario a sa vue, y compris la cascade du spectre, le système solaire, la couverture des constellations, les campagnes, l'animation, le rapport d'exécution, les exports d'interopérabilité et la chaîne en orbite terrestre basse. Un lien profond (?scenario=…&tab=…) ouvre la même exécution sur le panneau nommé.
  • Recherche et citation. La page Evidence liste les cinq articles Kshana sur arXiv (2606,22054, 2606,24210, 2607,02566, 2607,05415 et 2607,06212), chacun avec un résumé, une figure calculée par ce moteur, la commande qui la reproduit, un lien vers le Studio et le BibTeX, à côté de la manière de citer le logiciel. Le README gagne la même section Research.
  • Une page publique pour Kshana Pro. docs/PRO.md et la page Editions du site disent ce que la surcouche propriétaire Pro ajoute au même moteur (optimiseur de conception, incertitude et sensibilité, dossier de mission, veille de campagne, coexistence de spectre, service de tâches sur site, traçabilité des exigences), ce que chacune produit et ce qu'elle ne fait pas. Chaque chiffre Pro que le site montre est énoncé dans cette page publique. Pro n'ajoute aucun modèle physique, et le moteur ouvert reste entier et gratuit.
  • Un README réécrit. Des sections courtes, une image par section, la marque Kshana, deux rangées de badges, des images générées d'architecture, de flux de scénario, de chaîne en orbite terrestre basse et de vérification (tools/gen_readme_assets.py, qui échoue sur une image périmée), et des captures d'écran du Studio prises sur le Studio en cours d'exécution par tools/capture_studio_shots.mjs. Les README de crates.io, PyPI, npm et du serveur MCP suivent la même conception. Le matériel de référence long est replié ou déplacé vers docs/.

Modifié#

  • <scenario>.report.html est maintenant le rapport d'exécution avancé décrit sous Added, et la ligne wrote … de la CLI nomme aussi <scenario>.report.json. La fiche de synthèse d'une page qu'il a remplacée est inchangée sous le nom RunOutput::html_report(), que les liaisons Python et WebAssembly renvoient toujours. OracleKind::modelled_reason() expose la phrase que docs/MODELLED-RATIONALE.md imprime pour chaque ligne MODELLED ; ce document est inchangé.
  • Le README dit sur quoi Kshana Pro s'appuie. La section Editions et la ligne Kshana Pro sous « Support & professional services » indiquent maintenant ce que fait l'outillage d'ingénierie des systèmes fondée sur les modèles (MBSE) et de programme de Pro et lesquelles des sorties publiées du moteur ouvert il lit (le result.json et le report.json de chaque exécution, le fichier de scénario, le schéma des unités de champ et les étiquettes de la matrice de vérification), et sur quoi reposent dans le moteur ouvert les jumeaux numériques d'horloge, les études d'arbitrage et les paquets de preuves. Reformulation seulement : aucune sortie du moteur et aucun nombre publié ne change.
  • Compatibilité. L'énumération publique navsignal::Modulation gagne une variante Mboc, ce qui est un changement incompatible pour un appelant qui la traite de façon exhaustive. Les colonnes gcrs_r_m et gcrs_v_m_s du type de scénario ephemeris changent (voir « Révisions de chiffres publiés »). Une exécution est toujours reproduite par la version du moteur qui l'a faite.

Corrigé#

  • export_table_csv sur le serveur MCP nommait quatre types de scénario comme les seuls ayant un tableau CSV (valeurs séparées par des virgules) ; six en publient un. L'outil renvoyait toujours le tableau pour telecom-timing et pour leo-navmsg (son analyse encode-decode sur un modèle de message kepler16 ou kepler-rac), mais sa description, son message de refus et les documents qui listent les types de scénario omettaient les deux, de sorte qu'un agent apprenait à ne pas le demander. Ils sont nommés maintenant, et un test d'aller-retour récupère les deux tableaux.

  • La trame du message de navigation en orbite terrestre basse (LEO) n'avait pas les mêmes octets sur toutes les plateformes, ni dans tous les builds d'une même plateforme. scenarios/leo-navmsg-encode-decode.toml encodait une trame avec le contrôle de redondance cyclique 0x110315 dans le build de publication sur aarch64 macOS, 0x898BD8 dans un build de débogage de la même source sur la même machine, et 0x6A82D9 dans le build WebAssembly (WASM) ; leo-navmsg-celeste-iod.toml donnait 0x6EDB2D en natif contre 0xC6E4F0 dans le navigateur. Trois causes, chacune remontée jusqu'à la première valeur divergente :

    • Entre plateformes. L'orbite de vérité était identique au bit près sur les deux ; le point de départ de l'ajustement ne l'était pas. truth::state_to_elements prend l'inclinaison osculatrice d'un acos et l'argument du périgée d'un atan2, et les deux bibliothèques mathématiques les arrondissent différemment à la dernière place (sur 20 000 arguments, elles diffèrent pour 781 sinus, 858 cosinus, 1 931 exponentielles et 1 899 arctangentes à deux arguments).
    • Entre profils de build. Un build optimisé sur macOS fusionne un sinus et un cosinus d'un même argument en un seul appel à la routine combinée du système, et son sinus n'est pas celui du sin isolé pour 379 arguments sur 200 000 ; un build non optimisé fait les deux appels. Le type de scénario prend un sinus et un cosinus ensemble à treize endroits.
    • Dans l'horloge. L'échantillonneur normal de rand_distr appelle les fonctions exp et ln de l'hôte dans ses deux branches rares : sur quatre millions de tirages à graine fixe, trois différaient au dernier bit entre le build natif et le build WASM.

    L'ajustement de Levenberg–Marquardt, qui sur cet arc s'arrête à sa limite de 80 itérations et non à un minimum, transporte une unité de dernière place dans des champs quantifiés différents. Le type de scénario calcule maintenant chaque fonction transcendante par le nouveau src/portable_math.rs, qui appelle le crate libm en Rust pur (déjà dans l'arbre des dépendances, maintenant nommé dans Cargo.toml), compilé à partir d'une source unique pour chaque cible et non un appel de bibliothèque que l'optimiseur réécrit : leo_navmsg::{truth, fit, elements, codec, sisre, services} et le code du scénario. Les puissances entières sur ce chemin sont écrites en carré-et-multiplication, parce que f64::powi a une précision non spécifiée, et l'horloge de vérité tire ses écarts normaux de portable_math::standard_normal (méthode polaire de Marsaglia sur la sortie brute du générateur). Les routines partagées que l'orbite de vérité intègre sont écrites une seule fois, génériques sur la bibliothèque mathématique, avec un point d'entrée _portable interne au crate à côté de l'existant : l'accélération en harmoniques sphériques, les accélérations zonales et de traînée, les taux séculaires de J2 et le retard de Klobuchar. Les points d'entrée existants sont inchangés jusqu'au dernier bit, de sorte que le nombre d'aucun autre type de scénario ne bouge. leo_navmsg::tests::the_encoded_frame_is_the_same_bytes_on_every_platform fixe la trame entière de 171 octets et une valeur de contrôle par modèle d'éphéméride, dans le profil de test ordinaire (non optimisé), sur chaque plateforme et sans barrière d'hôte de référence ; the_kind_never_calls_the_host_mathematics_library lit les sources du type de scénario sur disque et échoue sur un appel transcendant natif, sur un échantillonneur rand_distr, ou sur un appel dans un module qui n'a pas été relu. Après le changement, un build de débogage, un build de publication et le build WASM produisent des documents de résultat identiques octet pour octet pour les cinq scénarios leo-navmsg. Cela déplace des nombres, consignés ici comme une révision. Le type de scénario leo-navmsg est nouveau dans cette version, donc rien de ce qui a été publié dans une version antérieure ne bouge, mais chaque chiffre de leo-navmsg bouge, en natif et dans le build WASM, et l'étape navmsg de leo-pnt-chain avec lui : les chiffres d'orbite parce que l'ajustement part maintenant des éléments portables, les chiffres d'horloge parce que l'horloge de vérité est une réalisation différente du même processus. docs/LEO-NAVMSG.md est régénéré à partir des nouveaux résultats ; sa valeur de contrôle publiée pour le scénario d'encodage et de décodage était 0x110315 et est 0x19105F (position à 1,126 mm du message exact là où elle était à 0,665 mm, horloge à 0,185 mm là où elle était à 0,451 mm). L'ampleur des changements dans les chiffres sous le millimètre est la sensibilité de l'ajustement, et non une erreur dans l'un ou l'autre jeu : l'ajustement est inchangé et s'arrête toujours à sa limite d'itérations.

  • Le rééchantillonnage à graine fixe tirait des indices différents sur une cible 32 bits. Rng::gen_range sur usize prend 64 bits du générateur sur un hôte 64 bits et 32 bits sur un hôte 32 bits, de sorte que la même graine donnait d'autres indices, et laissait le flux ailleurs, dans le build WASM. Trois endroits tiraient ainsi : les bootstraps de percentiles dans eval_stats (bootstrap_ci, bootstrap_auc_ci), le brassage avant chaque passe d'entraînement dans impairment_ml, et le test de permutation dans impairment_study. Ils tirent maintenant par portable_math::uniform_index, qui échantillonne toujours comme u64 : exactement ce que faisait un hôte 64 bits, de sorte qu'aucun nombre natif ne bouge. Cela déplace des nombres publiés du paquet WASM, consignés ici comme une révision : l'intervalle bootstrap quantum-anomaly-detect de l'aire sous la courbe (quantum_auc_ci, trade.foms[0].ci95) était [0.9901265, 0.9938305] dans le navigateur et est maintenant l'intervalle natif [0.99035875, 0.993861].

  • Noms de fichiers d'éphémérides STK à partir des identifiants de mobiles. Un identifiant de mobile contenant un / ou une espace (une couche de constellation et un satellite, Pulsar inclined/S1-0163) faisait paniquer la CLI sur --export stk ; chaque identifiant passe maintenant par une partie de fichier sûre (lettres, chiffres, -, _).

  • Le signe de la nutation TEME→GCRS, décrit sous « Révisions de chiffres publiés » plus haut parce qu'il déplace une sortie publiée.

0.28.0 - 2026-09-26#

Ajouté#

  • Type de scénario slot-timing (src/slot_timing.rs) : le nombre de secondes avant qu'une horloge libre ne sorte de la garde d'un créneau de routage ou de tâche indexé sur le temps, chaque terme contributeur à ce moment avec le terme dominant nommé, le temps restant depuis le dernier point, et le plus grand intervalle entre points qui garde l'horloge à l'intérieur, net de la latence du point. L'horloge vient d'une valeur par défaut de classe, d'un préréglage de fiche technique telecom-timing, d'une fiche technique en ligne (maxima de l'écart-type d'Allan, vieillissement, coefficient de température) ou d'un enregistrement de phase mesuré. Un dépassement au-delà du plus long temps de moyennage que la source prend en charge est signalé comme extrapolé. Exemple fourni : slot-timing-ocxo-leo. Voir docs/SLOT-TIMING.md.
  • Plancher de bruit rouge mesuré. L'écart-type d'Allan chevauchant d'un enregistrement de phase est ajusté par moindres carrés pondérés dans la base de modulation de fréquence à phase blanche et IEEE Std 1139 (slot_timing::fit_weighted), chaque point étant pondéré par ses degrés de liberté équivalents, de sorte qu'une réponse de holdover peut reposer sur le plancher propre de l'horloge plutôt que sur l'hypothèse de classe. Un ajustement non pondéré plaçait un faux plancher de scintillation sur un enregistrement de test à bruit blanc et raccourcissait de 30 % un dépassement à 2 000 s.
  • Validation sur jeu réservé de l'inversion du holdover sur une horloge réelle (tests/slot_timing_cs5071a_holdout.rs) : ajustés sur le premier tiers de l'enregistrement césium 5071A contre maser à hydrogène, les dépassements prédits à un écart-type pour six seuils de 0,5 à 2,5 ns tombent entre 0,84 et 1,03 des dépassements mesurés sur les deux autres tiers, pour un seuil de 1,5 fixé avant la première exécution du test. Un témoin (l'écart-type d'Allan à une seconde lu comme du bruit blanc) manque d'un facteur d'environ 1 000 et échoue au seuil. Nouvelle ligne VALIDATED du registre ; le workflow realdata-clock l'exécute maintenant.
  • La même prédiction sur un oscillateur à quartz réel (tests/slot_timing_ocxo_holdout.rs, scripts/fetch_ocxo.sh) : sur un oscillateur à quartz thermostaté mesuré, la prédiction sur jeu réservé est prudente, à 0,59 à 0,70 du dépassement mesuré et jamais plus tard, et le plus souvent hors du seuil de 1,5, parce que le plancher de bruit de cet oscillateur a diminué de moitié pendant l'enregistrement de 5,5 heures ; ajustée sur l'échantillon, elle tombe entre 0,98 et 1,17. Le cas du quartz n'est pas validé et reste MODELLED. L'exécution a aussi mis au jour un terme manquant : la fréquence d'un quartz dérive, de sorte que le modèle porte maintenant l'incertitude de la fréquence connue au point (fix_frequency_sigma) ; sans lui, la prédiction était optimiste jusqu'à 2,5×.
  • La même prédiction sur des horloges atomiques en orbite (tests/slot_timing_igs_holdout.rs, scripts/fetch_igs_clocks.sh) : 14 jours d'horloges finales de l'International GNSS Service pour les satellites GPS Block IIF, avec le protocole écrit avant le téléchargement des données. Huit satellites sur dix tombent dans le seuil de 1,5 ; G25 et G30 prédisent des dépassements jusqu'à environ deux fois plus tardifs que mesurés. Le protocole exige que chaque satellite réussisse, de sorte que le cas orbital n'est pas validé et reste MODELLED ; le résultat est fixé.
  • Classes d'horloge à quartz compensé en température (TCXO), à quartz thermostaté (OCXO) et à étalon de fréquence atomique au rubidium (RAFS) (ClockClass::Tcxo, Ocxo, Rafs), les composants qu'embarque un bus de petit satellite commercial ou une passerelle au sol, chacun citant une fiche technique publique (ClockClass::source). ClockClass::ALL, id et from_id ajoutés. Le baseline_clock_class de quantum-trade accepte les trois nouveaux identifiants. Ajouter des variantes à une énumération publique est un changement incompatible pour un appelant qui la traite de façon exhaustive.
  • Niveau de protection de la synchronisation temporelle pour un récepteur en orbite (src/orbital_timing.rs, la section spoofing facultative du type de scénario slot-timing) : combien de temps un leurre au sol peut atteindre un satellite en orbite terrestre basse par passage, le déphasage qu'un leurre à une vitesse de rampe maximale indiquée accumule avant que le satellite ne quitte sa portée ou qu'un contrôle indépendant ne s'exécute, et si chaque contrôle de contact au sol ou de liaison croisée est indépendant de ce leurre. Se réduit exactement à tpl::timing_protection_level_ns pour une horloge sans bruit de scintillation, de phase blanche ou de marche aléatoire. MODELLED.
  • Trois notes : docs/SLOT-TIMING.md (y compris la mesure de dérive d'après laquelle un créneau devrait être accepté : l'erreur de temps absolue maximale, et non l'erreur d'intervalle de temps maximale ni la déviation temporelle, et pourquoi), docs/DECEIVED-TIME.md (une commande signée appliquée à un temps trompé s'aiguille quand même mal) et docs/DEPLOYMENT-TARGETS.md (où Kshana s'exécute ; aucun cœur de vol no_std n'est proposé).

0.27.4 - 2026-09-26#

La version v0.27.3 a atteint crates.io (kshana et kshana-mcp) et PyPI, puis s'est arrêtée à npm, de sorte que npm, l'image MCP ghcr.io, le registre MCP, le JetBrains Marketplace et kshana.dev ne l'ont jamais reçue. 0.27.4 porte le même moteur, avec la correction de publication ci-dessous, vers tous les canaux.

Corrigé#

  • L'étape de publication npm nomme l'archive par un chemin explicite. npm lit un npm-dist/kshana-0.27.3.tgz nu comme le raccourci GitHub owner/repo, de sorte que la tâche npm de v0.27.3 a tenté de cloner github.com/npm-dist/kshana-0.27.3.tgz et a échoué avec « Permission denied (publickey) ». L'archive elle-même avait été construite et attestée. L'étape publie maintenant ./npm-dist/*.tgz. Tout ce qui suit npm dans l'ordre de publication (l'image MCP, le plugin JetBrains, la vérification de parité des canaux et le site) a été sauté, comme prévu.

Modifié#

  • Les catalogues d'unités de telecom-timing et de gnss-ins sont exemptés de la détection de copier-coller, selon la même politique et le même test de justification que les autres catalogues. Le portail de qualité SonarCloud était passé au rouge sur la duplication du nouveau code (4,0% contre 3%), et chaque bloc dupliqué était une ligne d'unités ou une entrée de masque ITU-T.

0.27.3 - 2026-09-25#

Ajouté#

  • scenarios/small-uas-jammed-nav.toml : combien de temps la navigation d'un petit drone tient après le brouillage du GNSS. Il exécute une centrale inertielle micro-électromécanique (MEMS) de classe contrôleur de vol, une Bosch BMI088, face à une unité de qualité tactique. Le signal GNSS (Global Navigation Satellite System) est nominal pendant 100 s, puis refusé pendant 60 s (jamming-demo.toml montre pourquoi un brouilleur proche fait cela). Les biais de la BMI088 sont les résidus laissés après l'étalonnage de démarrage, tirés des coefficients de température de sa fiche technique (BST-BMI088-DS000-19 rév. 1,9) : 0,015 °/s par K pour le gyroscope et < 0,2 mg par K pour l'accéléromètre. Deux hypothèses sont signalées dans le fichier : un échauffement de 10 K après l'étalonnage, et un réchauffement continu de 1 K par minute en vol. La dérive en vol est l'erreur que le filtre ne peut pas apprendre avant le début du brouillage, et c'est elle qui met fin à la navigation à l'estime. Chaque chiffre est modélisé ; le valider demanderait des journaux de vol dans un environnement brouillé. kshana example small-uas-jammed-nav l'imprime.

  • Chaque capteur gnss-ins peut fixer sa propre loi a priori du filtre ([imu_quantum.filter_prior] ou [imu_classical.filter_prior], avec sigma_accel_bias et sigma_gyro_bias). La valeur par défaut est inchangée, de sorte que chaque scénario existant donne le même résultat. Le biais de gyroscope résiduel d'une unité grand public se situe à environ 26 écarts-types hors de la valeur par défaut de qualité tactique, où le filtre ne l'apprendrait jamais. Une loi a priori qui n'est pas finie et positive est rejetée, et le résultat reprend la loi a priori lorsqu'une est fixée.

  • kshana example [<name>] donne à un utilisateur du registre un scénario à exécuter. Un utilisateur de cargo install kshana a l'exécutable et aucun répertoire scenarios/, de sorte que la première commande que donnait chaque guide de démarrage échouait. L'interface en ligne de commande (CLI) embarque maintenant les 75 scénarios de référence qui s'exécutent seuls, octet pour octet, compilés à partir de scenarios/ (src/bundled_scenarios.rs ; la table se trouve dans le binaire de la CLI, de sorte que la roue Python et le module WebAssembly ne grossissent pas). kshana example les liste ; kshana example clock-holdover > clock-holdover.toml en écrit un. Les deux autres fichiers sont réservés au dépôt : lunar-llr-datum lit des données archivées de télémétrie laser lunaire qui ne sont livrées qu'avec le dépôt, et quantum-pnt-demonstrator.suite est un manifeste d'étude qui exécute trois fichiers voisins avec --study. En demander un dit pourquoi et sort avec 2 au lieu d'imprimer quelque chose qui ne peut pas s'exécuter seul. tests/cli_first_run.rs tient la table alignée sur le répertoire dans les deux sens, de sorte qu'un nouveau fichier de scénario qui n'est ni fourni ni nommé réservé au dépôt échoue.

  • Chaque figure de mérite d'un résultat d'horloge, d'orbite, hybride ou de fusion dit maintenant si elle est VALIDATED ou MODELLED, dans le résultat lui-même. Le document de résultat gagne un bloc figure_tiers, toujours sa dernière clé. Il liste chaque chiffre rapporté (par exemple quantum.fom.timing_p95_ns) avec son niveau — VALIDATED signifie vérifié par rapport à une référence externe indépendante, MODELLED signifie un modèle issu des premiers principes qui est testé en interne — et la ligne de la matrice de vérification d'où le niveau est lu. Le niveau vient de src/verification.rs par src/fom_label.rs, de sorte qu'il n'y a pas de seconde table qui puisse diverger. Auparavant, les mots « validé » et « modélisé » apparaissaient zéro fois dans un résultat de holdover d'horloge, et un lecteur du JSON (JavaScript Object Notation) brut n'avait aucun moyen de distinguer les deux. Les chiffres de position hybrid et fusion n'ont aucune ligne de matrice propriétaire, ils sont donc listés sous untiered au lieu de recevoir un niveau. Le bloc ne porte aucun nombre. Il est prouvé additif, et non supposé : le retirer redonne le document d'avant le changement octet pour octet, pour les cinq types de scénario (un test du moteur), et les deux bancs de référence (tests/registry_golden.rs, tests/cross_platform_golden.rs) retirent maintenant exactement cette clé, et seulement lorsqu'elle est la dernière, puis hachent le reste par rapport à leurs constantes figées inchangées. Une liste dans chaque banc fixe quels scénarios doivent porter le bloc, de sorte que l'exclusion ne peut pas s'élargir discrètement.

  • Un type de scénario telecom-timing répond dans les unités d'un ingénieur de synchronisation : erreur de temps, erreur d'intervalle de temps maximale (MTIE) et déviation temporelle (TDEV), chacune avec un PASS ou un FAIL et une marge par rapport aux masques du Secteur de la normalisation des télécommunications de l'Union internationale des télécommunications (UIT-T). Les masques sont transcrits des éditions en vigueur : G.8272 (07/2025) pour les classes A et B de l'horloge de référence de temps primaire (PRTC), G.8272.1 (2024) Amd. 1 (07/2025) pour la PRTC améliorée en mode verrouillé et en holdover (y compris son enveloppe d'erreur de temps, qui monte de 30 ns à 100 ns sur une période de holdover fixée par la durée pendant laquelle l'horloge a été verrouillée), G.8273.2 (2023) Amd. 2 (11/2025) pour les horloges de frontière et d'esclave de temps de télécommunications, classes A à D, et G.8271.1 (2022) Amd. 3 (05/2025) pour les limites du réseau au point de référence C. Chaque entrée que ces Recommandations laissent « à l'étude » est absente, non estimée, et docs/TELECOM-TIMING.md liste chaque nombre avec son tableau ou son paragraphe et chaque élément qui a été laissé de côté. Le rapport donne aussi le temps de dépassement de chaque budget d'erreur de temps : par défaut le holdover ePRTC par défaut de 100 ns, une allocation de holdover réseau de 400 ns, la limite du point C de 1 100 ns et l'exigence de bout en bout de classe 4 de 1,5 microseconde.

    L'entrée est soit un holdover synthétique, soit une série qui vous appartient. Le holdover synthétique utilise l'un de quatre préréglages d'oscillateur (un oscillateur à quartz thermostaté, un étalon au rubidium, un étalon au césium et une horloge atomique à l'échelle d'une puce), chacun portant les chiffres de stabilité, de vieillissement et de température d'une fiche technique Microchip nommée. La façon dont ces chiffres deviennent un bruit de fréquence blanc, de scintillation et de marche aléatoire, un vieillissement et un terme de température est énoncée dans chaque rapport et étiquetée MODELLED. Une série qui vous appartient est faite de paires [time_s, time_error_ns], en ligne (c'est ainsi qu'elle s'exécute dans le navigateur) ou, sur les builds natifs, d'un fichier de valeurs séparées par des virgules. Le tableau MTIE/TDEV, avec la limite de chaque masque choisi à côté, est écrit comme artefact CSV de l'exécution.

    scenarios/telecom-prtc-holdover-24h.toml est un holdover au rubidium de 24 heures avec vieillissement, scintillation et un cycle de température quotidien : son erreur de temps la plus grande est de 603,2 ns, il franchit 100 ns 8 206 s après la perte et reste sous 1,5 microseconde toute la journée, et il échoue à l'enveloppe de holdover de la PRTC améliorée, comme le doit une horloge qui n'est pas de classe césium. scenarios/telecom-tie-ingest.toml montre l'entrée en ligne. Le MTIE et le TDEV que le type de scénario rapporte sont vérifiés par rapport au paquet allantools sur une série de holdover de 2 048 échantillons versionnée dans le dépôt, exactement pour le MTIE et à 1.1e-15 près pour le TDEV, de sorte que la matrice gagne une ligne VALIDATED et deux lignes MODELLED (la transcription des masques et les préréglages) et en compte maintenant 171 lignes — 65 VALIDATED, 102 MODELLED, 4 PARTNER. La couverture des unités de champ passe de 60 types de scénario sur 61 à 61 sur 62, et de 1 742 à 1 788 champs décrits. Le type de scénario est nouveau et additif : aucun scénario, aucune épingle et aucun chiffre publié existants ne bouge.

  • Le bac à sable exécute le moteur dans un Web Worker en arrière-plan, de sorte qu'un scénario lent ne fige plus la page. web/engine-worker.mjs héberge le moteur WebAssembly et web/engine.mjs lui transmet chaque exécution de scénario — exécutions, balayages de paramètres et exports SP3 / OMM / OEM / CSV. Une exécution qui dépasse 150 ms affiche un état occupé (Run désactivé, « Running… N s ») et un bouton Cancel qui termine et relance le worker ; un navigateur qui ne peut pas démarrer un worker de module se rabat sur l'ancien chemin du fil principal. cislunar-arc-recovery, retiré du catalogue parce qu'il figeait la page, y est de retour, étiqueté comme lent : il prend environ 13 s dans Chrome (quatre appels du moteur d'environ 3 s chacun), pendant lesquelles la page reste réactive.

  • Chaque grandeur rapportée par cislunar-observability porte maintenant une unité, une classe de provenance et une définition — l'avant-dernier type de scénario de la liste d'exemption à l'échelle du crate. Les 41 champs numériques du document RELEASED sont décrits, de sorte que la couverture des unités de champ passe de 59 types de scénario sur 61 à 60 sur 61 et de 1 698 à 1 742 champs décrits, l'arriéré sans définition restant inchangé à 239.

    Cela était bloqué par l'épingle qui fige le document publié, laquelle nommait units comme une clé que le document ne devait jamais gagner. En ajouter une aurait supposé de supprimer cette assertion et de rebaser trois hachages dans trois fichiers — une forme indiscernable d'une dissimulation de régression. À la place, les deux épingles qui mesurent ce document prouvent maintenant que l'ajout est additif : chacune retire de nouveau le bloc units et re-hache par rapport à la constante figée avant l'existence du bloc, et les deux constantes sont inchangées. Une mutation confirme que la garantie est réelle — déplacez une valeur publiée et rebasez le hachage du document entier comme le ferait une correction négligente, et le retrait suivi du re-hachage échoue encore. La troisième épingle, dans le banc générique registry-golden, est rebasée au même titre que les six sœurs qui l'ont été exactement pour cette raison, et son littéral expect_summary porteur de valeurs ne bouge pas.

  • realtime-frame-eop rapporte par rapport à quelle vérité chaque ligne d'orientation de la Terre a été évaluée, et à quelle fréquence le repli s'est déclenché. table3_joint_eop[].{ut1, polar_motion,combined} gagnent truth_source et truth_fallback_rows. Le plancher final est évalué par rapport au Bulletin B final et ne peut utiliser que les époques qui en publient un ; chaque ligne dN est évaluée par rapport à truth_pm()/truth_ut1(), qui se replient sur la valeur rapide du Bulletin A. Sur l'extrait 2026 fourni, cela représente 12 échantillons sur 31 à un jour, contre 0 au plancher — de sorte que la ligne du plancher et les lignes de prédiction à côté reposent sur une vérité mesurablement différente, ce que le rapport énonce maintenant au lieu de le laisser se déduire d'un nombre d'échantillons qui monte là où des horizons emboîtés disent que cela ne se peut pas.

  • moonlight-service-volume émet une référence de base képlérienne de même taille. ephemeris_comparison.keplerian_matched réexécute la constellation illustrative au nombre de satellites propre à l'ensemble RETRIEVED, présent seulement lorsque les nombres diffèrent. Le nombre fait partie de la géométrie de cette conception — l'AD du nœud ascendant (RAAN) et l'anomalie moyenne sont toutes deux réparties comme 360k/n — de sorte que sans lui, un ensemble récupéré de cinq satellites était évalué par rapport à un ensemble illustratif de huit et la conception était confondue avec la taille. Pour l'ensemble de référence LANS de cinq satellites, 8,68 des 14,24 points d'écart de couverture se révèlent être les trois satellites manquants et seulement 5,56 points la conception ; pour les quatre engins réellement en orbite lunaire, un ensemble de quatre satellites conçu à cet effet atteint 4,86 % là où ils atteignent 0 %. Un test fixe que la ligne appariée est une constellation reconstruite et non celle configurée rebaptisée, ce qui est la façon dont elle a d'abord été écrite et ce que l'exécution rapportait alors.

  • Neuf cartes de capacités sur le site public, couvrant 22 lignes de la matrice de vérification livrées sans carte au niveau produit. Le moteur avait vu grandir une famille de capacités — la vérification ARAIM par rapport aux vecteurs de référence publiés du Working Group C, la géométrie réelle de constellations lunaires récupérées, le contour de déni lunaire avec une bande de C/N₀ mesurée, l'étape de l'ordonnancement VLBI à la covariance de station, le transfert optique et RF avec injection de pannes inter-modalités, la prédiction en temps réel de l'orientation de la Terre par rapport au Bulletin A archivé, le partage d'ouverture entre navigation et communications, la navigation à l'estime INS/TRN, et la couverture des unités et de la provenance — chacune avec une ligne de matrice et un scénario fourni, et aucune nommée sur kshana.dev. La couverture carte-ligne passe de 72 lignes sur 168 à 94.

  • Huit scénarios ajoutés au catalogue du bac à sable. Le bouton Run d'une carte de capacité n'apparaît que si web/app.js porte aussi le fichier ; six cartes nommaient un scénario qu'il ne portait pas, de sorte qu'elles s'affichaient sans moyen de les exécuter — l'une d'elles, la donnée de télémétrie laser réelle, était dans cet état depuis sa livraison. tests/scenario_examples_doc_sync.rs impose maintenant l'invariant dans les deux sens : la cible run d'une carte doit être fournie sous scenarios/ et proposée par le catalogue. Testé par mutation sur les deux modes de défaillance.

  • moonlight-service-volume émet sa géométrie par satellite sous forme de <scenario>.table.csv lorsqu'un site d'export est configuré (G11). C'est le plus grand tableau que le crate publie — 2304 lignes dans la table conjointe de communications et de navigation publiée — et il n'atteignait les consommateurs que dans du JSON, la forme qui a tronqué la courbe de 57 points d'un scénario voisin à 23 points sous une colonne qui les annonçait tous. Une ligne par liaison, le nombre de lignes sur la ligne d'en-tête, les colonnes d'antenne présentes seulement lorsqu'une antenne était configurée. Une exécution sans site d'export est inchangée octet pour octet et n'écrit aucun fichier.

  • Le SBOM décrit maintenant ce qui est livré : 60 composants sont devenus 66. scripts/gen-sbom.sh listait chaque paquet de la résolution des fonctionnalités par défaut, dépendances de développement comprises. Cela mettait sgp4 et chrono — des crates réservés aux tests, compilés dans aucun artefact — dans la nomenclature, et laissait de côté la chaîne --features python que lie la roue PyPI (pyo3, pyo3-ffi, pyo3-macros, pyo3-macros-backend, pyo3-build-config, portable-atomic, target-lexicon, heck), qui est la frontière d'interface de fonctions étrangères de cette roue. Le script parcourt maintenant le graphe de résolution depuis le paquet kshana par les seules arêtes normales et de construction, sur l'union des jeux de fonctionnalités par défaut, python et wasm (le paquet npm porte ce même SBOM), pour chaque plateforme cible. Le verdict de conformance CycloneDX fixé est rebasé par son générateur versionné : 60 → 66 composants, 53 → 60 expressions de licence composées, et toujours zéro erreur de schéma une fois celles-ci placées dans la forme standard expression.

  • Le tableau CSV de reproductibilité atteint chaque point d'entrée, pas seulement la CLI et la roue Python. Le serveur MCP gagne un septième outil, export_table_csv, qui exécute un scénario et renvoie le tableau stable à l'octet près que la CLI écrit sous le nom <scenario>.table.csv — ou une erreur nommant les types de scénario qui en publient un (realtime-frame-eop, lunar-time-budget, lunar-jamming, et moonlight-service-volume seulement lorsque export_site_lat_deg + export_site_lon_deg sont définis). Le module WebAssembly gagne table_csv, qui renvoie le même texte ou undefined. Le test d'aller-retour MCP et les tests de la liaison Python fixent maintenant le CSV renvoyé octet pour octet par rapport à tests/golden/realtime-frame-eop.csv, et fixent que RunOutput.write_csv renvoie les octets écrits, et 0 sans fichier créé pour un type de scénario sans tableau. Chaque surface qui indique le nombre d'outils MCP ou liste les outils dit maintenant sept.

  • run_all dans le module WebAssembly : une seule exécution du moteur pour toutes les sorties. run, chart_svg, summary et table_csv exécutent chacun le scénario de zéro, de sorte que le bac à sable payait quatre exécutions complètes par clic — environ 12 s au lieu de 3 s pour cislunar-arc-recovery dans un navigateur. run_all renvoie {json, svg, summary, csv} à partir d'une seule exécution, et le bac à sable l'utilise maintenant. Il correspond aux quatre appels séparés octet pour octet.

Corrigé#

  • RÉVISION : le couplage du biais de gyroscope du filtre GNSS/INS avait le mauvais signe, et les chiffres de panne de gnss-ins changent. Le filtre de Kalman étendu (EKF) à état d'erreur garde les deux biais inertiels comme des résidus (vrai moins l'estimation courante, réinjecté par addition). La colonne de l'accéléromètre pilotait l'erreur de vitesse avec +C_b^n b_a, mais la colonne du gyroscope pilotait l'erreur d'attitude avec −C_b^n b_g. Un biais de gyroscope résiduel fait en réalité tourner l'attitude calculée de +C_b^n b_g, de sorte que chaque estimation du biais de gyroscope poussait dans le mauvais sens. Le paquet n'est resté stable que parce que sa loi a priori par défaut du biais de gyroscope (1e-4 rad/s, 1 écart-type) était assez serrée pour tenir ces états immobiles. Avec une loi a priori plus large, le filtre divergeait même lorsque le vrai biais de gyroscope était nul : 93 m d'erreur fusionnée pendant la panne devenaient 4,3 km. Les chiffres publiés pour scenarios/gnss-ins.toml changent comme suit :

    gnss-ins.toml avant (≤ 0.27.2) après
    IMU à atomes froids, RMS fusionné pendant la panne 96,1 m 1,9 m
    IMU à atomes froids, navigation à l'estime dans la spécification (50 m) 30 s 60 s (toute la panne)
    IMU tactique, RMS fusionné pendant la panne 62,5 m 3,1 m
    IMU tactique, navigation à l'estime dans la spécification (50 m) 37 s 60 s (toute la panne)

    Les chiffres en roue libre (130,7 m et 314,3 m) ne changent pas ; ils n'ont jamais utilisé le filtre. La lecture antérieure du paquet, selon laquelle la navigation à l'estime fusionnée est limitée par un plancher d'attitude de transmission et ne s'améliore donc pas avec un meilleur capteur, était un artefact de ce défaut et est retirée. Avec des biais constants et sans bruit, le filtre les apprend maintenant tant que le GNSS est disponible, de sorte que la navigation à l'estime fusionnée est un meilleur cas. La référence externe filterpy (tests/gnss_ins_sensor_fusion_reference.rs) ne vérifie que les mises à jour de mesure, ce qui explique qu'elle n'ait jamais vu la propagation. Deux tests vérifient maintenant directement le signe et échouent tous deux sur l'ancien. Le premier, dans closed_loop.rs, injecte un biais de gyroscope résiduel connu dans le strapdown et exige que le filtre prédise l'erreur d'attitude qui en résulte à 2 % près. Le second exige qu'une loi a priori large apprenne un biais de gyroscope de 1e-3 rad/s et reste dans 6 m. La référence multiplateforme de gnss-ins est refixée pour cette raison et aucune autre.

  • Chaque guide de démarrage du registre s'exécute maintenant tel qu'écrit sur une machine propre. Mesurés avant ce changement, les exemples crates.io et PyPI (Python Package Index) lisaient scenarios/clock-holdover.toml, que n'a pas une installation depuis le registre, et l'exemple npm plantait sous Node.js avec TypeError: fetch failed, parce que le init() du paquet récupère son binaire WebAssembly et que le fetch de Node ne peut pas lire un fichier local. Maintenant :

    • README.crates.md et README.pypi.md portent ce scénario en ligne, comme README.npm.md le faisait déjà. Le bloc Rust est un programme entier avec son propre main, puisque la ligne # Ok::<…> masquée par rustdoc qui le terminait est affichée sur crates.io et ne compile pas une fois collée. tests/readme_code_fences_doc_sync.rs le compile toujours octet pour octet, et refuse maintenant aussi une ligne masquée dans le bloc.
    • README.npm.md sépare le navigateur de Node.js et donne une recette Node qui lit le binaire sur disque et le passe à initSync. Le test de synchronisation de la documentation accepte initSync comme le chargeur que génère wasm-bindgen.
    • Tous trois intègrent le scénario avec ses chaînes de provenance non abrégées, de sorte que le hachage du scénario est 5ba83a232b94 sur chaque surface. L'exemple npm les abrégeait, ce qui lui donnait un hachage différent de celui de la CLI.
    • Reproduit à partir de builds locaux de cet arbre : un nouveau projet cargo new avec une dépendance par chemin vers le crate empaqueté a compilé et exécuté l'exemple Rust ; une roue construite avec maturin à partir des sources empaquetées, installée dans un nouvel environnement virtuel, a exécuté l'exemple Python ; et le paquet wasm-pack --target web, empaqueté et installé avec npm, a exécuté la recette Node. Les trois ont imprimé la même ligne de synthèse.
  • cargo run -- <scenario.toml> fonctionne depuis un clone. Cargo.toml définit default-run = "kshana". Sans cela, cargo refusait avec « could not determine which binary to run », que chaque ligne cargo run -- de la documentation rencontrait.

  • Les erreurs de la première minute de la CLI disent quoi faire ensuite. Un chemin de scénario qui n'existe pas ajoute maintenant une indication pointant vers kshana example, et un second argument positionnel imprime le texte d'usage en plus de nommer l'argument. --help, --version, l'erreur d'option inconnue (sortie 2) et la ligne ok: unique de --validate en cas de succès étaient déjà sur main. tests/cli_first_run.rs les couvre maintenant tous, puisqu'aucun test n'exécutait le binaire pour aucun d'eux auparavant.

  • list_kinds() en Python est documenté comme renvoyant une chaîne JSON unique, et non une liste. Il renvoie les mêmes métadonnées que scenario_kinds(), sérialisées, de sorte que l'itérer parcourt des caractères. Il garde son retour sous forme de chaîne pour que les appelants existants ne cassent pas. kshana.pyi, le commentaire de documentation de la liaison, docs/PYTHON_API.md et README.pypi.md le disent maintenant et renvoient vers scenario_kinds().

  • Les trois README de registre développent chaque abréviation à sa première utilisation. PNT est maintenant développé dans le slogan, où il apparaît pour la première fois, et CLI, TOML, JSON, SVG, CSV, CSAC, HTML, URL et API sont développés dans les fichiers qui les utilisent. Le titre du tableau des références indépendantes ne dit plus « CI-gated » avant que CI soit défini.

  • Correction d'un chiffre publié : la disponibilité ARAIM à deux constellations sur les TLE GPS + Galileo de Celestrak fournis dans le dépôt. docs/CAPABILITY.md affirmait que le regroupement de Galileo fait passer la disponibilité de 0,21 à 0,67 sous une VAL de 12 m et que le mode robuste aux pannes de constellation est limité avec seulement deux constellations. Cela venait de tests/araim_dual_real_data.rs, qui propageait chaque satellite depuis sa propre époque de TLE (parse_propagators abandonne l'époque), et les époques de ces fichiers s'étendent sur 70,6 h (GPS) et 335,7 h (Galileo), de sorte que les satellites se trouvaient à des instants mutuellement incohérents. Le test garde maintenant chaque époque (parse_tle) et évalue chaque satellite à un même instant UTC commun, la plus récente époque de TLE de l'ensemble (2026-06-07T07:21:04). La disponibilité mesurée sur la même grille de 24 h, 289 échantillons devient, pour le GPS seul, 0,993 (elle était 0,208), regroupée 1,000 (elle était 0,671) et pour le mode double robuste aux pannes de constellation 0,990 (elle était 0,031) ; à la limite APV-I, le mode double passe de 0,180 à 1,000. La conclusion s'inverse : sur un ciel cohérent, deux constellations portent l'hypothèse de panne de constellation à une VAL de 12 m. Les mêmes chiffres résultent en prenant comme référence la plus ancienne époque de TLE. Un autocontrôle du test fixe sa boucle de disponibilité échantillon par échantillon sur araim_dual_constellation_availability, de sorte que la seule différence est l'alignement temporel. docs/CAPABILITY.md et docs/REAL_TLE_GUIDE.md § 3 portent les nouveaux nombres ; l'entrée 0.13.0 ci-dessous est laissée telle que publiée.

  • Les surfaces publiques n'annoncent plus RINEX 4 comme validé. Le moteur refuse maintenant un fichier de navigation RINEX 4 par son nom au lieu de le décoder de travers, mais la grille des normes montrait encore une carte « RINEX 3 / 4 » avec une pastille validé, liée aux preuves RINEX-3 de l'analyseur de navigation. La carte est maintenant « RINEX 3 », et le README, docs/CAPABILITY.md, docs/STANDARDS.md, ROADMAP.md et le résumé des capacités énoncent ce qui est vrai : les fichiers d'observation RINEX 3.0x sont analysés, la disposition d'observation 4,00 est censée l'être mais aucun fichier 4,00 n'a été lu par le code, et les fichiers de navigation RINEX 4 sont refusés.

  • --validate dit quand « ok » signifie qu'il n'y avait rien à vérifier. Environ les deux tiers du catalogue ne publient aucun champ obligatoire — ces paquets exécutent leur configuration de référence à partir d'un corps vide — de sorte que le contrôle ne pouvait qu'imprimer « ok » pour eux, dans les mêmes mots qu'après avoir vérifié six champs. La ligne de succès indique maintenant le nombre de champs obligatoires qu'elle a trouvés présents, ou que le type de scénario n'en exige aucun.

  • scripts/gate.sh refuse un REPEAT ou un TEST_THREADS non numérique. Sous bash 3,2, REPEAT=no faisait échouer la comparaison numérique en erreur et l'évaluait à faux, de sorte que le portail annonçait « repeatability loop SKIPPED (REPEAT=0) » pour une valeur qui n'était pas 0 et écrivait quand même un reçu. Les deux réglages sortent maintenant avec 2 sauf s'ils sont de simples entiers.

  • La MSRV est indiquée comme 1,85 partout où une personne la lit. Cargo.toml est passé à 1,85 à la dernière version ; le badge du README, le texte d'installation et de dépannage, codemeta.json et la justification propre du crate MCP disaient encore 1,75.

  • RunOutput.__repr__ dans la liaison Python rapporte des octets, et non des « chars ». Il imprimait len() de chaînes UTF-8, ce qui est un nombre d'octets : 710 « chars » pour un tableau de 708 caractères.

  • Le README ne documente plus --study --study-name ensemble. --study-name est un indicateur à scénario unique, ignoré avec --study (le binaire avertit). Les deux exemples à copier-coller de README.md et de README.crates.md montrent maintenant la commande d'étude seule.

  • Les preuves de stabilité d'horloge du site énoncent les deux tolérances observées. La série césium 5071A est reproduite à ≤ 3e-5 et PHASE.DAT à ≤ 5e-5 ; le paragraphe donnait 3e-5 pour les deux.

  • Deux fichiers de sortie du moteur ne sont plus suivis. scenarios/quantum-pnt-demonstrator.study.{json,html} avaient été estampillés par le moteur 0.20.0 avec chaque figure de mérite vide, et la propre commande d'étude du README les écrasait, salissant l'arbre et bloquant le portail de push. *.study.json / *.study.html sont maintenant ignorés comme les quatre autres sorties du moteur.

  • Un balayage de graine dans le bac à sable n'échoue plus à chaque exécution. Le balayage faisait avancer le réglage entier seed de façon linéaire (1, 10,9, 20,8, …), et le moteur, le lisant comme u64, rejetait chaque valeur fractionnaire. Les réglages entiers balaient maintenant des nombres entiers distincts.

  • Chaque téléchargement du bac à sable dit quel moteur et quelle entrée l'ont produit. Quelques types de scénario (par exemple realtime-frame-eop) n'émettent ni engine_version ni scenario_hash, de sorte que leurs téléchargements s'appelaient simplement kshana-csv.csv. Le nom se rabat maintenant sur la version du moteur chargé et une empreinte FNV-1a-64 de 12 chiffres hexadécimaux du texte du scénario.

Modifié#

  • Le crate publié fait moins de la moitié de son ancienne taille, et cargo install kshana ne construit que la CLI. Le paquet incluait les articles, leurs dossiers de soumission, les artefacts de figures d'articles, les carnets, docs/, les scripts de mainteneur et les programmes d'exemple. Aucun n'est compilé par la bibliothèque ou la CLI. Il incluait aussi les trois générateurs internes sous src/bin/ (crossover_study, gen_validation_artifacts, validation_report), de sorte qu'une installation depuis le registre compilait et installait quatre exécutables, dont trois n'étaient utiles que dans une copie de travail. Ces arbres et les trois sources de générateurs sont maintenant exclus. Cargo liste les binaires d'un paquet à partir des fichiers qu'il contient, de sorte que le manifeste publié ne nomme que kshana. Dans un clone, les générateurs sont toujours trouvés automatiquement, de sorte que cargo run --bin <name> et la tâche de publication qui exécute validation_report sont inchangés. Mesuré avec cargo package : 763 fichiers, 16,7 MiB, 6,8 MiB compressés avant ; 591 fichiers, 10,5 MiB, 3,0 MiB compressés après. Sa construction de vérification, qui ne compile que les fichiers empaquetés, réussit. cargo install --path sur le crate empaqueté a installé un exécutable, kshana.

  • Une sortie qu'un ingénieur de synchronisation peut lire : plus de p95 0.0ns, plus de security 0.000 sans attaque, et des nombres de sites qui correspondent aux README. C'est une révision d'affichage. Aucun nombre publié ne change ; les valeurs JSON sont identiques, ce que prouvent les hachages de référence ci-dessus.

    • La synthèse d'une ligne imprimait l'erreur de synchronisation temporelle au 95e percentile (p95) de l'horloge optique comme 0.0ns alors que le tableau à côté montrait 1.20e-4 ns. Un chiffre de synchronisation non nul, trop petit pour une décimale, est maintenant imprimé avec trois chiffres significatifs (p95 1.20e-4ns) ; un zéro exact s'imprime toujours comme 0.0. Le rapport HTML (HyperText Markup Language), le tableau de comparaison des études et le rapport téléchargeable du bac à sable utilisent la même règle, de sorte qu'aucun chiffre non nul ne s'imprime non plus comme 0.000.
    • security est une borne analytique de détectabilité du leurrage qui n'a de sens que face à une attaque configurée. Les types de scénario clock, orbit, hybrid et fusion n'en configurent aucune, de sorte que leur synthèse imprime maintenant security n/a (no attack) au lieu d'un nombre tel que 0.000 qui se lit comme une détection manquée. La valeur reste dans fom.security, marquée applicable: false avec la raison dans figure_tiers, et les tableaux du rapport montrent « not applicable ». Le type de scénario spoof évalue toujours la détection.
    • Deux épingles de synthèse dans tests/registry_golden.rs ont bougé pour exactement ces deux raisons et aucune autre : golden_clock (le p95 quantique et les deux valeurs security) et golden_orbit (les deux valeurs security ; ses valeurs p95 sont exactement nulles). Leurs hachages de document entier n'ont pas bougé. Les synthèses attendues du README, des trois tutoriels et de leurs scénarios pédagogiques sont mises à jour en conséquence, et tests/tutorials.rs vérifie les copies pédagogiques par rapport au moteur.
    • La visite guidée du bac à sable ne s'ouvre plus au premier chargement. Sa fenêtre modale interceptait les premiers clics et son projecteur faisait défiler la page loin de l'endroit où le visiteur avait atterri. Elle démarre depuis le bouton « Take the 60-second tour » ou le bouton flottant Tour.
    • La page ne défile plus latéralement sur un téléphone. À 390 px, la rangée de la marque et le bouton GitHub représentaient environ 410 px de contenu, soit un débordement de 4 px ; l'en-tête tient maintenant à partir de 320 px, et le tableau des figures de mérite défile à l'intérieur de sa propre boîte au lieu d'élargir la page.
    • L'explorateur de capacités commençait par son propre nombre de cartes (« 46 capability cards … 17 backed by an external oracle ») à côté de README qui disent 64 sur 168. Il commence maintenant par la matrice de vérification, lue dans le web/data/verification-matrix.json généré (la même matrice sur laquelle sont fixés les nombres du README), et nomme ensuite les cartes pour la couche de synthèse qu'elles sont. web/counts.test.mjs, une nouvelle étape du workflow d'intégration continue (CI), vérifie l'arithmétique et recoupe README.md et les descriptions de la page ; tests/web_validation_counts_doc_sync.rs fixe le câblage du côté Rust.
  • La description publique commence maintenant par la synchronisation temporelle et le holdover, le domaine le mieux vérifié. L'ouverture du README et docs/POSITIONING.md présentent Kshana comme un moteur de preuves de résilience PNT ouvert, reproductible et étiqueté par provenance : d'abord la synchronisation temporelle et le holdover des infrastructures critiques (les estimateurs d'Allan, d'Allan modifié, de déviation temporelle et d'erreur d'intervalle de temps maximale et l'inversion de variance de la dérive en holdover sont les lignes VALIDATED qui la fondent), le quantique comme méthode neutre d'arbitrage quantique contre classique dont les résultats sont étiquetés MODELLED, et la navigation lunaire / cislunaire et en espace lointain comme capacités maintenues plutôt que comme thème principal. Les deux pages disent maintenant ce que Kshana n'est pas — pas un simulateur de signaux radiofréquence ni un banc matériel en boucle, pas un remplacement de MATLAB/Simulink, STK ou Orekit — et renvoient vers le nouveau type de scénario telecom-timing et vers docs/TELECOM-TIMING.md. L'ancienne phrase « there is no good open tool » a disparu : une recherche qui ne trouve rien n'est pas une preuve que rien n'existe. ROADMAP.md gagne un ordre de priorité sans date (d'abord la synchronisation temporelle, ensuite l'arbitrage quantique, le lunaire maintenu) et abandonne trois éléments périmés (les systématiques de Coriolis et de décalage lumineux, les conditions initiales NRHO et le scénario lunaire, tous livrés) ; la ligne du README « Coriolis and light-shift remain roadmap » est corrigée de la même façon.

  • docs/CAPABILITY.md a cessé de sous-déclarer. La ligne des référentiels fixes par rapport à la Terre disait « none » alors que la matrice évalue GCRS→ITRS comme VALIDATED ; elle dit maintenant « full », et la ligne des référentiels de base consigne le recoupement ANISE comme livré. Le mode guidé était listé comme feuille de route ; le bac à sable a livré des curseurs guidés et une visite guidée. Un balayage par rapport à src/verification.rs a corrigé cinq autres lignes qui précédaient leurs validations : le modèle de forces de Cowell et la détermination d'orbite par lots/séquentielle par rapport à Orekit 12,2, les passages de stations au sol par rapport au détecteur d'élévation d'Orekit, le noyau de dilution de précision par rapport à gnss_lib_py, et l'import OEM par rapport à l'analyseur indépendant oem ; la ligne de vérification et validation nomme maintenant les garde-fous qui vérifient que chaque test cité existe.

  • Le glossaire explique ce que dit un fichier de résultat. docs/GLOSSARY.md gagne des entrées en langage courant pour les termes de sortie (holdover, p95, intégrité, le score de sécurité, PDOP, sigma_y, q_wf), les termes de synchronisation des télécommunications (erreur de temps, max|TE|, cTE, dTE, MTIE, TDEV, PRTC, ePRTC, T-BC, T-TSC, OCXO, CSAC) et les trois niveaux de preuve (VALIDATED, MODELLED, PARTNER).

  • Les abréviations sont développées à la première utilisation dans chaque document public écrit à la main. Le README et 24 fichiers sous docs/ avaient plusieurs centaines d'abréviations utilisées avant leur développement, ou sans lui ; chacune est maintenant développée là où elle apparaît pour la première fois dans ce fichier. Les trois fichiers générés (docs/VERIFICATION-MATRIX.md, docs/MODELLED-RATIONALE.md, docs/SCENARIOS.md) sont laissés tels quels : ils sont écrits à partir de src/verification.rs et de api::list_scenario_kinds(), de sorte que leur formulation doit changer à la source.

  • La couverture de lignes a une mesure de référence. docs/COVERAGE.md consigne 95,63 % (37 697 lignes sur 39 419) à partir de la tâche CI coverage sur b1d350d, et tests/coverage_figure_doc_sync.rs y fixe les cinq surfaces publiques « ~96% » — le seul chiffre phare qui était tenu à la main, et qui avait déjà bougé une fois sans que personne le remarque.

  • De nouveaux portails de synchronisation de la documentation pour des surfaces que rien ne lisait. tests/readme_code_fences_doc_sync.rs vérifie chaque import { … } from "kshana" d'un bloc JavaScript par rapport aux exports WebAssembly, et fixe l'exemple Rust de README.crates.md octet pour octet sur une copie que le binaire de test compile. tests/security_md_doc_sync.rs échoue si src/lib.rs perd #![forbid(unsafe_code)] ou si SECURITY.md cesse de l'énoncer. tests/no_overclaims.rs analyse maintenant aussi web/README.md et les trois README de registre, et chaque norme du site doit énoncer explicitement son proof.

  • Les deux vérifications d'horloges sur matériel réel s'exécutent sur un runner. realdata-clock.yml (mensuel et sur déclenchement manuel) récupère les séries 5071A et PHASE.DAT et exécute les deux tests avec KSHANA_REQUIRE_REALDATA=1, de sorte qu'une entrée manquante échoue au lieu d'être sautée. Les deux scripts de récupération sont fixés sur un seul commit d'allantools et vérifient le SHA-256.

  • Le stub de types Python est vérifié par rapport à la roue construite (mypy.stubtest dans la tâche des liaisons), ce qui explique que csv/write_csv aient été livrés sans stub.

  • Le glossaire définit URE, EOP, FoM, CTI et TIB, que le README et le registre utilisaient tels quels.

  • Le contrat de champs publié de chaque type de scénario est maintenant vrai, et un test l'y maintient. Cinq des 61 types de scénario ont changé. Les types de scénario dont required_fields n'est pas vide passent de 21 à 22 : ephemeris exige maintenant tle|orbit+epoch (un kind = "ephemeris" nu passait --validate puis faisait échouer l'exécution), et quantum-trade ajoute candidate_adev_taus+candidate_adev_values|candidate_clock_class, que son exécution exigeait déjà. Une entrée obligatoire peut utiliser | (l'un de ceux-ci) et + (tous ceux-ci ensemble) ; --validate comprend les deux. lunar-joint-od-clock, pvt et earth-gnss-lunar publient 9 champs facultatifs réels qu'ils avaient omis. docs/SCENARIOS.md dit maintenant que kind est obligatoire pour chaque type de scénario sauf clock. tests/required_fields_are_true.rs vérifie chaque type de scénario par rapport à son scénario livré : retirer n'importe quelle entrée obligatoire doit faire échouer l'exécution, et un document ne contenant que les champs obligatoires doit s'exécuter.

  • Les notes du JetBrains Marketplace sont soumises à un portail. scripts/check-version-sync.sh échoue maintenant à moins que l'entrée <change-notes> la plus récente de plugin.xml ne nomme la version livrée ; sept versions publiées avaient servi les notes de 0.22.0 sans changement.

  • Le chiffre de couverture du rapport technique est le chiffre mesuré. paper/kshana-technical-report.md disait « near 97 % » ; il dit maintenant près de 96 % (95,63 % mesurés, docs/COVERAGE.md) et est la sixième surface que le test de couverture fixe.

  • Le client du moteur hors du fil principal est testé (web/engine.test.mjs, en CI) : liste d'autorisation de l'aiguillage, annulation et relance, les trois chemins de repli sur le fil principal, et reprise après plantage, face à un faux worker.

  • Rien n'est publié tant que le commit étiqueté n'a pas passé ses tests, et une publication n'est pas terminée tant que chaque registre ne la sert pas. L'ordre est maintenant étiquette, vérification, publication, parité, site, en une seule exécution de release.yml (docs/RELEASING.md).

    • La publication attend le verdict. publish.yml, mcp-publish.yml et jetbrains-plugin.yml ne démarrent plus au push de l'étiquette ; release.yml les appelle depuis des tâches qui ont needs: verify. Auparavant, ils lui faisaient concurrence : sur v0.27.2, crates.io, npm et le Python Package Index (PyPI) avaient tous publié dans les 4,5 minutes suivant l'étiquette, et verify était revenu 84 minutes après elle ; sur v0.27.0, npm et PyPI ont publié alors que la tâche crates.io échouait. Une nouvelle tentative manuelle sur une étiquette est retenue par le nouveau scripts/check-release-verdict.sh, qui exige un verify au vert pour ce commit exact depuis l'interface Actions et échoue de façon fermée sur tout autre cas.
    • Tout est construit avant que quoi que ce soit ne soit téléversé, et crates.io, dont l'étape d'empaquetage est celle qui a échoué en cours de publication, publie en premier.
    • Un jeton de registre manquant fait échouer la tâche au lieu de sauter le téléversement et de rapporter un succès.
    • Une vérification de parité après la publication. scripts/check_channel_parity.py interroge crates.io (kshana et kshana-mcp), npm, PyPI (la distribution source et les six roues de plateforme) et ghcr.io jusqu'à ce que chacun serve la version, ou fait échouer l'exécution ; docs.rs et le registre du Model Context Protocol (MCP) sont rapportés, non exigés. Exécuté sur des versions passées, il trouve 0.22.0 absente de npm et de PyPI, 0.23.0 de PyPI et 0.27.0 de crates.io.
    • Des binaires de ligne de commande précompilés pour macOS (Apple silicon et Intel) et Windows x86-64, nommés par cible (kshana-aarch64-apple-darwin et ainsi de suite), à côté du kshana Linux, dont le nom est inchangé. Un fichier SHA256SUMS couvre chaque ressource, et verify-release le vérifie et exécute les binaires macOS et Windows sur leurs propres systèmes.
    • kshana.dev montre une version publiée, pas main. Il se redéployait à chaque push sur main alors que ses pages nommaient la dernière version. pages.yml ne construit maintenant qu'une étiquette de publication : la publication le déclenche une fois que chaque canal sert la version, et un déclenchement manuel redéploie la dernière version (ou une version nommée).
    • Une seule source de roues. La matrice de six cibles copiée à la main de publish.yml a disparu ; il appelle wheels.yml, de sorte que le portail d'étiquettes auditwheel et la vérification de reproductibilité à l'octet près évaluent maintenant les roues que PyPI reçoit, et qu'un échec de l'un ou de l'autre arrête la publication.
    • Outils de construction fixés. Chaque workflow demande Rust 1.93.0 (la tâche msrv sa propre version) ; publish.yml et pages.yml avaient demandé @stable, et le journal de v0.27.2 montre rustup installant 1.98.1 puis compilant avec 1.93.0 seulement parce que rust-toolchain.toml l'emporte sur lui. wasm-pack est fixé à 0.13.1 (la version qui a construit v0.27.2, que le script d'installation non fixé a choisie) avec une vérification de somme de contrôle, et mcp-publisher à 1.8.1 avec son SHA-256 publié. scripts/check-toolchain.sh échoue maintenant si un workflow demande un autre compilateur ou envoie un script téléchargé dans un shell. Aucune tâche de vérification, aucune épingle de référence ni aucun script de portail local n'a été retiré ou assoupli.

Sécurité#

  • Chaque GitHub Action tierce est fixée par SHA de commit — 93 références dans 15 workflows, dont 92 nouvellement — avec l'étiquette gardée en commentaire final pour que Dependabot la mette à jour. L'exception est dtolnay/rust-toolchain, dont l'étiquette est le sélecteur de chaîne d'outils.

  • Les couches de base de l'image du serveur MCP sont fixées par empreinte multi-architecture, et Dependabot surveille maintenant le Dockerfile de mcp/kshana-mcp, de sorte que les couches de l'OS reçoivent toujours les mises à jour de sécurité — par une PR relue.

  • La vérification étiquette contre manifeste s'exécute dans les deux workflows de publication qui livrent la version de l'étiquette. mcp-publish.yml (image ghcr, registre MCP) et jetbrains-plugin.yml (Marketplace) font concurrence à publish.yml au lieu de l'attendre, de sorte qu'une étiquette mal coupée n'était contrôlée que chez un voisin. Les deux exécutent maintenant scripts/check-version-sync.sh avant de construire.

  • Quatre avis de sécurité que Dependabot a levés le jour où ses alertes ont été activées sont corrigés. Le serveur MCP passe de rmcp 1,7 à 2,2 : trois avis contre rmcp < 2,1 (une fuite de la table de sessions Streamable-HTTP, une validation manquante de la ressource protégée OAuth, des en-têtes personnalisés suivant une redirection inter-origines) — aucun atteignable ici, puisque le serveur ne parle que stdio, mais un crate publié ne devrait pas fixer un SDK vulnérable. Les macros de rmcp 2 exigent Rust 1,88, de sorte que kshana-mcp seul déclare maintenant rust-version = "1.88" ; la bibliothèque kshana reste à 1,85. Le seul changement d'API (Content → ContentBlock) est appliqué, et les tests d'aller-retour passent. L'action d'analyse SonarQube passe de v5 à v6, ce qui corrige un avis d'injection d'arguments (≥ 4,0, < 6,0).

0.27.2 - 2026-09-22#

Ajouté#

  • Chaque élément Rust que cite une ligne de la matrice de vérification est maintenant résolu par rapport au crate. Le garde-fou existant vérifiait les citations en forme de chemins de fichiers ; 63 des 164 lignes hors partenaire nomment plutôt leur preuve comme un élément du crate — navsignal::code_tests, integrity::tpl_scalar::tests, api::tests::tracking_loop_kind_round_trips_through_the_dispatch — et un jeton sans suffixe .rs était invisible pour un analyseur de chemins. Ces lignes auraient pu nommer un module renommé, un module de test vidé ou une fonction qui n'a jamais existé, et chaque portail serait resté au vert.

    tests/verification_rows_name_a_test_that_exists.rs résout les 339 citations de ce type par l'arbre des modules, exige que chaque ligne hors partenaire nomme au moins un test qui porte effectivement #[test], et exige que les lignes de partenaire n'en nomment aucun. Quatre mutations ont servi à l'évaluer : renommer un module cité, faire pointer l'unique citation de test d'une ligne vers une fonction qui n'est pas un test, renommer le vrai mod tests, et en retirer les attributs #[test] — chacune passe au rouge sur l'assertion qui lui correspond.

    Une ligne était déjà fausse : Alternative / complementary PNT citait tests/*, un motif glob, ce qui n'est pas une citation. Elle nomme maintenant tests/alternative_complementary_pnt_reference.rs et les trois modules de test du crate qui la soutiennent.

  • Les figures publiées sont revérifiées par rapport au moteur à chaque construction (tests/published_figures_still_reproduce.rs). Les trois graphiques de démonstration du README sont la propre sortie chart.svg du moteur et rien ne réexécutait le scénario ; les deux études de croisement de l'article avaient été générées une fois et versionnées ; et le README énonce en prose quatre figures de mérite à côté de scenario-fom.png. Les trois sont maintenant fixées sur la sortie du moteur en direct.

    Les réconcilier a donné le résultat utile : les graphiques de démonstration avaient été dessinés au moteur 0.22.0 et le JSON de croisement de l'article à 0.20.0, et à 0.27.1 chaque valeur tracée dans les cinq artefacts est identique — les trois SVG de graphiques diffèrent d'une exécution neuve d'exactement deux caractères chacun, la marque de version dans le pied de page. Les graphiques ont été rendus de nouveau pour que le pied de page soit vrai. Le JSON de l'article est volontairement laissé estampillé 0.20.0 : c'est l'enregistrement de l'exécution dont un article publié intègre la figure, et le réestampiller prétendrait une provenance que le PDF n'a pas. Le garde-fou affirme à la place la propriété plus forte — que le moteur actuel reproduit toujours chaque valeur publiée.

Corrigé#

  • Les analyses SonarCloud étaient enregistrées comme VERSION=not provided, de sorte que la période de nouveau code previous_version n'avançait jamais : elle restait ancrée sur l'analyse du 2026-07-02, évaluant quatre-vingt-deux jours de travail comme un seul delta et mesurant 7877 lignes dupliquées « nouvelles » face à un seuil de 3 %. L'analyse transmet maintenant la version du crate. La duplication sous-jacente est réelle et n'est pas masquée par cela : elle est concentrée dans les registres déclaratifs FieldUnit répétés dans ensemble, hybrid, fusion, inertial et report, et dans le tableau de vérification de 168 lignes, et elle est nommée ici comme du travail à faire plutôt qu'exclue de la mesure.

  • scripts/gate.sh n'avait pas de verrou à écrivain unique, et chaque exécution écrivait le même journal. Ce n'est pas de la coquetterie : les integration_binaries, tests_passed et tests_ignored du reçu sont relus DANS ce journal, et le hook de pré-push fait confiance au reçu. Un portail qui avait été tué mais dont le binaire de test était encore vivant continuait d'écrire dans le fichier que l'exécution suivante venait de tronquer — de sorte que les comptes d'une exécution pouvaient être attestés comme ceux d'une autre, autorisant un push sur la foi d'une suite qui n'avait jamais été exécutée sur l'arbre poussé. Il y a maintenant un seul portail par copie de travail (refusant avec la sortie 75 à côté d'un portail vivant, effaçant un verrou périmé dont le pid a disparu) et un journal par exécution, avec target/gate-run.log rafraîchi à partir de l'exécution qui se termine en sortant. Les deux sens sont testés : un pid vivant refuse, un pid mort est effacé.

  • src/verification.rs affirmait que ses tests ne prouvent « do not prove the named test/oracle strings resolve to live code ». Deux garde-fous le font maintenant exactement, de sorte que la documentation du module disait le contraire de la vérité ; elle énonce maintenant ce qui est vérifié par machine et ce qui est laissé au jugement humain. Une référence périmée à verification::gen — le module est artifacts — est corrigée dans la propre documentation du garde-fou voisin.

Modifié#

  • main a été réécrite le 2026-09-22 et poussée de force. Dix commits sont devenus quatre. La réécriture a replié chaque commit qui avait laissé un portail au rouge dans le commit qui l'a rétabli, de sorte que chaque commit sur main a maintenant un arbre qui passe, et a retiré les exécutions annulées qu'un groupe de concurrence à l'échelle de la branche laissait sur chaque commit remplacé.

    Rien n'a été jeté. Les commits d'avant la réécriture restent atteignables par les étiquettes qui les désignent, et l'arbre final est identique octet pour octet à l'arbre dont la réécriture est partie — git diff entre l'ancien sommet et le nouveau est vide, hormis les trois fichiers de workflow que cette version change.

    Les SHA remplacés, pour quiconque détient une référence vers l'un d'eux :

    ancien sujet
    9733177 docs(changelog): disclose the authorship rewrite and the two dangling crate sha1s
    5d16ea8 fix(docs): the engine-flow diagram said 6 figures of merit; the engine scores 7
    148d31d fix(test): two more cross-platform pins, and two wrong assumptions of my own
    a3a2667 feat(web): surface the lunar cluster on the site — seven capability cards
    1e8bec6 docs(lunar): document 42 public fields and ratchet the ceiling down to 985
    7bba514 chore(release): v0.27.0
    3154548 test(docs): guard the distribution diagram, the last unguarded one
    7864142 chore(release): v0.27.1

    Les étiquettes v0.27.0 et v0.27.1 n'ont délibérément PAS été déplacées. Elles pointent toujours vers 7bba514 et 7864142, les commits exacts dont les arbres ont produit les artefacts maintenant en ligne sur crates.io, npm, PyPI, ghcr.io et le registre MCP. Le .cargo_vcs_info.json d'un crate consigne le sha1 à partir duquel il a été empaqueté, les registres sont immuables, et l'attestation de provenance de construction SLSA sur les ressources de la version v0.27.1 est liée à ce commit. Déplacer les étiquettes aurait laissé chacun de ces artefacts publiés pointer vers un commit qui n'existe plus. Les laisser garde les anciens commits atteignables et chaque chaîne de provenance publiée résolue, au prix de deux étiquettes qui ne sont plus des ancêtres de main — ce qui est la raison d'être de cette version : v0.27.2 donne à main une étiquette à elle, empaquetée à partir d'un commit qui s'y trouve.

    Ceci est la deuxième réécriture divulguée de cet historique ; la première, le 2026-09-21, a canonisé la paternité et est consignée dans les notes de 0.27.0 avec ses deux sha1 de crate orphelins. Une réécriture est divulguée ici chaque fois, parce qu'un dépôt qui vend une provenance vérifiable ne peut pas déplacer discrètement le sol sous un artefact publié.

0.27.1 - 2026-09-22#

Corrigé#

  • Le crate publié ne compilait pas. src/lunar_orientation.rs contient un include_str! de niveau supérieur de tests/fixtures/llr_geometry/de440_moon_pa.csv, et le manifeste exclut /tests/fixtures du paquet, de sorte que l'archive que reçoit crates.io manquait d'un fichier que la bibliothèque intègre elle-même. La publication de v0.27.0 a échoué à sa construction de vérification pour cette raison et aucune 0.27.0 n'a atteint crates.io ; npm et PyPI, dont les tâches n'en dépendent pas, ont publié normalement. L'exclusion porte maintenant une exception pour ce seul catalogue.

    Tout autre include_str! d'une donnée de test dans src/ se trouve dans un module #[cfg(test)] et n'atteint donc jamais la bibliothèque empaquetée. Seul celui de niveau supérieur l'atteint.

  • Rien dans la CI n'exécutait cargo package, ce qui explique qu'une archive qui ne peut pas compiler ait d'abord été découverte par la tâche de publication, après que deux autres registres avaient déjà livré. Une tâche package construit et compile maintenant l'archive exacte à chaque push.

Modifié#

  • Les épingles d'émission de la réalisation du référentiel lunaire ne bougent plus à chaque changement de version. Le pied de page du SVG porte la version du moteur, de sorte que chaque version rebasait trois hachages — deux fois en un jour — et une épingle reprise par routine cesse d'être lue. La chaîne de version est normalisée en un substitut avant le hachage, et il est affirmé séparément que l'émission indique la version en cours d'exécution, de sorte que ce fait est vérifié plus précisément que le hachage ne l'a jamais vérifié.

0.27.0 - 2026-09-22#

Ajouté#

  • lunar-llr-datum — la donnée de référentiel lunaire issue d'une vraie campagne d'observation. lunar-frame-campaign remplaçait une transformation de Helmert injectée par une campagne simulée et le disait : son réseau de stations, son calendrier et son écart-type par observation sont des entrées illustratives. Ce scénario retire la simulation des deux endroits où un calendrier et un modèle d'erreur entrent dans la réponse. Les époques sont les instants d'émission de 337 points normaux archivés de télémétrie laser lunaire de l'ILRS (2015-04-08 .. 2015-06-27, Grasse MeO 7845 et Matera MLRO 7941, les cinq réseaux de rétroréflecteurs), et chaque poids d'observation est la propre précision archivée de ce point normal, bin_rms / sqrt(n_raw) — une médiane de 5,13 mm de distance aller simple, tirée du fichier plutôt que choisie ici. Les coordonnées des stations viennent de l'ITRF2020 de l'IERS et celles des réflecteurs du tableau 7 du JPL DE430 ; chaque jeu de données de test consigne une URL, une date de récupération et un SHA-256 et se régénère à partir de sa source par un générateur versionné qui vérifie la source et s'interrompt plutôt que d'émettre un nombre. Le rapport nomme quels liens sont mesurés et lesquels restent modélisés, et les modélisés sont mesurés : la distance aller simple observée moins calculée sur les données réelles est de 156 494 m RMS, ce que le même ensemble de tests confirme par rapport à JPL Horizons sur la même période (195 655 m RMS vectoriel, pire époque 0,054° — dans les ~0,3° que la série lunaire analytique intégrée revendique pour elle-même). Additif : un nouveau type de scénario, un nouveau lecteur (realdata::llr_crd) et un nouveau module (lunar_llr) ; les paquets de référentiel lunaire existants sont fixés bit pour bit.

  • sigma_ure_m comme paramètre de scénario sur lunar-integrity et moonlight-service-volume. La précision de mesure de distance du signal dans l'espace était une constante de compilation (LUNAR_SIGMA_URE_M), de sorte qu'un balayage du volume de service ne pouvait répondre que par réussite ou échec à une valeur fixe. Les niveaux de protection y sont exactement linéaires, de sorte que l'exposer transforme le balayage en une exigence de précision de mesure de distance sur tout le volume. La valeur par défaut reproduit le comportement antérieur bit pour bit.

  • Export de la géométrie par satellite sur moonlight-service-volume : export_site_lat_deg + export_site_lon_deg ajoutent un tableau per_sat_geometry donnant l'azimut, l'élévation et la distance oblique vers chaque satellite à chaque époque pour un site sélénographique nommé, plus l'indicateur de visibilité. La synthèse agrégée de couverture écrase délibérément la géométrie par satellite, mais la distance oblique est exactement ce qu'un bilan de liaison consomme, de sorte qu'une analyse conjointe de communications et de navigation ne pouvait pas être faite à partir de la seule synthèse. Désactivé sauf si les deux coordonnées sont données ; purement additif.

  • lunar_service::topocentric, la fonction d'aide publique d'angles de visée derrière l'export.

  • Une ligne de la matrice de vérification pour la nouvelle capacité de géométrie.

  • Le diagramme d'antenne réel dans l'export de géométrie. Le moteur porte un diagramme d'ouverture circulaire uniformément éclairée depuis P1 (antenna::pattern_gain_dbi, la forme d'Airy [2·J₁(x)/x]²) et rien en dehors de antenna.rs ne l'utilisait — un gain dans l'axe associé à une règle empirique gain-largeur de faisceau faisait le travail à la place. Un tableau export_antenna facultatif sur moonlight-service-volume (lu seulement lorsque le site d'export est défini) donne maintenant à chaque ligne exportée l'angle hors de l'axe au satellite et le gain d'émission vers le site issu de ce diagramme, et ajoute un bloc antenna_pattern qui rapporte le nombre dans le faisceau selon le diagramme réel à côté du nombre dans le faisceau selon l'approximation symétrique (θ₃dB[deg] = √(31000/G_lin)) avec la différence comme correction nommée. Les deux nombres sont émis ; aucun ne remplace l'autre. Mesurés à l'ouverture lunaire représentative du moteur lui-même (parabole de 1 m, 2,4 GHz, η = 0,60) sur un site polaire sud et la couche illustrative de classe LCNS, les deux divergent de plus d'un satellite : le diagramme réel place 0 des 76 liaisons visibles dans le faisceau à mi-puissance, l'approximation en revendique 28 — une correction de −2,33 satellites par époque, pire époque isolée 3. L'approximation porte une efficacité d'ouverture propre (0,641 contre la règle des 70·λ/D degrés avec laquelle elle est d'ordinaire citée, 0,920 contre une ouverture circulaire uniforme), de sorte que sur une parabole η = 0,60 elle renvoie un faisceau 1,238× trop large ; le bloc émet les deux efficacités impliquées plutôt que de les laisser se déduire. Purement additif : mesuré sur le point de fonctionnement documenté, 597 feuilles préexistantes, 0 changée, 0 retirée, 494 ajoutées.

  • antenna::symmetric_beamwidth_rad, antenna::symmetric_relation_implied_efficiency, antenna::within_half_power_beam, antenna::HALF_POWER_DROP_DB, antenna::SYMMETRIC_GAIN_BEAMWIDTH_CONST_DEG2, antenna::UNIFORM_APERTURE_HPBW_COEFF et lunar_service::nadir_off_boresight_rad, les éléments publics qui la soutiennent. Le diagramme est aussi maintenant ancré sur les constantes d'Airy publiées plutôt que seulement sur lui-même : le franchissement à mi-puissance est localisé par bissection et comparé à x = 1.61634, ce qui donne la largeur exacte à mi-puissance 1.02899·λ/D et consigne honnêtement que le coefficient conventionnel 1.02 place pattern_gain_dbi à −2,955 dB, et non −3,010 dB.

  • Un tableau de reproductibilité au format long pour lunar-time-budget. Les sorties à valeurs de tableau du scénario — la grille de temps de moyennage, les sept courbes x(τ) par terme et leur total en somme quadratique — n'atteignaient les consommateurs que sous forme de tableaux JSON. Un tableau publié avait été tronqué à 400 caractères et publiait 23 de ses 57 temps de moyennage sous une colonne qui les annonçait tous, et le manuscrit reconstruisait les courbes par terme à partir de formes closes parce que le moteur ne les avait jamais émises. Une exécution simple écrit maintenant aussi <scenario>.table.csv avec une ligne par (indice de grille, temps de moyennage, terme), qui ne peut pas être tronqué en quelque chose qui a encore l'air complet. L'indice de grille est une clé de jointure exacte ; τ est écrit sur 13 chiffres significatifs et chaque x sur 7, de sorte que les octets ne divergent pas entre les constructions d'une même source. Purement additif : le JSON du rapport est identique octet pour octet.

  • Le rapport hybrid-optical-rf se décrit maintenant lui-même. Un bloc link_configuration reprend les entrées de liaison résolues — longueur d'onde de la porteuse, ouverture d'émission et de réception, distance, largeur d'impulsion, temps d'intégration, rendements et pertes — avec les valeurs par défaut appliquées, de sorte qu'un article énonce la configuration avec laquelle il a tourné au lieu de citer une valeur par défaut lue dans la source. Un bloc units donne l'unité et la classe de provenance de chaque grandeur qu'un article est susceptible de citer. Les traces de covariance de transmission en sont la raison d'être : elles étaient émises sous un simple variance et un manuscrit en déduisait des mètres carrés à partir d'un contrôle de cohérence interne. La déduction était juste, ce qui est précisément pourquoi c'était un défaut — rien n'aurait détecté qu'elle soit fausse. Purement additif : mesuré sur quatre configurations, 456 champs préexistants, 0 changé, 0 retiré, 196 ajoutés.

  • Une ligne de la matrice de vérification pour le tableau de reproductibilité du budget de temps, honnêtement InternalConsistency / MODELLED — le total est vérifié par rapport à la somme quadratique des termes du même fichier, qui partage les propres définitions de termes du moteur et n'est donc pas une référence indépendante. Ensemble, elles ajoutent trois lignes. Le total courant pour cette section non publiée est de 168 lignes — 64 VALIDATED, 100 MODELLED, 4 PARTNER.

Modifié#

  • La paternité des commits sur tout l'historique est maintenant une identité unique, et deux crates publiés pointent vers un commit qui n'existe plus. Le 2026-09-21, l'historique git a été réécrit de sorte que chaque commit humain soit écrit et validé par ashfordeOU <236818772+ashfordeOU@users.noreply.github.com>. Il portait auparavant trois graphies d'une même personne — 688 commits sous ashfordeOU <contact@ashforde.org>, 34 sous Chakshu Baweja <contact@ashforde.org> et 94 déjà canoniques. L'unique commit de dependabot[bot] a été délibérément laissé sous son propre auteur : rebaptiser la mise à jour de dépendance d'un robot reviendrait à revendiquer la paternité d'un travail que personne ici n'a fait.

    Aucun contenu n'a changé. La réécriture n'a touché que les en-têtes d'auteur et de validateur, et cela se vérifie plutôt que d'être affirmé : l'arbre de chaque étiquette et de chaque branche est identique au bit près à ce qu'il était avant. v0.26.0 se résout toujours vers l'arbre 92284e9420605568f1bfabb78cd95d383b40f3e2, exactement comme avant.

    Ce que cela a coûté. Le nom d'un commit est un hachage de son arbre, de ses parents et de ses en-têtes d'auteur, de sorte que changer un ancêtre renomme chaque descendant. Le commit de publication v0.26.0 était dce2dbf7700788cf6de46260c14673c0e5347360 et est maintenant d4921f3025569e00e425e1747d0acfc261e96e18. Deux artefacts ont consigné l'ancien nom au moment de la publication et ne peuvent pas être corrigés, parce qu'une version publiée dans un registre est immuable par conception :

    • kshana 0.26.0 sur crates.io — .cargo_vcs_info.json consigne dce2dbf…
    • kshana-mcp 0.26.0 sur crates.io — le même sha1, path_in_vcs: mcp/kshana-mcp

    Rien d'autre n'est touché. Le paquet npm ne consigne aucun gitHead, et la distribution PyPI ne consigne aucun commit du tout ; les deux ont été vérifiés plutôt que supposés.

    Aucune réparation ne fait que dce2dbf… nomme le commit réécrit : cette chaîne est l'ancienne ascendance, et la seule façon de la résoudre est de garder publié l'historique d'avant la réécriture, ce qui rétablirait la paternité que la réécriture a retirée. La provenance de 0.26.0 passe donc par l'étiquette plutôt que par le sha1 consigné — et l'étiquette fournit les octets identiques à partir desquels le crate a été construit. La prochaine version consigne un commit valide sans qu'aucune action ne soit nécessaire.

Corrigé#

  • realtime-frame-eop prenait par défaut un fichier EOP sans ligne de prédiction (G12). Le scénario intégrait un extrait finals2000A de cinq lignes finales seulement comme valeur par défaut hors ligne, de sorte qu'une exécution nue rapportait predicted_rows.n = 0 et que le tableau par horizon reposait sur 5, 4, 3 et 2 paires. Le moteur pouvait toujours lire une ligne de prédiction — l'entrée n'en avait simplement aucune. La valeur par défaut est maintenant l'extrait IERS 2026 textuel (tools/finals2000A_2026.txt, MJD 61173–61204) : 20 finales du Bulletin B et 12 lignes de prédiction seule du Bulletin A, de sorte qu'une exécution nue sans argument de fichier et sans réseau rapporte predicted_rows.n = 12 et un tableau par horizon à n = 20 / 31 / 30 / 29, et la comparaison avec le prédicteur opérationnel et l'accord avec les propres prédictions publiées du produit se remplissent aussi. L'extrait de 45 lignes sur longue période a été mesuré comme alternative et rejeté : il est lui aussi finales seulement, ce qui aurait laissé predicted_rows.n à 0. Cela déplace des nombres publiés, selon la règle R4 et avec l'autorisation du fondateur : dix des 22 cellules de p4_frame_eop.csv publié et 24 des 42 cellules remplies de tests/golden/realtime-frame-eop.csv. Le plancher de pôle rapide moins final mesuré devient 0,0678 mas (contre 0,0769 mas), valeur que le propre tableau de mouvement du pôle de l'article P4 publie déjà à n = 20 — les deux concordent maintenant au lieu de différer de 13,5 %. Tout autre chiffre que P4 imprime à partir de ce tableau est inchangé à la précision imprimée. L'énumération complète ancien → nouveau, y compris les champs qui n'ont pas bougé, se trouve dans docs/revisions/G12-default-eop-cell-changes.md. L'extrait finales seulement reste livré, fixé octet pour octet et exercé : un nombre nul de lignes de prédiction sur lui est la propriété du fichier, et un test le prouve toujours.

  • Un plafonnement obsolète du nombre de satellites dans moonlight-service-volume. Le scénario plafonnait n_sats à 12 alors que son propre constructeur de constellation en gère 24 et qu'un test affirme 24 : chaque nombre demandé au-dessus de 12 était donc réduit en silence, et un balayage du nombre de satellites renvoyait des valeurs identiques au-delà de 12 — impossible à distinguer d'une véritable saturation géométrique. Le plafond est désormais fixé à la limite du constructeur. Il s'agit d'un changement de comportement pour n_sats > 12 uniquement.

  • Le même plafonnement obsolète dans lunar-differential-pnt. lunar_dpnt plafonnait n_sats à 12 avec la même conséquence, et celle-ci a atteint un tableau publié : dpnt_nsats_sweep.csv contient une ligne n = 16 identique octet pour octet à sa ligne n = 12, car le moteur renvoyait une réponse à douze satellites sous une étiquette à seize satellites. Le plafond est désormais fixé à la limite du constructeur, soit 24, et un nouveau test la verrouille — chaque constellation plus grande doit à la fois indiquer son propre nombre et améliorer strictement le niveau de protection, de sorte que le plafonnement ne puisse pas revenir sans être remarqué. Cela modifie des chiffres publiés : le niveau de protection pour n = 16 passe de 16,92 m à 14,57 m. Balayée jusqu'à 24, la courbe est strictement monotone (11,94 m à 24 satellites, soit 29,5 % de mieux qu'à 12), il n'y a donc pas de saturation à 12 — le plateau apparent était le plafonnement. Changement de comportement pour n_sats > 12 uniquement.

0.26.0 - 2026-09-18#

Une version de documentation, de transparence et de bac à sable. Aucun changement de comportement du moteur : la matrice de vérification s'établit à 102 lignes — 56 VALIDATED, 42 MODELLED, 4 PARTNER, sans changement par rapport à 0.25.0.

Ajouté#

  • Rustdoc au niveau de la crate (//! dans lib.rs) couvrant les points d'entrée, le modèle d'honnêteté et de niveaux de preuve, et la reproductibilité, de sorte que docs.rs s'ouvre sur une vraie page d'accueil plutôt que sur un simple mur de modules.
  • docs/SCENARIOS.md — une référence par type pour les 50 types de scénario, générée à partir de api::list_scenario_kinds() (la source de vérité unique) par gen_validation_artifacts et protégée par tests/scenarios_reference_doc_sync.rs, de sorte qu'elle ne peut pas diverger du répartiteur.
  • Documentation des modules pour les 11 modules publics jusque-là non documentés (allan, estimator, fom, hybrid, inertial, models, report, run, scenario, timetransfer, types).
  • Sources bibliographiques pour cinq modules de formules qui énonçaient une équation sans nommer de référence : batch_ls (Tapley/Schutz/Born ; Bjorck), cr3bp (Szebehely ; Koon et al.), detection (Kay), attitude_budget (Wertz ; Sidi), reentry (Allen-Eggers, NACA TR-1381).
  • Un fichier security.txt publié sur kshana.dev pour la divulgation coordonnée.
  • Niveau de validation par exécution dans le bac à sable. Le tableau des figures de mérite d'une exécution unique comporte désormais une pastille VALIDATED/MODELLED par figure, lue à partir de la même recherche fomTier() que celle du rapport téléchargeable (qui reprend src/fom_label.rs, lui-même dérivé de la matrice de vérification), de sorte que le niveau affiché à côté d'une valeur en direct ne peut jamais contredire le registre.
  • lunar-attack-surface dans le menu du bac à sable — les 50 types de scénario exécutables sont désormais accessibles en un clic (contre 49/50 auparavant).
  • Cinq autres cartes de capacité exécutables (météorologie spatiale, évaluation des perturbations RF, résilience, interopérabilité CCSDS OEM, KIF), ce qui porte les cartes exécutables de 11 à 16. Les cartes réservées à l'API et à la bibliothèque conservent un lien honnête vers la documentation plutôt qu'un faux bouton d'exécution.

Modifié#

  • La couverture de la documentation est désormais verrouillée par cliquet dans la CI. check-doc-coverage.sh compile la bibliothèque avec missing_docs, compte les avertissements, et n'échoue que si ce nombre dépasse un plafond fixé (986). Un #![warn(missing_docs)] strict sous -D warnings aurait transformé environ 1000 éléments publics actuellement non documentés en une rupture de compilation du jour au lendemain ; ainsi, les nouveaux éléments publics non documentés font échouer la compilation, tandis que l'arriéré existant est résorbé de façon délibérée.

Corrigé#

  • La ligne de l'outil MCP list_scenario_kinds annonçait «¤~17 types de scénario intégrés¤» alors que api::list_scenario_kinds() en exposait 50 depuis un certain temps — une documentation destinée aux agents qui sous-estimait d'un facteur trois la capacité réelle. Alignée sur le nombre exact.
  • Régénération de la référence indépendante de concordance du SBOM CycloneDX pour le graphe de dépendances mis à jour (60 composants). Le verdict de concordance est inchangé : zéro erreur de schéma normalisée, et chaque identifiant atomique de licence figure toujours dans l'énumération SPDX officielle.

0.25.0 - 2026-07-15#

Ajouté#

  • Cinq capacités promues au niveau VALIDATED externe, chacune étant désormais recoupée avec une implémentation tierce indépendante de la même grandeur définie de façon unique (non circulaire, avec des jeux de test régénérables hors ligne) :
    • Conversion loi de puissance IEEE-1139 → écart-type d'Allan par rapport aux formes closes de allantools pour les cinq types de bruit (tests/powerlaw_oadev_reference.rs) ;
    • Poids du formateur de faisceau CRPA MVDR / à annulation de norme minimale par rapport à numpy/scipy LAPACK (tests/crpa_reference.rs) ;
    • Détermination d'attitude Wahba / TRIAD / QUEST par rapport à la SVD Rotation.align_vectors de SciPy sur des observations sans bruit (tests/wahba_reference.rs) ;
    • Échange de blocs de covariance OEM CCSDS 502,0 avec un aller-retour via l'analyseur de la bibliothèque indépendante oem (tests/ccsds_oem_covariance_reference.rs) ;
    • le noyau des statistiques de détection d'acquisition à loi quadratique (Marcum-Q généralisée / P_d / P_fa / seuil) par rapport à ncx2/chi2 de SciPy (tests/acquisition_reference.rs). La matrice de validation vérifiée par machine passe à 56 VALIDATED · 42 MODELLED · 4 PARTNER sur 102 lignes (contre 51 · 47 · 4). Les réserves honnêtes sur la portée sont conservées — par exemple, la promotion de l'acquisition ne couvre que le noyau des statistiques de détection ; le CFAR et la perte par chevauchement restent MODELLED.
  • Figures de mérite dans le domaine de la position (fom::positioning_performance) : CEP, SEP et 2DRMS exacts à partir de la covariance de position ENU 3D d'une solution de navigation, plus un niveau de protection horizontal. Le CEP et le SEP sont les erreurs radiales médianes exactes (et non la règle linéaire 0.589·(σ₁+σ₂)), recoupées avec les quantiles rayleigh/maxwell de scipy.stats et avec une médiane Monte-Carlo NumPy indépendante (tests/positioning_fom_reference.rs). Remplace l'ancien module factice qui indiquait honnêtement ne pas être implémenté — la signature de la fonction a changé : de () renvoyant une erreur à (cov_enu, hpl_m) renvoyant un PositioningFom.
  • Degrés de liberté équivalents (EDF) des intervalles de confiance achevés pour tous les estimateurs de la famille d'Allan (assurance::uncertainty::edf) : les EDF de l'écart d'Allan modifié, de Hadamard et de la variance totale utilisent désormais l'algorithme d'EDF combiné de Greenhall et Riley et la forme TOTVAR du tableau 7 du NIST SP 1065 (auparavant, seul l'EDF de l'écart d'Allan à recouvrement était implémenté ; les autres le réutilisaient en silence), recoupés avec allantools edf_greenhall/edf_totdev (tests/uncertainty_edf_reference.rs).
  • Recoupements externes indépendants pour les capacités de géométrie PNT lunaire, de DOP, d'EOP, de DRO et de télémétrie RF (tests/validate_p*.rs, avec des jeux de test et des générateurs de référence indépendante sous tests/fixtures/{p1_footprint,lunar_service,eop_prediction,rf_ranging_precision,dro_family_jpl,p2_independent_dop}/). Chaque recoupement soumet une capacité modélisée déjà livrée à une référence indépendante produite par une implémentation différente, de sorte que l'accord est non circulaire : l'empreinte orbitale d'émission/de capture par rapport à scipy.special.j1 (Cephes — une fonction de Bessel J1 réellement différente) ; le DOP de la géométrie des balises de surface par rapport à une résolution NumPy indépendante de (HᵀH)⁻¹ ; la croissance de l'erreur de prédiction de la persistance UT1/EOP par rapport à une nouvelle analyse NumPy distincte des mêmes lignes IERS finals2000A textuelles ; la famille d'orbites rétrogrades distantes planes par rapport à la base de données NASA/JPL Three-Body Periodic Orbit Database ; et le budget de précision de la télémétrie RF par rapport à une référence issue des premiers principes. Ce sont des preuves de régression supplémentaires pour des modules existants ; l'ajout de ces tests de recoupement ne change à lui seul le statut d'aucune capacité (les cinq promotions ci-dessus sont des changements de statut distincts, adossés à une référence indépendante, dans src/verification.rs).
  • Scénario lunar-attack-surface (src/attack_surface.rs, kind = "lunar-attack-surface") : une exécution P1 composée, accessible en binaire (CLI / Python / MCP / wasm via run_toml), de sécurité des signaux lunaires, qui assemble le déficit de puissance du bilan de liaison et sa bande de sensibilité de 12 à 18 dB, la puissance d'émission de brouillage/leurrage requise en fonction de la distance de sécurité, l'empreinte orbitale de capture sous un diagramme d'antenne réel, le résultat de l'accrochage de capture par leurrage dans la boucle de poursuite, la portée d'horizon d'un corps sans atmosphère, et le budget d'authentification OSNMA/TESLA. Un corps vide reproduit la référence de base P1.
  • Bande de sensibilité du déficit de puissance (linkbudget::deficit_sensitivity_band, deficit_power_factor) : un véritable balayage multi-axes (référence × PIRE × distance oblique) construit sur sweep::SweepAxis et évalué via received_signal_power_dbw, qui reproduit la bande P1 de 12 à 18 dB et réconcilie les facteurs linéaires de 32× (arrondi) et de 36× (non arrondi).
  • Cube de capture par leurrage en trois dimensions (spoof_capture::capture_cube) : ajoute l'axe du décalage de porteuse/Doppler à la carte de capture (J/S × décalage de code × décalage de porteuse, temps d'accrochage par cellule) ; la tranche à porteuse nulle se réduit exactement à la capture_map en 2D.

Modifié#

  • La détection par réseau clairsemé de moniteurs (monitor_network) compose désormais la statistique AGC physique de spoof_monitors et la grille de visibilité sélénographique de lunar_service pour dériver la statistique de détection et la géométrie de chaque station, au lieu de paramètres libres et d'un recouvrement ad hoc par grand cercle ; les probabilités de détection par moniteur et pour le réseau restent les formes closes du khi-deux/Marcum-Q de detection. Les champs SurfaceMonitor / SpoofEvent ont changé pour devenir des grandeurs physiques (lat/lon/alt/puissance).

Corrigé#

  • Dimensionnement de la surcharge d'authentification OSNMA/TESLA (nma_budget) : les portions de champ OSNMA par page (HKROOT de 8 bits + MACK de 32 bits par page de 2 s) étaient étiquetées à tort comme des totaux par sous-trame, ce qui sous-estimait la surcharge d'un facteur 15 (1,33 bit/s). Corrigé selon les totaux publiés par sous-trame de 30 s dans le SIS-ICD (HKROOT 120 + MACK 480 bits ⇒ 20 bit/s). La conséquence est désormais énoncée honnêtement : à un débit de message de navigation AFS de 50 bit/s, la surcharge d'authentification représente un coût de premier ordre d'environ 40 %, et non quelques points de pourcentage négligeables ; le champ auth_latency est documenté comme le délai de divulgation de la clé (une borne inférieure du délai de bout en bout avant la première position authentifiée).

0.24.0 - 2026-07-09#

Une version à large portée en matière de capacités. Elle apporte deux suites d'analyse entièrement validées en externe — une famille complète d'analyse de décision multicritère (MCDA) et les estimateurs de dérive d'Allan / stabilité d'horloge à long τ — et ouvre, au-dessus du substrat, une nouvelle couche de scénarios exécutables : budget temporel lunaire, référentiel/EOP en temps réel, hybride optique/RF, observabilité cislunaire et résilience aux conflits d'un PNT en couches, ainsi qu'un substrat de capacités de balise de surface lunaire et de sécurité des signaux. La matrice de validation vérifiée par machine passe à 51 VALIDATED · 47 MODELLED · 4 PARTNER sur 102 lignes (contre 40 · 47 · 4 sur 91) : les onze nouvelles lignes sont toutes des validations par référence indépendante externe des estimateurs d'analyse de décision et de synchronisation temporelle, vérifiées avec une tolérance serrée par rapport à des bibliothèques indépendantes (SciPy, pymcdm, pyDecision, allantools), tandis que la nouvelle surface de capacités PNT est présentée honnêtement comme MODELLED. Comme toujours, aucune affirmation de modèle numérique n'est relevée de niveau sans un jeu de données externe pour l'étayer.

Ajouté#

Scénarios exécutables — chacun étant un kind de scénario enregistré, acheminé par le moteur et prouvé de bout en bout par la CI grâce à tests/determinism.rs (qui exécute chaque scenarios/*.toml fourni et échoue systématiquement dès qu'une fixture est inexécutable) :

  • Résilience aux conflits d'un PNT en couches (conflict-resilience, src/conflict_resilience.rs) — un moteur de résilience Monte-Carlo à graine fixée pour une architecture PNT multicouche, avec un modèle de survie par vecteur à dégradation progressive du § 4,2 (quatre vecteurs de menace nommés, la forme close de survie du PNT utilisable vers laquelle converge chaque Monte-Carlo par couche, émise dans le JSON du résultat) et une provenance des paramètres de menace documentée et protégée contre la dérive (src/conflict_threat_params.rs). Architectures MODELLED ; la convergence du Monte-Carlo de survie vers la forme close est le noyau validé.
  • Observabilité cislunaire (cislunar-observability, src/cislunar_observability.rs) — un spectre propre du gramien d'observabilité sur un arc, un générateur de graines d'orbite rétrograde distante (DRO) à correction différentielle, et un recoupement indépendant par filtre d'information en racine carrée dont la covariance a posteriori devient finie exactement au rang d'observabilité complet. Constellation MODELLED ; les invariants de rang, de gramien, de STM et de SRIF sont le noyau validé.
  • Continuité et intégrité d'un hybride optique/RF hétérogène (hybrid-optical-rf, src/hybrid_integrity.rs, src/optical_availability.rs, src/optical_linkbudget.rs, src/cross_raim.rs) — disponibilité et intégrité inter-domaines lorsque le PNT optique et le PNT RF sont combinés. MODELLED.
  • Budget temporel lunaire endogène (lunar-time-budget, src/lunar_time_budget.rs) et budget référentiel / EOP en temps réel (realtime-frame-eop, src/realtime_frame_eop.rs, src/frame_eop.rs) — les budgets P3/P4 de temps lunaire et d'orientation de la Terre, dérivés de manière endogène de la chaîne de synchronisation temporelle plutôt qu'affirmés. MODELLED.

Suites d'analyse validées en externe — des capacités de bibliothèque, chacune entrant dans la matrice sous la forme de nouvelles lignes VALIDATED (vérifiées par rapport à une référence externe indépendante, et non par une auto-vérification) :

  • Suite complète d'analyse de décision multicritère (MCDA) (src/mcda/) — les quatre familles de méthodes : agrégation de valeurs (WSM, WPM, WASPAS), système de rapports (MOORA) et proportionnelle (COPRAS), distance à l'idéal (TOPSIS), programmation de compromis (VIKOR) et surclassement (PROMETHEE II avec six formes de critère généralisé, ELECTRE I concordance/discordance) — plus les poids de priorité par vecteur propre de Perron AHP avec le seuil du rapport de cohérence de Saaty (CR < 0,10), l'utilité MAUT, l'extraction du front de Pareto et l'analyse de sensibilité aux poids. Les neuf agrégateurs reproduisent pymcdm / pyDecision et le vecteur propre AHP concorde avec SciPy/LAPACK, le tout à moins de 1e-9 (tests/mcda_*_reference.rs). Le diagramme en tornade de sensibilité est également présenté dans le scénario de résilience aux conflits.
  • Estimateurs de dérive d'Allan et de stabilité d'horloge à long τ (src/allan.rs) — MTIE (la statistique de dérive d'erreur temporelle crête à crête d'après laquelle sont rédigés les gabarits de synchronisation ITU-T G.810/G.823/G.8261), la dérive en domaine temporel MDEV et TDEV, et les estimateurs à portée étendue Theo1 / TOTVAR. VALIDATED par rapport à allantools sur la série NIST SP 1065 ; l'hybride ThéoH à biais retiré, construit sur TOTVAR, reste honnêtement MODELLED.
  • Banc d'assurance / de référence indépendante externe (src/assurance/) — un banc de références indépendantes relié directement à la barrière d'honnêteté de la CI, un enregistrement de provenance W3C-PROV avec une racine de Merkle déterministe, et des degrés de liberté équivalents de Greenhall ainsi que des intervalles de confiance du khi-deux sur les estimations de stabilité.
  • Point d'extension PackRegistry / ExternalPack (src/registry.rs, src/api.rs) — un point de répartition par lequel les paquets de capacités passent par un seul registre (la répartition intégrée se trouve sur le chemin critique de la CLI ; les paquets hors arbre se rattachent derrière un ExternalPack::register_into par défaut), protégé par une suite de tests de référence d'identité octet pour octet et par des barrières de CI autonomes / wasm32.

Substrat de capacités modélisées — de nouveaux modules de bibliothèque qui alimentent les scénarios ci-dessus et les suivants (pas encore un kind de scénario autonome) :

  • DOP de balise de surface lunaire (src/lunar_beacon.rs) avec budget de précision réalisée, balayage à N satellites et carte du GDOP, plus une éphéméride lunaire perturbée (src/lunar_perturbed.rs) et la géométrie d'horizon sans atmosphère / l'inverse de la puissance de leurrage / la bande de déficit AFS (src/jamming.rs, src/linkbudget.rs). Réutilise le noyau de DOP validé par gnss_lib_py.
  • Ingestion de MNT au format LOLA + visibilité directe sur le relief (src/realdata/lola_dem.rs).
  • Défense à trois couches de la sécurité des signaux — capture par leurrage, intégrité inter-capteurs et dimensionnement du réseau de moniteurs (src/spoof_capture.rs, src/cross_sensor_integrity.rs, src/monitor_network.rs) avec une empreinte d'antenne à faisceau orbital et un budget d'authentification OSNMA (src/antenna.rs, src/nma_budget.rs). MODELLED.

Modifié#

  • La matrice de validation et chaque artefact dérivé ont été régénérés à partir de la source de vérité unique (src/verification.rs) : le registre du site, les diagrammes de la carte des modules et de la provenance de la validation, ainsi que les chaînes de décompte du README et de chaque surface indiquent désormais 51 / 47 / 4 sur 102 (contre 40 / 47 / 4 sur 91) ; la garde d'honnêteté des décomptes analyse désormais tout l'historique git, et les figures du README sont harmonisées sur la palette de marque sombre.
  • Un seul pilote d'intégration adaptative partagé soutient désormais à la fois integrate et integrate_dopri (src/integrator.rs), ce qui supprime le pas d'intégration dupliqué.
  • Ajout à la CI de l'analyse statique SonarQube Cloud (Rust + couverture importée), avec des badges de notation de sécurité / maintenabilité / fiabilité dans le README.
  • Un passage nommant des clients d'IA tiers est omis ici ; il figure dans CHANGELOG.md sur GitHub.

  • Discipline de publication et de conditionnement : la CI enregistre un environnement de déploiement pour chaque publication de paquet/registre, et la tâche ciblée de publication autonome est écartée des lents binaires de validation.
  • La garde d'hygiène contre l'attribution est limitée aux seuls marqueurs de paternité, de sorte que nommer un hôte d'intégration ou un produit ne fait plus échouer la compilation.
  • Documentation : la section Citing du README énumère désormais les quatre prépublications arXiv publiées, et la capacité de DOP de balise de surface est documentée dans la ligne lunaire.

Corrigé#

  • Compteurs de boucle entiers pour les boucles pilotées par des flottants (Sonar S2193).
  • Inverse du khi-deux précis à faible nombre de degrés de liberté, grâce à un raffinement de Newton dans le chemin des intervalles de confiance de l'assurance.
  • kshana.dev : la section des normes s'ouvre désormais par défaut et le décompte de repli du registre est corrigé ; les chaînes obsolètes du README et du site autour de la couche d'observabilité sont synchronisées.

0.23.0 - 2026-06-29#

Une version de capacités qui ajoute une couche générale d'observabilité par information de Fisher / Cramér–Rao et de plan d'expériences optimal, et la version sur laquelle repose l'article sur l'observabilité du PNT lunaire. La matrice de validation vérifiée par machine passe à 40 VALIDATED · 47 MODELLED · 4 PARTNER sur 91 lignes (contre 39 · 46 · 4 sur 89) : le nouveau moteur d'estimation est vérifié par rapport à une référence indépendante externe et est VALIDATED ; son application lunaire est honnêtement MODELLED. Comme toujours, aucune affirmation de modèle numérique n'est relevée de niveau sans un jeu de données externe pour l'étayer.

Ajouté#

  • src/fim.rs — information de Fisher, bornes de Cramér–Rao et plan d'expériences optimal. Un moteur général et réutilisable de théorie de l'estimation : la matrice d'information de Fisher M = HᵀWH à partir d'une jacobienne de mesure et de poids ; un solveur propre symétrique (Jacobi cyclique) ; la borne inférieure de Cramér–Rao par l'inverse, ou par la pseudo-inverse de Moore–Penrose plus une base de l'espace nul lorsque l'information est de rang déficient (le cas du réseau libre / du défaut de datum) ; et des métriques de plan d'expériences optimal D, A, E et T, avec un sélecteur best_design sur des géométries candidates. VALIDATED par rapport à NumPy (eigh/inv) et aux bornes en forme close publiées de Kay (1993) à 1e-9 près (tests/fim_observability_reference.rs), de sorte qu'il entre dans la matrice comme une ligne à référence indépendante externe plutôt que comme une auto-vérification.
  • Observabilité de la détermination d'orbite conjointe lunaire (lunar_observability dans src/lunar_combination.rs, présentée dans le rapport de combinaison lunaire) : applique le moteur FIM/CRLB à la résolution conjointe orbite-horloge pour mettre en évidence le défaut de datum de la station absolue, la restauration de son rang à mesure que des stations de base terrestres sont ajoutées, la CRLB atteinte sur la position de la station, et le conditionnement E-optimal. Honnêtement MODELLED — le moteur d'estimation est validé en externe, mais le réseau lunaire auquel il est appliqué est une simulation représentative, et aucun jeu de données actuel ne peut transformer cette géométrie en mesure.
  • Géométrie représentative d'orbite lunaire elliptique gelée (ELFO) pour le scénario de combinaison lunaire (orbit_ecc, orbit_inc_deg, orbit_argp_deg, orbit_planes ; le placement circulaire reste la valeur par défaut) et un champ d'observabilité sans VLBI dans le rapport, afin de montrer que le résultat sur le défaut de datum est valable pour toute géométrie. La même échelle 3→1→0 et le même seuil de trois stations valent pour une ELFO de la famille Moonlight/LCNS, et avec trois lignes de base VLBI terrestres, la position absolue de la station est observable avec une borne sub-métrique — verrouillé par elfo_geometry_confirms_the_observability_structure. Toujours MODELLED.

Modifié#

  • La matrice de validation et chaque artefact de preuve généré ont été régénérés à partir de la source de vérité unique (src/verification.rs) : le registre (web/data/verification-matrix.json), docs/VERIFICATION-MATRIX.md, docs/MODELLED-RATIONALE.md, les figures de ventilation de la validation et de type de référence indépendante, ainsi que les chaînes de décompte du README sur toutes les surfaces de distribution indiquent désormais 40 / 47 / 4 sur 91.

0.22.1 - 2026-06-29#

Une version corrective consacrée uniquement au conditionnement. Aucun changement de moteur, de scénario ou de résultat ; la matrice de validation reste inchangée à 39 VALIDATED · 46 MODELLED · 4 PARTNER sur 89 lignes.

Corrigé#

  • Publication npm : le champ repository.url du paquet, dérivé du manifeste de la crate, utilisait un propriétaire GitHub à la casse incorrecte (AshfordeOU), ce qui faisait échouer la vérification de provenance sigstore de npm (qui compare la casse du propriétaire de façon stricte). Le champ repository du manifeste est désormais le ashfordeOU canonique en minuscules, de sorte que le package.json généré correspond au sujet de la provenance et que la version npm est publiée.

Modifié#

  • La construction de la roue fixe codegen-units = 1 afin que la roue manylinux soit reproductible octet pour octet d'une reconstruction à l'autre (le contrôle de reproductibilité par reconstruction et comparaison).

0.22.0 - 2026-06-29#

Une version de consolidation centrée sur la preuve, la provenance et la discipline de distribution. La matrice de validation vérifiée par machine passe à 39 VALIDATED · 46 MODELLED · 4 PARTNER sur ses 89 lignes (contre 15 · 42 · 4 sur 61), grâce au recoupement de capacités modélisées avec des références externes indépendantes. Chaque artefact distribué porte désormais une attestation cryptographique de provenance de construction SLSA, est livré avec un SBOM CycloneDX, et est publié de façon synchrone sur toutes les surfaces. Aucune affirmation de modèle numérique n'est relevée de niveau sans un jeu de données externe pour l'étayer ; toute nouvelle capacité reste honnêtement MODELLED.

Ajouté#

  • Dynamique d'attitude (src/attitude_dynamics.rs, MODELLED) — équations d'Euler du corps rigide sans couple + cinématique des quaternions (RK4), avec des autotests de lois de conservation (norme du quaternion, énergie cinétique, |Iω|, précession de la toupie symétrique).
  • Recoupement de capacités modélisées avec des références externes indépendantes, ce qui porte la matrice de validation à 39 lignes VALIDATED, chacune adossée à un jeu de données externe (la barrière d'honnêteté de la CI interdit un statut VALIDATED sans un tel jeu). Les validations par référence indépendante externe les plus récentes : la courbe de stabilité mesurée d'une horloge optique (l'ajustement de la courbe d'ADEV de quantum_trade reproduit le σ_y(τ) publié de l'horloge à réseau optique de ⁸⁸Sr de Norcia et al., Science 366 : 93 (2019), Zenodo 10.5281/zenodo.3382347, CC-BY-4.0, intégré sous tests/fixtures/optical_clock_adev/) ; la génération des codes d'étalement GPS L1 C/A (le LFSR G1/G2 de src/sdr.rs reproduit les octals de phase de code du tableau 3-Ia de l'IS-GPS-200 pour les PRN 1 à 9) ; et le lecteur de modèle numérique d'élévation SRTM sur un terrain réel (src/altpnt/terrain.rs lit une tuile SRTM v3 NASA/USGS du domaine public, intégrée, N36W117 / Vallée de la Mort, et situe Badwater Basin dans sa bande de relevé documentée).
  • Nouvelles capacités MODELLED, chacune recoupée en interne avec une forme close ou avec un chemin de code voisin : dynamique de mouvement relatif de Clohessy–Wiltshire / Hill, géolocalisation passive d'émetteurs par TDOA/FDOA, détermination d'attitude de Wahba/TRIAD/QUEST, résolution d'ambiguïté entière de la phase de la porteuse GNSS (LAMBDA), ciblage dans le plan B et assistance gravitationnelle à coniques raccordées, formation de faisceau d'un réseau CRPA anti-brouillage, statistiques d'acquisition GNSS à loi quadratique, ambiguïté de franges / plage dynamique d'un capteur inertiel quantique, bruit d'horloge en loi de puissance IEEE-1139 + plancher de bruit de fréquence de scintillation, et échange de blocs de covariance CCSDS-OEM.
  • Registre de preuves à source unique avec une documentation de vérification générée et une garde contre la dérive ; un registre de validation consultable sur kshana.dev, avec des liens directs vers les preuves de chaque carte.
  • Métadonnées de citation lisibles par machine — codemeta.json (CodeMeta 2,0) et .zenodo.json, alignés sur le manifeste Cargo par tests/citation_metadata_doc_sync.rs.
  • Provenance de la chaîne d'approvisionnement — attestation de provenance de construction SLSA pour l'archive tar de la crate, les wheels, la sdist et l'archive tar npm ; publication de confiance PyPI par OIDC ; SBOM CycloneDX livré dans la wheel et dans le paquet npm ; comparaison de construction reproductible et vérification après publication.
  • Découvrabilité — robots.txt, sitemap.xml et métadonnées Open Graph / JSON-LD sur kshana.dev ; une figure validation-breakdown générée, dérivée de la matrice.
  • README par surface pour crates.io / PyPI / npm, avec une garde d'honnêteté des décomptes.

Modifié#

  • La référence du transfert de temps par effet Sagnac passe à ExternalDataset — la correction de Sagnac pour un tour équatorial complet est désormais vérifiée par rapport aux 207,4 ns publiés par Ashby (Living Reviews in Relativity 6 : 1, 2003, éq. 1,29 ; reproduit à moins de 0,05 ns). La capacité composite de transfert de temps reste honnêtement MODELLED.
  • Documentation, diagrammes et figures actualisés d'après la matrice en vigueur (39/46/4/89) : le diagramme de provenance de la validation, la figure oracle-kind-stacked (désormais générée à partir de la matrice avec une garde de CI contre la dérive), VALIDATION/PROVENANCE/CAPABILITY/QUANTUM-MODELS/WHEEL_TAGS, la documentation d'architecture et les tutoriels, et le total du registre sur kshana.dev.
  • Reformatage de l'arborescence des sources avec le rustfmt épinglé (chaîne d'outils 1.93.0) — purement stylistique, sans changement de comportement.
  • Versionnage synchronisé. Chaque surface de distribution (crate, PyPI, npm, crate MCP + image OCI, extension JetBrains) suit désormais le même numéro de version que le moteur, ce que scripts/check-version-sync.sh impose dans la CI.
  • Extension JetBrains relicenciée sous AGPL-3.0-only (la version 0.1.1 publiée annonçait encore Apache-2.0) et qui tire désormais sa version pour la Marketplace de l'étiquette de version.
  • Renforcement de la robustesse — les unwrap hors tests sont supprimés ou justifiés ; clippy::unwrap_used s'applique au code hors tests.
  • Refonte de kshana.dev centrée sur la preuve : bandeau d'accueil dominant, diagrammes d'architecture et figures de résultats, i18n, sections Registre et Normes repliables et adaptatives.

Corrigé#

  • Éphéméride précise SP3 — application de la correction de nœud de rotation terrestre de l'IGS pendant l'interpolation.
  • Images des registres — les README de PyPI/crates.io/npm utilisent des URL d'images absolues ; les chemins d'images relatifs du README principal s'affichaient comme des images cassées sur la page PyPI de la version 0.21.0. Une garde de CI (tests/surface_readme_image_urls_doc_sync.rs) empêche la régression.
  • CI — fmt + clippy au vert ; fin de la compilation contre des données réelles ignorées par git.

Tests#

  • La covariance d'horloge du filtre de Kalman reste semi-définie positive et symétrique (test de propriété, tests/property.rs).
  • Gardes de synchronisation de la documentation : chaque chaîne de décompte de validation publique, les métadonnées de citation, la figure générée et les URL d'images des README de surface sont toutes alignées sur leur source de vérité.

0.21.0 - 2026-06-26#

Cette version ajoute deux suites d'applications MODELLED au moteur ouvert — un démonstrateur de PNT à technologies quantiques (transfert de temps quantique de confiance, navigation quantique sans GNSS, détection quantique de défauts/anomalies) et une suite de PNT lunaire / cislunaire (temps-coordonnée lunaire, VLBI lunaire, détermination d'orbite et d'horloge conjointe, réalisation de référentiel, volume de service, PNT différentiel, export d'interopérabilité) — chacune exécutable à partir d'un seul kind, chacune émettant un enregistrement TradeEvidence honnête ainsi qu'un registre de représentativité / d'écarts avant vol. Elle apporte aussi six nouvelles validations par référence externe indépendante, ce qui porte la matrice de validation vérifiée par machine à 15 VALIDATED · 42 MODELLED · 4 PARTNER sur ses 61 lignes. Les nouveaux chiffres d'application sont MODELLED à partir de paramètres illustratifs issus de sources publiques — sans TRL, sans antécédent de vol, sans certification ni aval d'une agence — et les noyaux validés qu'ils réutilisent sont étiquetés comme tels.

Ajouté#

  • Suite de démonstrateurs de PNT à technologies quantiques (quantum-time-transfer, quantum-gnss-free-nav, quantum-anomaly-detect). Trois domaines d'application MODELLED exécutables derrière le moteur, chacun émettant TradeEvidence plus un enregistrement de représentativité / d'écarts avant vol :
    • Transfert de temps quantique de confiance (src/timetransfer_chain.rs) — un budget bidirectionnel horloge à réseau optique + liaison photonique contre CSAC + RF, réutilisant le niveau de protection de la synchronisation temporelle, avec une figure de mérite de sécurité face aux attaques par retard/rejeu (1 − P_md) et une détection d'anomalies d'horloge + latence CUSUM.
    • Navigation quantique sans GNSS (src/quantum_nav_od.rs) — une navigation inertielle à interféromètre à atomes froids contre un INS de qualité navigation pendant une coupure GNSS, en reconnaissant honnêtement que, sans position externe, le biais de l'accéléromètre reste inobservable et que l'erreur continue donc de croître.
    • Détection quantique de défauts / d'anomalies (src/quantum_faults.rs) — un catalogue de défauts étiquetés avec une AUC ROC à intervalle de confiance par bootstrap et un défaut minimal détectable pour un taux de fausses alarmes fixé.
    • Une bibliothèque partagée de modèles d'erreur de dispositifs quantiques (src/quantum_devices.rs) et un banc unifié de comparaison quantique/classique (src/qtrade.rs) sous-tendent les trois.
  • Suite de PNT lunaire / cislunaire. Sept types de scénario (kind) MODELLED exécutables, superposés au noyau CR3BP : temps-coordonnée lunaire (taux séculaire LTC/TCL − TT, src/lunar_time.rs), observable géodésique de retard VLBI lunaire (src/lunar_vlbi.rs), estimateur par lots d'orbite et d'horloge conjointes multitechniques (src/lunar_combination.rs), réalisation de référentiel (Helmert à 7 paramètres + raccord WGCCRE de l'IAU 2015, src/lunar_frame_realise.rs), analyse du volume de service de classe Moonlight / LCNS (src/lunar_service.rs), PNT différentiel lunaire (src/lunar_dpnt.rs) et un export d'interopérabilité aligné sur LunaNet / IOAG (CCSDS-OEM + échelle de temps lunaire dans l'enveloppe KIF, src/lunar_interop.rs). Tout est MODELLED à partir de paramètres illustratifs issus de sources publiques ; non validé par rapport à un véritable suivi VLBI / Gateway ; aucune affiliation ni aval d'une agence.
  • Six nouvelles validations par référence externe indépendante (la matrice de validation s'établit désormais à 15 validées) :
    • ADEV / HDEV sur une véritable horloge au césium 5071A — validés par rapport aux références aux points décadiques de Stable32 (tests/cs5071a_reference.rs).
    • OADEV / MDEV / TDEV sur la référence PHASE.DAT de Stable32 — validés par rapport aux tableaux publiés de Stable32 (tests/phasedat_reference.rs).
    • AUC ROC de détection d'anomalies sur la télémétrie réelle d'ESA OPS-SAT — validée par rapport à scikit-learn (tests/opssat_ad_reference.rs).
    • Synthèse de fonctionnelles de gravité ICGEM — validée par rapport à la norme de gravité normale GRS80 (γ de Somigliana à 3.5e-12 près ; carte des perturbations EGM2008, tests/icgem_gravity_reference.rs).
    • Modèle ionosphérique diffusé de Klobuchar — validé par rapport à RTKLIB (tests/klobuchar_reference.rs).
    • Noyau de détection RAIM (171 cas, tests/raim_reference.rs) et niveau de protection SBAS DO-229E sur des données EGNOS réelles (fork SBAS-PL de RTKLIB, tests/sbas_reference.rs) — tous deux validés par rapport à leurs références externes indépendantes.
  • Registre de représentativité et d'écarts avant vol (src/representativeness.rs). Un enregistrement structuré que chaque démonstrateur émet — ce qui est représentatif, ce qui est simplifié et ce qui sépare le modèle du vol — le pendant honnête de chaque comparaison MODELLED.
  • Agrégation d'études et ergonomie de la CLI. Un manifeste de suite de scénarios avec agrégation d'études en une seule commande, des métadonnées d'étude stables par hachage + --study-name, une analyse statique des scénarios par --validate, et l'affichage du niveau de validation de chaque figure de mérite dans les rapports d'étude.

Modifié#

  • kshana.dev repensé autour d'un socle de domaine partagé — capacités et validation réunies dans un seul explorateur de domaine avec un vocabulaire commun, les nouveaux îlots validés mis en évidence, un instrument Terre animé fidèle aux terres émergées et un appel à l'action pour demander une étude, ainsi que l'image de marque et les liens d'Ashforde OÜ.
  • README + ARCHITECTURE vérifiés pour l'exhaustivité et l'honnêteté — décomptes obsolètes de validés corrigés (désormais 15 références externes indépendantes), diagrammes étendus, et citation des prépublications sur le niveau de protection conditionnel de la synchronisation temporelle (arXiv:2606,24210) et sur l'écart d'optimisme des perturbations RF (arXiv:2606,22054).
  • Les sources de paper/ et la chaîne de brouillon JOSS sont conservées dans le dépôt public.

0.20.0 - 2026-06-22#

Cette version ajoute quatre capacités d'étude au moteur ouvert — un niveau de protection conditionnel de la synchronisation temporelle, une notation de résilience PNT alignée sur un cadre de référence, une évaluation de l'écart d'optimisme face aux perturbations RF, et un front-end de récepteur défini par logiciel / de données réelles — chacune reproductible à partir d'une seule commande et écrivant un artefact déterministe octet pour octet. Toutes les études sont MODELLED (étalonnage synthétique ou sur jeu de données public), portent leur provenance honnête (version du moteur, graines, hachage de configuration) et leurs étiquettes de validation, et ne sont pas des certifications.

Ajouté#

  • Niveau de protection conditionnel de la synchronisation temporelle (tpl). Une borne, limitée par le holdover, de l'erreur de temps non détectée en cas de leurrage GNSS, avec un plancher de moniteur à k sigma, une variance de marche libre de van Loan sur la latence de détection et un délai d'alarme CUSUM. Étalonné sur une véritable attaque enregistrée (JammerTest 2024, scénario 2.1.1) via cargo run --release --example tpl_jammertest, qui reproduit son tableau de référence à partir de scalaires récupérés de l'enregistrement public (le jeu de données brut n'est pas redistribué).
  • Notation de résilience PNT alignée sur un cadre de référence + étude d'instabilité des décisions (resilience). Modèle d'architecture, notation alignée sur RPCF, simplexe de pondération de Dirichlet, instabilité par tau de Kendall et taux d'inversion du top-1, et effondrement de la diversité de mode commun (Hill-N2), avec cargo run --release --example resilience_report -- paper-artifacts/resilience-study.json. Table de correspondance dans docs/RESILIENCE-CROSSWALK.md.
  • Étude de l'écart d'optimisme face aux perturbations RF (impairment_study, impairment_ml, eval_stats). Un panel de 13 détecteurs sur un corpus synthétique fondé sur des paramètres, un écart d'optimisme entre dans la distribution et hors distribution, des tendances de loi d'échelle avec une hypothèse nulle par permutation, et un prédicteur de dégradation par exclusion d'un élément, via cargo run --release --example optimism_study -- paper-artifacts/optimism-study.json.
  • Front-end de récepteur défini par logiciel (sdr) et adaptateurs de données réelles (realdata/). De l'IQ/IF brut aux prises du corrélateur et au SQM, plus des adaptateurs d'ingestion (RINEX, u-blox UBX, GnssLogger, JammerTest, Yunnan, SatGrid) et des exemples de sondage. Ils lisent des enregistrements que l'utilisateur fournit localement ; aucun enregistrement n'est versé dans le dépôt.
  • Artefacts d'étude versionnés. Les fichiers optimism-study.json et resilience-study.json, déterministes octet pour octet, sont désormais suivis sous paper-artifacts/, de sorte que les chiffres des études peuvent être vérifiés sans reconstruction ; ils restent régénérables à partir des générateurs ci-dessus. Les jeux de données bruts restent hors du dépôt (/realdata-cache/).

Modifié#

  • Version portée à 0.20.0 dans Cargo.toml, CITATION.cff et README ; les artefacts de l'étude de croisement sont régénérés pour que leur estampille corresponde à la version publiée.

0.19.0 - 2026-06-18#

Modifié#

  • Relicencié d'Apache-2.0 vers la GNU AGPL-3.0-only, avec une licence commerciale disponible auprès d'Ashforde OÜ (double licence). Le moteur ouvert reste entièrement ouvert et publiquement vérifiable ; le copyleft réseau de l'AGPL (§13) signifie qu'un dérivé fermé ou hébergé doit revenir au logiciel libre — ou prendre une licence commerciale. Cela protège le noyau validé contre le fork suivi de fermeture, tout en conservant la crédibilité d'un moteur public, exécutable et auditable. Voir LICENSE (AGPL) et le nouveau LICENSING.md (ce que couvre chaque licence et quand elle s'applique).
    • LICENSE contient désormais le texte de l'AGPL-3.0 ; les en-têtes SPDX de toutes les sources sont mis à jour en AGPL-3.0-only ; NOTICE, README, GOVERNANCE, GLOSSARY, le site web et les métadonnées de la crate et des paquets (Cargo.toml, pyproject.toml, CITATION.cff, la crate MCP + l'image) sont mis à jour en conséquence.
    • Les conditions pour les contributeurs (CONTRIBUTING.md) concèdent désormais les contributions entrantes sous l'AGPL et accordent à Ashforde OÜ le droit d'inclure les contributions dans l'édition sous licence commerciale, afin que la double licence continue de fonctionner.
    • Politique de dépendances inchangée mais justifiée à nouveau (deny.toml, GOVERNANCE) : les dépendances restent permissives (Apache/MIT/BSD/ISC). L'AGPL n'est autorisée que pour la propre crate de kshana — une dépendance sous copyleft contaminerait l'édition commerciale et briserait la double licence.
    • Note pour l'aval : il s'agit d'un changement de licence vers un copyleft. Les utilisateurs qui comptaient sur les conditions permissives d'Apache-2.0 peuvent continuer à utiliser la dernière version sous Apache-2.0 (v0.18.0 et antérieures, telles que publiées) ; à partir de v0.19.0, c'est l'AGPL-3.0 / licence commerciale.

Sécurité#

  • pyo3 mis à jour de 0,24 à 0,29 pour éliminer RUSTSEC-2026-0176 / RUSTSEC-2026-0177 (GHSA-36hh-v3qg-5jq4 / GHSA-chgr-c6px-7xpp) des analyses OSV/de dépendances externes. Ce sont deux avis au niveau des fonctions dont les fonctions concernées (BoundList/TupleIterator::nth/nth_back, PyCFunction::new_closure) ne sont jamais appelées par Kshana, et pyo3 est une dépendance optionnelle (fonctionnalité python) — l'exposition réelle était donc nulle — mais la mise à jour maintient une analyse propre pour les auditeurs en aval. Migration de src/python.rs vers l'API de pyo3 0,29 (type de retour Bound pour scenario_kinds ; skip_from_py_object explicite sur la pyclass RunOutput). Les 11 tests de liaison Python réussissent avec l'extension reconstruite.

0.18.0 - 2026-06-17#

Ajouté#

  • Onze nouveaux types de scénario exécutables — démonstrateurs à deux appels d'offres, un pont d'interopérabilité CCSDS et une suite de premier ordre d'analyse de mission / d'environnement (tous MODELLED, additifs ; les références de reproductibilité existantes restent inchangées). Chacun peut être lancé par la CLI / Python / WASM / MCP, est livré avec un scenarios/<kind>.toml et porte une étiquette MODELLED explicite dans le JSON de son résultat et dans son résumé d'une ligne (un test par type dans tests/dominance_demonstrators.rs vérifie que l'étiquette est présente et que la sortie ne contient jamais la chaîne VALIDATED) :

    • impairment-eval (src/impairment_eval.rs) — banc d'évaluation de la détection par apprentissage automatique des perturbations RF : un corpus synthétique étiqueté + un banc ROC/AUC indépendant du détecteur + un rapport d'écart d'optimisme dans la distribution / hors distribution (caractéristiques opérationnelles uniquement — jamais de données de terrain/IQ).
    • quantum-trade (src/quantum_trade.rs) — comparaison PNT quantique/classique avec ingestion d'ADEV mesurées et une enveloppe de résilience en environnement privé de GNSS.
    • space-weather (src/space_weather.rs) — indices solaires/géomagnétiques (table IAGA Kp↔ap, Ap journalier, F10.7a centré sur 81 jours), température exosphérique de Jacchia-71 et couplage de la densité thermosphérique piloté par l'activité sur une atmosphère statique (PAS un modèle de densité absolue NRLMSISE).
    • oem-interop (src/oem.rs) — pont d'import et d'aller-retour OEM CCSDS 502,0 pour les éphémérides GMAT / Orekit / STK (le lecteur parse_oem, inverse exact de l'écrivain).
    • launch-window (src/launch.rs) — azimut de lancement à deux corps (sin Az = cos i/cos lat), Δv de changement de plan, bonus de rotation du site et géométrie des opportunités quotidiennes.
    • reentry (src/reentry.rs) — corridor de rentrée balistique d'Allen-Eggers : décélération maximale, vitesses de pic de g et de pic de chauffage, altitude du pic de g.
    • eo-coverage (src/eo_payload.rs) — géométrie d'emprise / GSD / accès / revisite en observation de la Terre (triangle spatial SMAD).
    • space-packet (src/space_packet.rs) — encodage/décodage de l'en-tête primaire de paquet spatial CCSDS 133.0-B avec aller-retour exact au bit près.
    • attitude-budget (src/attitude_budget.rs) — couple de gradient de gravité à 3 degrés de liberté + budget d'erreur de pointage RSS (budget scalaire avant matériel, pas une boucle de commande).
    • passes (src/passes.rs) — prédiction des passages lever/coucher d'une station au sol (AOS/TCA/LOS, élévation maximale, accès).
    • link-budget (src/linkbudget.rs) — équation de liaison unidirectionnelle CCSDS-401 / DSN-810-005 (C/N₀ = EIRP − FSPL − L_other + G/T − k, FSPL / Eb·N₀ / marge / fermeture).
  • UKF hybride quantique + classique à couplage serré à 17 états — présenté comme un scénario exécutable (MODELLED). Un nouveau type de scénario hybrid-ukf (src/fusion/hybrid_ukf.rs, scenarios/hybrid-ukf.toml) qui transforme le filtre non parfumé GNSS/INS à couplage serré à 17 états, jusque-là réservé à l'API (src/fusion/tightly_coupled17.rs), en un scénario que les liaisons CLI/Python/WASM/MCP peuvent lancer. Le vecteur d'erreur à 17 états est constitué des 15 états d'erreur INS (position, vitesse, désalignement d'attitude, biais d'accéléromètre + de gyroscope) augmentés de la correction du biais d'accéléromètre issue du CAI — l'interféromètre à atomes froids (src/inertial/quantum_imu.rs) fixe le plancher de marche aléatoire de vitesse q_va, de sorte que la dérive à long terme en marche libre est celle qu'impose le capteur quantique — et d'une horloge à 2 états phase + fréquence dont le bruit de processus provient du moteur d'horloge à paramètres q (clock_state::q_from_allan, qui met en correspondance le profil d'écart-type d'Allan d'une horloge avec les DSP q_wf/q_rw, mises à l'échelle en unités de distance). La plateforme est assistée par GNSS pendant une phase d'amorçage (le filtre apprend les biais, la vitesse et l'horloge), puis traverse en marche libre une coupure GNSS avec la seule IMU à CAI et l'horloge, de sorte que l'exécution démontre une hybridation IMU classique à court terme + quantique à long terme. La figure de mérite est l'autocohérence du filtre : le NEES agrégé (Normalised Estimation Error Squared, sur le sous-ensemble position/vitesse/horloge estimable) et le NIS de blancheur de l'innovation (Normalised Innovation Squared) sur un ensemble Monte-Carlo, vérifiés par rapport à leurs bandes de χ² à 95 % (Bar-Shalom §5,4). Le filtre adapté tombe dans les bandes ; un filtre volontairement mal réglé (les paramètres q_factor / r_factor) est signalé — un critère objectivement vérifiable et discriminant, et non une simple validation de pure forme. La vérification NEES / blancheur de l'innovation est la RÉFÉRENCE STATISTIQUE INDÉPENDANTE : un énoncé d'autocohérence (la covariance rapportée par le filtre correspond honnêtement à la dispersion de ses propres erreurs sous le bruit modélisé), PAS une garantie de précision en conditions réelles. Portée honnête : tout est modélisé / simulé — les entrées du CAI et de l'horloge sont des valeurs encadrées, représentatives de la littérature, et non du matériel mesuré ; le matériel du CAI et sa personne clé restent la propriété du partenaire ; rien ici n'implique un TRL > 3, un antécédent de vol ou une validation externe (le JSON du résultat et le résumé d'une ligne portent explicitement ces étiquettes). La trajectoire unique, à vitesse constante et à plat, ne rend les états d'attitude et de biais d'IMU qu'à peine observables ; le NEES est donc évalué sur les 8 états estimables ; une trajectoire avec manœuvres pour une observabilité complète des 17 états figure dans la feuille de route. Ajoute aussi l'instrumentation de cohérence Ukf::update_stats (qui renvoie le NIS de chaque mise à jour) et TightlyCoupled17::{update_gnss_nis, nees, nees_subset}. Tous les scénarios existants sont inchangés (additif ; références de reproductibilité inchangées).

  • Navigation séquentielle (récursive) référencée au relief — SITAN comme filtre en continu. Un nouveau type de scénario terrain-slam (src/altpnt/sequential.rs, scenarios/terrain-slam.toml) qui exécute le modèle de mesure existant altimètre contre MNT époque par époque à travers le moteur SIR particle_filter, plutôt que par la recherche grossière-à-fine par lots qu'utilise terrain-nav pour retrouver un unique décalage constant de l'INS. À chaque point de passage, le nuage est propagé par l'incrément rapporté par l'INS (lui-même corrompu par la croissance de la dérive à chaque pas), repondéré par la correspondance au relief et rééchantillonné en cas de dégénérescence — de sorte qu'une dérive d'INS variable dans le temps est suivie le long de la trajectoire, ce qu'un ajustement à décalage constant ne peut structurellement pas faire. Sur le MNT synthétique, l'estimation récursive reste bornée et reconverge (final ≈ 70 m) alors que la solution inertielle sans aide diverge sans borne jusqu'à ≈ 5 km ; l'erreur à chaque époque suit le caractère distinctif du relief (le filtre dérive sur l'INS biaisé au-dessus des cols plats et se reverrouille au-dessus d'un relief marqué), et le moniteur de taille d'échantillon effective confirme un nuage sain. Portée honnête : la carte est connue et fixe — localisation récursive par rapport à un MNT stocké (la moitié localisation du SLAM sur relief), et non estimation conjointe de la carte ; non circulaire par construction (la rampe de dérive injectée est la vérité indépendante). Tous les scénarios existants sont inchangés (additif ; références de reproductibilité inchangées).

  • Socle de résilience sans GNSS + tranches de démonstrateur FutureNAV (src/holdover.rs, et fondations d'enveloppe de résilience sous src/impairment_eval.rs, src/quantum_trade.rs, src/navsignal.rs, src/inertial/quantum_imu.rs, avec des tranches de vérification FutureNAV dans src/verification.rs). Compose les briques de PNT alternatif — holdover d'horloge, poursuite du signal, marche libre inertielle, relief — en un seul récit de résilience à une coupure GNSS. MODELLED ; additif.

  • Kshana Interchange Format (KIF) — une enveloppe d'artefact versionnée et autodescriptive (src/interchange.rs). Une enveloppe étiquetée par schéma autour des résultats de scénario, de sorte qu'un artefact stocké porte avec lui son type, sa version de schéma et ses étiquettes MODELLED/VALIDATED, et que les anciennes enveloppes restent lisibles avec compatibilité ascendante. Additif ; le JSON de résultat existant est inchangé.

  • Modulation / poursuite du signal de navigation + correcteur différentiel de halo/NRHO en CR3BP (src/navsignal.rs, src/cr3bp.rs). Un modèle de premier ordre de modulation et de poursuite du signal de navigation, et un correcteur différentiel du problème circulaire restreint à trois corps pour les orbites de halo / de halo quasi rectiligne, présentés sur l'axe existant des capacités d'espace lointain. MODELLED.

  • Mode d'évaluation du décalage de distribution + réglage de l'échelle de sévérité du corpus pour impairment-eval (src/impairment_eval.rs). Ajoute une séparation explicite dans la distribution / hors distribution et une échelle de sévérité du corpus réglable au banc d'écart d'optimisme ROC/AUC (caractéristiques opérationnelles uniquement — jamais de données de terrain/IQ).

  • ROI par couverture + mise en correspondance des détections manquées avec l'impact sur l'intégrité (src/frugal.rs, src/integrity_impact.rs). Un regard de ROI en ingénierie frugale (coût par unité de couverture) et une mise en correspondance entre le taux de détections manquées et l'impact sur l'intégrité. MODELLED ; additif.

  • Fiche de paramètres citée du modèle d'erreur de l'interféromètre à atomes froids (CAI) (src/inertial/quantum_imu.rs). Une fiche de paramètres encadrés, référencés dans la littérature, pour le modèle inertiel du CAI — les entrées sont citées, et non issues de matériel mesuré (aucune revendication de TRL ni de vol) ; elle alimente le plancher de marche aléatoire de vitesse de hybrid-ukf.

  • Gouvernance du projet. GOVERNANCE.md documentant le modèle de décision et la frontière entre ouvert et fermé ; la ligne communauté/gouvernance de la carte des capacités passe de none → partial pour en rendre compte.

Corrigé#

  • Niveau de protection d'intégrité ARAIM — biais nominal (b_nom) et σ_URA désormais appliqués. Le niveau de protection MHSS soustrait désormais la projection unilatérale du biais nominal b_k = Σ_i |s_i|·b_nom pour chaque mode de défaut, et utilise le sigma d'intégrité σ_URA (distinct du sigma de précision σ_URE) porté par l'Integrity Support Message. Cela rend le niveau de protection plus prudent et correct au regard des normes, et modifie donc les valeurs de PL rapportées par les scénarios d'intégrité existants. L'ISM/le scénario gagne les champs #[serde(default)] sigma_ura_m / b_nom_m, de sorte que les entrées qui les laissent non définis conservent le comportement antérieur. Voir docs/ARAIM_REFERENCE.md pour la formule b_k rétablie et la note d'implémentation honnête.

  • Cohérence du khi-deux du moniteur de leurrage. parity_raim_test utilise désormais le chemin commun d'inverse du khi-deux raim::chi2_quantile, ce qui supprime une seconde implémentation divergente du khi-deux, de sorte que le RAIM et le moniteur de leurrage par parité s'accordent sur leurs seuils.

  • gravity-map-nav raccordé au répartiteur de la CLI. Le scénario n'était auparavant accessible que par l'API ; il est désormais lancé comme un kind= à l'instar de tous les autres scénarios.

  • Exactitude de la documentation et des décomptes. Les décomptes de types de scénario du README sont désormais alignés sur api::list_scenario_kinds().len() par un test scenario_count_doc_sync, de sorte que le décompte documenté ne peut plus diverger du répartiteur.

0.17.0 - 2026-06-14#

Ajouté#

  • PNT de l'espace lointain et de Mars — moteur ouvert de navigation radiométrique + simulation GSE. Un nouvel axe de capacités, entièrement additif, au-dessus du noyau validé sur la Terre (chaque scénario terrestre existant est identique octet pour octet — les références de reproductibilité passent sans changement et sans régénération). Il ajoute : un noyau de dynamique multicorps (Body{mu, re, zonals, gravity, rotation, IAU-pole} avec la gravité tesséral GMM-3 de Mars, un référentiel martien lié au corps de l'IAU, un point d'extension EphemerisProvider enfichable, des dates juliennes en deux parties inférieures à la microseconde et TT↔TDB) ; des observables radiométriques (temps de lumière itératif + délai de Shapiro, Doppler et distance à deux/une/trois voies par la résolution à deux trajets de Moyer, retournement cohérent du transpondeur, télémétrie régénérative/PN selon CCSDS 414, Δ-DOR selon CCSDS 506, milieux plasma solaire/troposphère/ionosphère) ; l'analyse et l'émission CCSDS-TDM (503) ; un filtre d'information en racine carrée à dynamique réduite avec des accélérations empiriques RTN, une horloge embarquée à trois états et un modèle de traînée martienne ; un estimateur de fusion conjoint à une et deux voies ; la surface de scénarios mars-pnt (constellation relais + LMO/transfert/surface) à travers la CLI, Python, WASM, MCP et le bac à sable ; et un simulateur de performance GSE de bout en bout (géométrie → bilan de liaison → observables → SRIF → covariance). Niveau de validation — validé par simulation : détermination d'orbite synthétique en boucle fermée (Mars-LMO ≈ 0,2 m) et autocohérence analytique, avec la dynamique martienne centrée sur le Soleil recoupée de façon indépendante avec JPL DE440 (xval/anise-mars-od, conditionné à la présence du noyau : 137 m sur un arc de 1 jour, le résidu honnête de n corps non modélisé). Les précisions d'espace lointain indiquées sont des figures de mérite de simulation / de covariance, et non des résultats de mission réelle ; la validation par des données de suivi réelles DSN/ESTRACK reste sur la feuille de route. ANISE (MPL-2.0, édition 2024) est confiné à une crate de recoupement exclue de l'espace de travail, de sorte que la barrière de licences cargo deny et la tâche MSRV-1.75 ne sont pas touchées.
  • Traces au sol d'une exactitude de niveau agence à partir de la véritable orientation terrestre de l'IERS. Le scénario ephemeris accepte un champ facultatif eop_finals2000a — le corps intégré d'un véritable fichier IERS finals2000A — et réduit la trace au sol au moyen de l'UT1−UTC et du mouvement du pôle de chaque époque, interpolés à partir de ce fichier (la même EopSeries qu'utilise precise_od), en remplaçant les scalaires nominaux dut1_s/xp_arcsec/yp_arcsec. Les données voyagent dans le scénario, de sorte que l'exécution reste reproductible et n'a besoin d'aucun système de fichiers (elle fonctionne dans le bac à sable WASM). Une option kshana --eop <finals2000A> intègre un fichier réel au scénario depuis la CLI. Cela supprime l'asymétrie selon laquelle seul precise_od consommait de véritables données d'orientation terrestre.

Corrigé#

  • Cohérence de référentiel pour la vitesse radiale. La station au sol est désormais ramenée dans le référentiel inertiel par l'inverse exact de la réduction du satellite (frames::itrf_to_teme, qui annule le mouvement du pôle et la rotation sidérale) au lieu d'une rotation GMST aveugle au mouvement du pôle, de sorte que les deux extrémités partagent un même référentiel. L'effet sur le Doppler rapporté est inférieur au plancher de validation, mais cela supprime un véritable désaccord de référentiel et une affirmation excessive d'« exactitude » dans le code source.
  • carrier_hz est validé. Une fréquence porteuse nulle ou non finie renvoie désormais une erreur au lieu de produire en silence un Doppler nul (elle rendait λ = c/porteuse infini), comme la garde existante de step_s.

0.16.0 - 2026-06-11#

Ajouté#

  • Validation du modèle de forces par ajustement d'éphéméride, recoupée avec de véritables produits d'agences. Un nouvel estimateur par moindres carrés par lots (src/precise_od.rs) avec une matrice de transition d'état variationnelle et une édition des valeurs aberrantes, piloté par un modèle de forces complet (PreciseForceModel : géopotentiel EGM2008, corps tiers, marées solides + océaniques + atmosphériques, et accélérations empiriques CPR/2 par tour), alimenté par un véritable analyseur d'orientation terrestre IERS finals2000A. Validé par rapport à des orbites de référence publiées : Galileo MEO à 13 cm après ajustement, Swarm-A LEO de l'ESA et LRO lunaire (sélénocentrique, gravité GRAIL, référentiel du corps IAU-2015 — dynamique réduite 6,6 m, honnêtement au-dessus de l'objectif de 5 m sur le chemin ouvert ; le chemin ANISE/DE440 de niveau DE qui l'atteint est une crate exclue de l'espace de travail).
  • Scénario spoof-detect — un détecteur de leurrage multicouche intégré, combinant la parité RAIM de chaque époque, des moniteurs d'AGC et de qualité du signal (SQM) et une décision fusionnée, validé par rapport aux paramètres de scénario TEXBAT publiés (Humphreys et al., ION GNSS 2012), y compris le cas difficile à porteuse alignée.
  • Scénario ephemeris — état, référentiels, trace au sol et Doppler. Propage un satellite (TLE→SGP4 ou orbite analytique) et émet, à chaque pas, l'état inertiel TEME et GCRS (position et vitesse), la position ITRF/ECEF liée à la Terre, la trace au sol du point subsatellite WGS-84 (latitude / longitude / altitude), ainsi que l'azimut / l'élévation / la distance topocentriques avec la vitesse radiale et le Doppler depuis une station au sol. Accessible depuis la CLI, Python, WASM et le serveur MCP, et livré comme préréglage « Trace au sol » dans le bac à sable web, où la trace est dessinée sur une véritable carte du monde (côtes Natural Earth 1:110m, intégrées — sans réseau ni dépendance externe).
  • Export CCSDS OEM (--export-oem / export_oem = true) — l'Orbit Ephemeris Message porteur de la vitesse, consommé par GMAT / Orekit / STK, à parité avec les exports SP3 et OMM existants.
  • Marées terrestres solides, océaniques (FES2004) et atmosphériques (Ray 2001 S2) sur le géopotentiel (Conventions de l'IERS, chap. 6), intégrées au modèle de forces.
  • Wheels ARM64 — la construction PyPI produit désormais aussi des wheels Linux aarch64 (manylinux_2_28), macOS arm64 et Windows arm64.
  • Rapport technique étendu (prépublication) lié depuis le README, et article JOSS rendu soumissible (ORCID de l'auteur, compilé en PDF dans la CI à chaque modification).

Modifié#

  • Référentiels validés au millimètre par rapport aux vecteurs publiés de Vallado. La réduction TEME→PEF/ITRF, la chaîne complète CIO IAU 2006/2000A GCRS→ITRS et la conversion ECEF→géodésique WGS-84 sont désormais alignées sur l'exemple détaillé de Vallado et al. (AIAA 2006-6753) avec ses EOP de l'IERS, et non plus seulement sur l'autocohérence interne.
  • Recoupements indépendants d'échelles de temps. L'ERA et les échelles UTC/TAI/TT concordent avec hifitime à moins de 1 µs, et l'éphéméride planétaire DE440 concorde avec JPL Horizons (positions géocentriques de la Lune et du Soleil), les deux comme barrières de CI toujours actives.
  • Le bac à sable web masque l'onglet des figures de mérite lorsqu'un résultat ne comporte aucune ligne de figure de mérite, de sorte que les paquets à graphique seul (éphéméride, RAIM, leurrage) s'ouvrent sur leur graphique — pour l'éphéméride, la trace au sol — plutôt que sur un tableau vide.
  • Les curseurs guidés du bac à sable et le balayage de paramètres fonctionnent désormais pour le scénario d'éphéméride / de trace au sol : ses réglages (latitude / longitude de la station, pas de temps, durée, UT1−UTC) sont ajustables, et un balayage peut tracer la géométrie du passage (élévation maximale, Doppler maximal, altitude, vitesse) en fonction de n'importe lequel d'entre eux — par exemple l'élévation maximale en fonction de la latitude de la station. L'onglet Balayage n'est désormais affiché que lorsqu'un scénario est réellement balayable, de sorte qu'aucun paquet ne propose une commande qui ne trace rien.
  • Documentation de l'approximation SGP4 DUT1 ≈ 0 à l'endroit de l'appel de GMST (une erreur de rotation ≤ ~13″, bien en deçà de l'erreur propre au modèle de SGP4) et actualisation de CAPABILITY.md.

0.15.1 - 2026-06-09#

Ajouté#

  • L'extension JetBrains Kshana — PNT simulator est désormais publiée et approuvée sur la JetBrains Marketplace. Le README, kshana.dev et la documentation de distribution y renvoient directement.

Corrigé#

  • La publication au registre MCP réussit désormais : le champ description de server.json dépassait la limite de 100 caractères du registre (HTTP 422). Il a été raccourci, et le nom du serveur (ainsi que l'étiquette de propriété de l'image) a été aligné sur l'espace de noms canonique io.github.ashfordeOU/kshana-mcp.
  • La publication à la JetBrains Marketplace réussit désormais : la CI retéléversait la même version de l'extension que celle qui avait été listée manuellement, ce que la Marketplace refuse. La version de l'extension passe à 0.1.1, et la garde d'idempotence traite maintenant aussi une réponse « already contains version » comme un succès sans effet.
  • Invalidation de cache pour kshana.dev : les chaînes de requête style.css/app.js estampillées de la version suivent la publication, de sorte que les visiteurs qui reviennent obtiennent toujours la construction actuelle.

0.15.0 - 2026-06-08#

Ajouté#

  • kshana-mcp — Kshana comme serveur Model Context Protocol (MCP) (mcp/kshana-mcp/). Une crate autonome, exclue de l'espace de travail (le SDK rmcp est en édition 2024), qui expose le moteur validé aux agents et assistants d'IA — Cursor, JetBrains AI Assistant / Junie et tout client MCP — via stdio. Outils : run_scenario, list_scenario_kinds, validate_scenario, export_sp3, export_omm, chacun étant une fine enveloppe autour de kshana::api.
  • Extension pour IDE JetBrains (ide/jetbrains/). Clic droit sur un scénario .toml → Run Kshana Scenario ; les figures de mérite et le JSON du résultat arrivent en flux dans une fenêtre d'outils Kshana. Extension Kotlin de plateforme pure, compatible avec tous les IDE JetBrains 2024,3+.
  • Distribution publique + publication automatique à chaque version pour les deux :
    • kshana-mcp sur crates.io (cargo install kshana-mcp) via publish.yml.
    • kshana-mcp sous forme d'image OCI multi-architecture sur ghcr.io (docker run ghcr.io/ashfordeou/kshana-mcp) via un nouveau mcp-publish.yml.
    • kshana-mcp dans le registre MCP officiel via GitHub OIDC (aucun secret) ; l'entrée du registre (server.json) utilise le type de paquet OCI avec un propriétaire vérifié par étiquette.
    • l'extension pour IDE sur la JetBrains Marketplace via publishPlugin (conditionné par un jeton, signature de développeur facultative) à chaque étiquette de version.

0.14.1 - 2026-06-08#

Ajouté#

  • Validation croisée indépendante de référentiels avec ANISE/SPICE (xval/anise-frames/). Une crate autonome, exclue de l'espace de travail, recoupe la réduction CIO IAU 2006/2000A de kshana (kshana::cio::gcrs_to_itrs_matrix, GCRS→ITRS) avec la rotation GCRF→ITRF93 d'ANISE (la réimplémentation NAIF/SPICE en Rust pur) à partir du fichier earth_latest_high_prec.bpc de JPL, avec les mêmes paramètres d'orientation terrestre IERS finals2000A fournis aux deux côtés, sur huit époques trimestrielles de 2020 à 2023. Les deux réalisations indépendantes du référentiel concordent avec une rotation relative maximale de 0,028″ — ≤ 0,86 m au sol, ≤ 0,93 m en LEO, ≤ 3,6 m en orbite GNSS, ce qui respecte avec une large marge le recoupement de référentiel « < 10 m » de longue date de la ROADMAP (il complète, sans la remplacer, les ancrages SOFA/ERFA existants identiques bit pour bit). La crate est isolée parce que anise + hifitime sont sous MPL-2.0 / édition 2024 et ne doivent jamais entrer dans le graphe de dépendances publié de kshana, son Cargo.lock, la barrière de licences cargo deny ni la construction MSRV ; ANISE est épinglé avec default-features = false. Comprend un binaire frame-xval (qui télécharge le BPC d'environ 5 Mo, affiche un tableau et écrit report.{json,md}), une barrière de test qui s'ignore elle-même en l'absence de noyau ou de réseau, et une tâche de CI facultative réservée à workflow_dispatch (qui ne bloque jamais main). Documenté dans docs/VALIDATION.md (ligne CIO) et ROADMAP.md.

Corrigé#

  • Bac à sable adapté aux mobiles. Correction du débordement horizontal du .panel du bac à sable sur téléphone (un élément de grille CSS dont la valeur par défaut min-width: auto s'affichait environ 100 px plus large que la fenêtre d'affichage) via min-width: 0 et des commandes à largeur contrôlée ; vérifié sans défaut à 360 / 390 / 414 / 768 px. Alignement des boutons d'action « Épingler pour comparer » / « Télécharger le rapport » (boîtes de marge égales dans la ligne flex). Agrandissement des boutons d'exécution, curseurs, listes déroulantes et liens de navigation jusqu'au minimum d'environ 44 px pour les cibles tactiles WCAG 2.5.5 / Apple HIG sur téléphones et appareils tactiles, la taille sur ordinateur restant inchangée.

0.14.0 - 2026-06-08#

Corrigé#

  • Renforcement de la robustesse à l'issue d'une passe de test adverse. (1) sbas_protection_level rejette désormais les élévations/azimuts/variances non finis et les diagonales de covariance négatives ou non finies (une géométrie quasi singulière amplifiée par un petit σ pouvait auparavant franchir la barrière du pivot absolu et renvoyer un VPL NaN / un HPL absurde sous la forme d'un Some valide — une défaillance silencieuse de l'intégrité). (2) Le propagateur numérique (propagate/propagate_dopri) échoue de façon sûre sur un état initial non fini au lieu de faire tourner indéfiniment le contrôleur adaptatif. (3) L'assistant de cellule du MNT ne panique plus sur une grille à un seul échantillon (1×N). (4) L'azimut de lunar_look_angle est maintenu strictement dans [0, 360). (5) SphericalHarmonicField::from_gfc rejette un GM/rayon non physique (NaN / non positif).

Ajouté#

  • Binaire validation_report + artefact de version : un générateur sans dépendance qui émet un résumé de validation HTML d'une page, prêt à imprimer, qui indexe chaque validation imposée par la CI (SGP4 666/666, EGM2008, référentiels identiques bit pour bit, Allan du NIST, fiches techniques d'IMU, ARAIM/SBAS, reproductibilité sur 3 systèmes d'exploitation, couverture) avec son test et sa référence indépendante externe. Le workflow de publication génère kshana-validation-summary.html et le joint (avec la provenance SLSA) à chaque version étiquetée.
  • pytest d'interopérabilité numpy + durcissement des wheels : tests/python/test_numpy_interop.py (exécuté dans la CI) plus un conteneur manylinux épinglé et une étape de vérification auditwheel show dans la construction de la wheel.
  • Tutoriels et formation : docs/tutorials/ (trois tutoriels détaillés, des scénarios annotés par domaine, des exercices de niveau Tier-1/2/3) avec tests/tutorials.rs qui aligne chaque nombre cité sur la sortie réelle du moteur.
  • Artefacts de soumission externe (paper/, notebooks/, submissions/) : un brouillon d'article JOSS, un notebook quantique contre classique, et des kits prêts à déposer pour awesome-gnss / ESA Navipedia / NASA ASCL / ESA ESSR / ION/IAC, plus FUNDING.yml — préparant les étapes externes de soumission.
  • Navigation PNT alternative référencée au relief et combinée (module altpnt) : un navigateur de correspondance de relief TERCOM/SITAN sur un MNT (chargeur .hgt + générateur de fixtures synthétiques) et un navigateur combiné gravité + magnétisme (IGRF) + relief en environnement privé de GPS, exposés comme types de scénario terrain-nav et combined-altpnt. Validé par la convergence de la correspondance au relief (un décalage injecté connu est retrouvé) et par une erreur bornée du filtre combiné sur une fenêtre privée de GPS.
  • Géométrie LunaNet LANS (lunar) : sites nommés de la surface lunaire (Apollo 11/15/16, rebord de Shackleton) avec des coordonnées sélénographiques de référence, angles de visée depuis la surface (az/él/distance), visibilité/couverture et DOP du site, validés par rapport au rayon de la Lune, aux coordonnées publiées des sites et à l'identité d'élévation de 90° pour une position radiale à la verticale.
  • Bac à sable guidé dans le navigateur : curseurs en mode guidé, panneau de sortie à onglets, visite de première utilisation en superposition, modes de balayage de paramètres et de superposition de plusieurs exécutions, vue orbitale 3D sans dépendance en canvas/SVG (le paquet orbite émet désormais un eci_track additif), mode intégrable/iframe, et téléchargement sous forme de rapport HTML — chacun avec des tests unitaires node dans la CI.
  • Modèle d'erreur d'IMU validé par fiches techniques (tests/imu_allan_spec.rs) : l'ARW/VRW/instabilité de biais des ADIS16465/16488/16460 retrouvés à partir de l'écart-type d'Allan synthétisé et vérifiés par rapport aux spécifications du fabricant (identification NIST SP1065 / IEEE 952).
  • Validation des estimateurs d'Allan du NIST SP1065 (tests/allan_nist_sp1065_1000point.rs) : les quatre estimateurs reproduisent les écarts-types de référence publiés à 1000 points et les bornes de confiance du tableau 32.
  • Niveaux de protection SBAS / DO-229E, combinaison sans ionosphère L1/L5 et carte de compliance DO-316 (module sbas). sbas_protection_level forme la matrice de géométrie pondérée à partir de l'élévation/azimut de chaque satellite et du budget d'erreur UDRE/GIVE/aéroporté/troposphère, inverse la matrice normale (orbit::invert4 partagé) et projette les variances en HPL/VPL au moyen des facteurs K de DO-229E (PA 6.0/5.33, NPA 6,18). iono_free_l1l5 ajoute la pseudodistance GPS L1/L5 sans ionosphère (IS-GPS-705, γ₁₅ = 1.79327), validée pour annuler le retard ionosphérique indépendant du premier ordre du moteur. do316_compliance_map relie les exigences DO-316/DO-229E aux fonctions qui les implémentent. Validé par rapport aux définitions en forme close des facteurs K, à la géométrie de référence numpy inv(GᵀG) et à l'identité de covariance par deux voies ; le recoupement de concordance RTKLIB/gLAB sur les PL publiés est documenté comme en attente de revue dans docs/COMPLIANCE.md.
  • Gravité complète en harmoniques sphériques tesséral — le champ EGM2008 jusqu'au degré/ordre 70. Un nouveau gravity_sh::SphericalHarmonicField évalue le géopotentiel et son accélération dans le référentiel lié à la Terre à partir de coefficients C̄_nm, S̄_nm entièrement normalisés, en utilisant la récurrence stable de Legendre normalisée de Holmes–Featherstone (la dénormalisation déborderait à ce degré). Les coefficients fournis sont le produit EGM2008 de la NGA (domaine public, via ICGEM), intégrés dans egm2008_data.rs et reproduits bit pour bit par tools/gen_egm2008.py à partir du tools/egm2008_to70.gfc versionné ; tout modèle ICGEM .gfc se charge via from_gfc. Validé par rapport à trois références indépendantes : l'effondrement en masse ponctuelle (C̄00 seul = −μr/|r|³), un champ purement zonal reproduisant le forces::zonal_accel existant à environ 1e-9 près, et l'accélération analytique concordant avec le gradient par différences finies du potentiel sommé directement à moins de 1e-6.
  • Accélération de Lense–Thirring (entraînement des référentiels) en relativité générale (forces::lense_thirring_accel, IERS 2010 éq. 10,12), le terme gravitomagnétique au-delà de la correction de Schwarzschild existante, intégré au propagateur numérique par un nouvel indicateur ForceModel::lense_thirring(). Validée comme linéaire en moment cinétique de la Terre et inférieure de 1 à 2 ordres de grandeur au terme de Schwarzschild, le régime des mesures de LAGEOS / Gravity Probe B.
  • Un trait Propagator qui unifie les propagateurs d'orbite analytique et numérique. Le propagateur numérique de Cowell à modèle de forces est désormais un pair de premier rang de SGP4 : un nouveau type NumericalPropagator (état initial + ForceModel + Tolerance + choix d'un Integrator à doublement de pas ou de Dormand–Prince) et Sgp4 implémentent tous deux propagator::Propagator, dont state_at(t_seconds) -> StateVector renvoie l'état inertiel TEME en unités SI (m, m/s), de sorte que les deux sont interchangeables derrière un Box<dyn Propagator>. L'implémentation SGP4 est la conversion exacte km/min→SI de la méthode intrinsèque (vérifiée par un test d'égalité) ; l'implémentation numérique franchit, via le trait, la même barrière sub-métrique de Kepler exact, les deux pilotes adaptatifs concordent, et une PropagatorError fait remonter le code SGP4 sous-jacent.

0.13.0 - 2026-06-08#

Cette version comble la plus grande lacune d'exactitude du moteur : l'orientation de la Terre et la réduction des référentiels sont désormais réalisées au niveau d'une implémentation de référence (validées bit pour bit par rapport à ERFA/SOFA), la pile d'intégrité gagne un ARAIM bi-constellation sur de véritables TLE GPS+Galileo, et les couches de propagation, de capteurs quantiques, lunaire/cislunaire et géomagnétique s'approfondissent toutes — avec une API Python typée, un bac à sable de navigateur plus riche et une matrice de reproductibilité sur trois systèmes d'exploitation. Points forts :

  • Référentiels, bit pour bit. Nutation complète IAU 2000A et 2000B, précession IAU 2006, réduction GCRS↔ITRS IAU 2006/2000A fondée sur le CIO (X, Y, s), mouvement du pôle de l'IERS et référentiels de sortie TEME→GCRS/ITRS — chacun validé bit pour bit par rapport aux routines de référence ERFA/SOFA.
  • ARAIM bi-constellation (GPS + Galileo) sur de véritables TLE, avec HPL/VPL, sortie en diagramme de Stanford et un docs/ARAIM_REFERENCE.md ouvert.
  • PNT cislunaire : un propagateur CR3BP Terre–Lune, des référentiels MCI↔MCMF, des coordonnées sélénographiques et un scénario exécutable d'intégrité lunaire LunaNet.
  • Capteurs quantiques : systématiques de Coriolis et d'effet Stark alternatif pour l'interféromètre à atomes froids, un balayage de dérive et une validation par rapport au budget de Freier (2016).
  • Modèle de champ principal géomagnétique IGRF-14, autonome et validé.
  • API Python typée (PyO3 RunOutput/ScenarioMeta, .data(), scenario_kinds, validate_toml, stubs de types) avec une construction de wheel en CI, plus une sortie de propagateur GCRS/ITRS de premier rang et un export CCSDS OMM.
  • Crédibilité et reproductibilité : une comparaison directe de la précision de SGP4 avec la crate indépendante sgp4, une barrière de couverture en CI (environ 97 % des lignes de src/) et une matrice de reproductibilité sur trois systèmes d'exploitation (ubuntu/macos/windows).

Modifié#

  • Chaque graphique du bac à sable respecte désormais le thème du site. Les douze générateurs de graphiques SVG — le graphique de résultat/holdover (src/report.rs + src/chart.rs), le graphique d'écart-type d'Allan (web/app.js) et chaque graphique de scénario (src/hybrid.rs, jamming.rs, timetransfer.rs, spoof.rs, raim.rs Stanford + disponibilité, lunar.rs, ensemble.rs, sweep.rs, gnss_sim.rs, fusion/pack.rs, inertial/mod.rs) — utilisaient des panneaux bleu marine froids (#0e131b), des axes/textes gris froids et une palette de séries rouge/bleu/violet discordante. Ils utilisent désormais partout la palette graphite chaude : panneaux --bg, grille chaude --line, libellés --fg, avec une attribution cohérente des séries — quantique = or miel (--accent-bright), classique = ambre chaud (--partial), spécification/limite = --crit. Les vues à codage de sécurité conservent leur sens : le diagramme de Stanford du RAIM reste vert (disponible) / ambre (trompeur) / rouge (dangereux) / acier atténué (indisponible), et HPL/VPL se lisent en or/bronze.
  • Les graphiques se décrivent désormais eux-mêmes lorsqu'ils sont enregistrés ou téléchargés. Les deux graphiques intègrent leur titre dans le SVG (le titre du graphique d'Allan et son sous-titre « lower is better » ne figuraient auparavant que dans le HTML autour de l'image, de sorte qu'une image enregistrée n'avait pas de légende), et tous deux portent un pied de page de provenance — Kshana v<version> · <scenario-hash> · kshana.dev — afin qu'un graphique téléchargé se suffise à lui-même et reste reproductible.
  • Chaque graphique porte désormais le pied de page de provenance. Le pied de page — Kshana v<version> · scenario <hash> · kshana.dev — est apposé de façon centralisée pour tous les types de scénario dans api::run_toml (il n'était auparavant présent que sur les graphiques de holdover et d'Allan), de sorte que toute image enregistrée ou téléchargée — depuis le bac à sable, l'export .chart.svg de la CLI ou la fiche de résultats HTML — identifie sa version, l'empreinte de son scénario et sa source. Le hachage est étiqueté scenario par souci de clarté et provient du scenario_hash du résultat lorsqu'il est présent, avec un repli sur le hachage de la source pour les rapports d'intégrité/lunaires. Ce qu'est l'empreinte et pourquoi elle est là est documenté dans la section « Output » du README et dans docs/PROVENANCE.md.

Corrigé#

  • raim::chi2_quantile et l'échantillonneur de bruit de Stanford du RAIM ne paniquent plus sur des entrées hors plage / non finies (un résultat de fuzzing dépendant de l'ordre de read_dir, issu des nouveaux scénarios ARAIM). chi2_quantile protège désormais p/k comme normal_quantile (en renvoyant une valeur limite au lieu de paniquer avec assert!), et le Normal du bruit de Stanford de disponibilité borne σ à une valeur strictement positive — de sorte que la pile d'intégrité/ARAIM ne panique jamais sur des scénarios mutés ou mal configurés.

Ajouté#

  • Matrice de CI de reproductibilité multiplateforme. Une nouvelle tâche reproducibility-matrix exécute les tests de reproductibilité sur ubuntu-latest, macos-latest et windows-latest à chaque push. Comme le JSON de résultat complet n'est pas identique octet pour octet d'un système à l'autre (divergence de libm au dernier ULP), elle vérifie exactement la projection invariante par plateforme — l'empreinte d'entrée plus la forme de la sortie, épinglées par scénario sous forme de références SHA-256 dans tests/golden/ par le nouveau tests/cross_platform_golden.rs — en plus des valeurs numériques épinglées (golden.rs, à 1e-6 près), des états SGP4 (sgp4_verification.rs, à 2e-5 km près) et du déterminisme au sein d'un même processus (determinism.rs). Ensemble, ils prouvent la reproductibilité multiplateforme sur trois systèmes d'exploitation sans la fragilité d'un hachage octet par octet de l'intégralité de la sortie. docs/REPRODUCIBILITY.md documente cette séparation.
  • Barrière de couverture de code dans la CI. Une nouvelle tâche coverage exécute cargo-tarpaulin avec le moteur fondé sur les sources LLVM, publie un rapport lcov comme artefact de construction et impose un plancher de couverture de lignes sur src/ (tables de données générées, point d'entrée de la CLI, tests et ressources web exclus). La couverture de lignes mesurée est d'environ 97 % sur src/ (SGP4 et modules d'horloge ≥ 95 %) ; la barrière est fixée à 85 % — au-dessus de l'objectif de ≥ 80 % et à distance de la valeur mesurée, de sorte qu'elle détecte les régressions sans déclenchements intempestifs. Un badge de couverture est publié dans le README.
  • SGP4/SDP4 comparé directement à la crate indépendante sgp4. Un nouveau test (tests/sgp4_crate_comparison.rs) recoupe le propagateur de Kshana avec la bibliothèque SGP4 en Rust la plus utilisée (neuromorphicsystems/sgp4, ajoutée comme dépendance de développement réservée aux tests) sur les mêmes 666 vecteurs AIAA 2006-6753. Les deux étant pilotées avec le modèle de gravité WGS72 qu'utilisent les vecteurs, les deux implémentations indépendantes concordent à moins du micron sur les orbites proches de la Terre et résonantes, et à 4,12 mm dans le pire des cas sur tous les régimes, toutes deux reproduisant le tableau de référence tcppver.out. Le tableau de comparaison versionné (tests/fixtures/sgp4_comparison.md, régénéré via KSHANA_REGEN_FIXTURES=1) détaille le résultat par régime (LEO/MEO, espace lointain, résonance de ½ jour et de 1 jour) et note les quatre cas volontairement pathologiques que la crate rejette à la construction. Les assertions en direct maintiennent les deux à moins de 2e-5 km de la référence et en accord à moins de 4e-5 km — une garde contre les régressions, pas un résultat ponctuel. C'est un gage de qualité face à la concurrence : l'exactitude par rapport à une base de code indépendante, et pas seulement à un tableau statique. (Le from_elements par défaut de la crate utilise WGS84 et diffère donc de la référence WGS72 d'environ un km — signalé honnêtement dans le texte du tableau.)
  • L'export CCSDS OMM est désormais accessible de bout en bout. Le rédacteur OMM (src/omm.rs) n'avait auparavant aucun chemin CLI/API ; les éléments moyens d'un scénario orbit peuvent désormais être publiés sous forme de catalogue OMM CCSDS 502.0-B-2 — un message OMM KVN par satellite défini par TLE — via kshana <orbit.toml> --export-omm out.omm, ou export_omm = true dans le scénario écrit automatiquement <scenario>.omm (à l'image de l'existant --export-sp3). Chaque message porte le numéro de catalogue NORAD réel du satellite, sa désignation internationale COSPAR (YYYY-NNNP) et son époque (forme jour de l'année du CCSDS), analysés à partir de la ligne 1 du TLE par le nouveau tle::parse_tle_identity ; la ligne de nom devient OBJECT_NAME (sinon OBJECT <id>). CREATION_DATE est l'époque du scénario, et non l'heure réelle, de sorte que la sortie est reproductible. Nouvelle API : api::export_omm / api::auto_export_omm, OmmFile::from_tle_block, OrbitClockScenario::to_omm_string. Un scénario Walker synthétique ou RINEX (sans éléments moyens TLE) renvoie une erreur au lieu d'émettre un fichier vide. Validé par rapport à l'instantané gps-ops de 30 satellites fourni (tests/sp3_export_roundtrip.rs).
  • Info-bulles interactives de lecture sur les graphiques du bac à sable. Déplacer le curseur sur un graphique aimante un réticule sur l'échantillon le plus proche et affiche une info-bulle de valeur (web/hover.mjs, raccordée dans web/app.js). Sur le graphique d'Allan, elle indique τ et le σ_y(τ) de chaque horloge ; sur les graphiques de scénarios en série temporelle (holdover d'horloge, navigation à l'estime, transfert de temps, PNT hybride, GNSS/INS), elle indique le temps et la valeur de chaque suite dans les unités propres du graphique (ns / m / ps / utilisation), analysées à partir du résultat afin que la lecture corresponde à la courbe. Les diagrammes spécialisés (RAIM, leurrage, balayage) n'ont pas de superposition. Les graphiques restent des <img> blob autodescriptifs — la superposition est un réticule transparent + une info-bulle par-dessus, de sorte que le téléchargement, la comparaison et l'export ne sont pas touchés. Les calculs de coordonnées (échantillon le plus proche, curseur→fraction du tracé, analyse de polyligne) font l'objet de tests unitaires (web/hover.test.mjs, exécutés dans la CI).
  • Mode de comparaison A/B dans le bac à sable. Épinglez n'importe quelle exécution comme référence de base A, lancez un second scénario, et les deux s'affichent côte à côte avec un tableau d'écarts de figures de mérite (holdover, RMS/p95 de synchronisation temporelle, disponibilité) qui colore le gagnant pour chaque métrique (web/compare.mjs, raccordé dans web/app.js ; logique d'écart testée unitairement dans web/compare.test.mjs, exécutée dans la CI). Toutes les valeurs sont insérées sous forme de texte et tous les graphiques via des <img> blob, de sorte que rien provenant d'une chaîne de scénario n'est jamais injecté comme balisage.
  • Boutons de téléchargement des graphiques (SVG + PNG). Chaque graphique du bac à sable dispose désormais d'une barre d'outils « Télécharger SVG / PNG » assortie au thème (web/chartdl.mjs, raccordée dans web/app.js). Le SVG restitue l'original fidèle et redimensionnable ; le PNG rastérise cette même image autodescriptive à 2x pour les diapositives et les documents. Les fichiers sont nommés d'après leur provenance — kshana-<chart>-v<version>-<scenario-hash>.<ext> — et la logique de nom/taille de fichier fait l'objet de tests unitaires (web/chartdl.test.mjs, exécutés dans la CI).
  • Modèle de champ principal géomagnétique IGRF-14 (src/igrf.rs). Le champ en harmoniques sphériques standard de l'IAGA (degré/ordre 13, époque 2025,0 + variation séculaire 2025–2030 ; coefficients générés par machine à partir du fichier officiel igrf14coeffs.txt par tools/gen_igrf.py dans src/igrf_data.rs, reproductibles bit pour bit). Une synthèse normalisée de Schmidt renvoie le vecteur de champ (nord/est/bas) et les éléments dérivés (déclinaison, inclinaison, intensité horizontale/totale) en tout lieu/date géodésique, plus le pôle géomagnétique et l'intensité du dipôle — le pendant magnétique de l'apparieur de cartes de gravité pour la navigation PNT alternative. Validé de façon autonome : la synthèse concorde avec le dipôle incliné exact en forme close, le champ analytique complet de degré 13 concorde avec une différence finie du potentiel scalaire, l'axe du dipôle reproduit le pôle géomagnétique connu (~80,7°N, −72,7°E) et une intensité d'environ 29,7 µT, et le champ global est physique.
  • Liaisons Python typées (src/python.rs). Au-delà des run/run_full à chaîne en entrée et chaîne en sortie, le module expose désormais une classe typée RunOutput (.json, .svg, .summary et un accesseur .data() qui renvoie le résultat analysé dans un dict Python natif — sans nouvelle analyse JSON, enveloppable par NumPy), plus run_typed, scenario_kinds() (liste analysée de dicts de métadonnées) et validate_toml() (une liste de messages d'erreur, sans levée d'exception). Fournit un stub de types PEP 561 (kshana.pyi + py.typed) pour mypy/pyright/les éditeurs et un guide de démarrage docs/PYTHON_API.md. Les fonctions existantes sont inchangées.
  • Référentiels de sortie de premier rang pour les propagateurs (énumération Frame de src/orbit.rs + position_in_frame + state_gcrs). Tout Propagator (Kepler, SGP4, RINEX, GLONASS, SP3) peut désormais émettre sa position en TEME, GCRS (≈ J2000) ou ITRS (lié à la Terre) — TEME en natif, GCRS via la réduction TEME→GCRS validée, ITRS en enchaînant celle-ci avec la rotation gcrs_to_itrs CIO IAU 2006/2000A — ainsi que son état GCRS complet (position + vitesse) via state_gcrs. La sortie inertielle à la date n'est plus limitée à TEME.
  • Réduction céleste-terrestre IAU 2006/2000A fondée sur le CIO (src/cio.rs). La chaîne GCRS↔CIRS↔ITRS moderne, sans équinoxe : coordonnées du CIP X, Y extraites de la matrice de biais-précession-nutation IAU 2006/2000A (réutilisant la précession FW validée + la nutation 2000A avec l'ajustement P03 de eraNut06a), la série du localisateur du CIO s à 66 termes (eraS06, générée par machine à partir de la référence ERFA par tools/gen_s06.py dans src/cio_s06_data.rs, reproductible bit pour bit), la matrice GCRS→CIRS (eraC2ixys), l'angle de rotation de la Terre (eraEra00) et la rotation complète GCRS→ITRS (eraC2tcio, composée avec le mouvement du pôle de l'IERS existant). Validé bit pour bit par rapport au vecteur de test publié eraXys06a (X=0.5791308482835292617e-3, Y=0.4020580099454020310e-4, s=-0.1220032294164579896e-7 à JD_TT 2453736,5), ainsi qu'aux vecteurs de test eraC2ixys et eraEra00. La chaîne CIO et l'ancienne réduction TEME à équinoxe/GMST-1982 s'accordent, à la différence près de leur convention de temps sidéral documentée d'environ 2·(équation des équinoxes). C'est la réduction rigoureuse que le chemin équinoxe/GMST approximait.
  • Série complète de nutation IAU 2000A (src/nutation.rs nutation_iau2000a, nutation_matrix_2000a). Le modèle MHB2000 complet — 678 termes luni-solaires + 687 termes planétaires — précis à < 0,1 mas, en plus de la troncature 2000B à 77 termes existante. Les tables sont générées par machine à partir de la référence nut00a de l'IAU SOFA / ERFA par tools/gen_nut00a.py dans src/nutation_iau2000a_data.rs (le générateur reproduit le fichier versionné bit pour bit), et toute la série — les deux jeux d'arguments fondamentaux IERS-2003 et MHB2000 ainsi que les longitudes planétaires — est validée bit pour bit par rapport au vecteur de test publié eraNut00a (Δψ = −0.9630909107115518e-5, Δε = 0.4063239174001679e-4 à JD_TT 2453736,5, à 1e-13 rad près). La réduction TEME→GCRS par défaut conserve la série 2000B (~1 mas, en deçà de la simplification de rotation du référentiel de vitesse de la chaîne) ; nutation_matrix_2000a expose la matrice à la date à < 0,1 mas pour les appelants qui en ont besoin.
  • Scénario exécutable d'intégrité lunaire (kind = "lunar-integrity", scenarios/lunanet-araim.toml). Raccorde la passe de niveau de protection du pôle sud lunaire (src/lunar.rs LunarScenario → south_pole_hpl_pass) à l'exécuteur de scénarios avec un LunarReport JSON et un graphique SVG HPL en fonction du temps, de sorte que le cas d'intégrité cislunaire est accessible directement depuis la CLI. Il met honnêtement en évidence l'écart : avec le σ_URE de LANS de 30 m, le HPL du pôle sud (≈ 260–450 m) dépasse une limite d'alerte de 50 m (0 % de disponibilité) — l'intégrité du PNT lunaire n'est pas encore atteinte.
  • Disponibilité ARAIM bi-constellation sur de véritables TLE GPS+Galileo, et raccordement à l'exécuteur de scénarios (src/raim.rs, src/orbit.rs, scenarios/araim-gps-galileo.toml). Ajoute araim_dual_constellation_availability (le moteur ARAIM avancé — pannes d'un seul satellite et de toute la constellation — exécuté sur une grille temporelle) et visible_positions_labeled, et le raccorde à l'exécuteur IntegrityScenario via un indicateur araim_dual, de sorte qu'une étude ARAIM multi-GNSS est accessible directement depuis le TOML. Un test sur données réelles (tests/araim_dual_real_data.rs) sur des instantanés Celestrak GPS+Galileo du 2026-06-07 intégrés montre que la mise en commun de Galileo fait passer la disponibilité ARAIM de 0,21 à 0,67 sous un VAL exigeant de 12 m (10,5→21,8 satellites en vue), tandis que le mode robuste aux pannes de constellation est fondamentalement limité avec seulement deux constellations — la raison quantitative pour laquelle une intégrité bi-constellation robuste pousse vers une troisième constellation ou le SBAS. Reste à faire, en toute honnêteté : la reproduction numériquement exacte du tableau A-3 de la TN ARAIM de l'UE par rapport à une seule époque verrouillée sur une version, et un enregistrement de fixture Zenodo.
  • Problème circulaire restreint à trois corps (CR3BP) pour le système Terre–Lune (src/cr3bp.rs). Un nouveau noyau de dynamique cislunaire que les propagateurs à deux corps/SGP4 ne peuvent pas fournir : équations du mouvement en référentiel tournant (cr3bp_accel), un propagateur RK4 (propagate_cr3bp), l'intégrale de la constante de Jacobi (jacobi_constant) et les cinq points de Lagrange (lagrange_points). Validé par rapport à des ancrages en forme close / publiés : les points colinéaires Terre–Lune (L1 ≈ 0,83692, L2 ≈ 1,15568, L3 ≈ −1,00506), les points équilatéraux exacts L4/L5 = (½−μ, ±√3/2, 0), les cinq confirmés comme équilibres du champ, la constante de Jacobi conservée à la précision de l'intégrateur lors de la propagation, et la force de rappel hors plan qui rend possibles les orbites de halo/NRHO. C'est la base pour représenter une véritable NRHO. Reste à faire, en toute honnêteté : les conditions initiales périodiques d'une NRHO 9:2 corrigée différentiellement, le modèle excentrique/à éphéméride (DE), et la transformation dénormalisée vers les référentiels sélénocentriques de src/lunar.rs.
  • Mouvement du pôle de l'IERS et réduction TEME→ITRF (src/frames.rs). Ajoute polar_motion_matrix (iauPom00 de SOFA : W = Rx(−y_p)·Ry(−x_p)·Rz(s′) avec le localisateur du TIO s′), pef_to_itrf / itrf_to_pef et teme_to_itrf — la rotation TEME→PEF fondée sur GMST suivie du mouvement du pôle — pour obtenir une position liée à la Terre précise à l'ITRF, au-dessus du teme_to_ecef limité à GMST (le mouvement du pôle est un effet de plusieurs dizaines de mètres au rayon orbital). x_p/y_p sont des grandeurs IERS observées que fournit l'appelant. Reste à faire, en toute honnêteté : une chaîne entièrement fondée sur le CIO (X, Y, s) et un recoupement numérique ANISE/SPICE à moins de 10 m restent à venir.
  • Systématiques de l'interféromètre à atomes froids, balayage de dérive et validation par un dispositif publié (src/inertial/quantum_imu.rs, docs/QUANTUM.md). Étend l'accéléromètre CAI issu des premiers principes avec les deux principales systématiques déterministes : la phase de Coriolis/rotation Φ_cor = 2·k_eff·v_⊥·Ω·T² (coriolis_phase, avec le biais d'accélération équivalent 2·Ω×v via coriolis_accel_bias) et la phase de déplacement lumineux AC-Stark Φ_LS = (δ_LS,1 − δ_LS,3)/Ω_eff (ac_stark_phase, qui s'annule par symétrie π/2–π–π/2 pour un déplacement constant). Ajoute cai_drift_sweep (dérive de position à l'estime en fonction du temps de cycle — le cœur d'une comparaison quantique/classique) et un test de validation par rapport au gravimètre mobile de Freier et al. 2016 (arXiv:1512,05660) : le plancher de bruit de projection quantique modélisé se situe en dessous du bruit à court terme publié de 96 nm/s²/√Hz, à environ 2 ordres de grandeur. docs/QUANTUM.md est mis à jour. Reste à faire, en toute honnêteté : les systématiques de front d'onde et de pointage du faisceau, la résolution de l'ambiguïté de franges, la reproduction exacte de l'essai en vol CARIOQA-PMP / Boeing-AOSense (qui exige des DSP de plateforme publiées) et un préréglage du bac à sable JS.
  • Réduction de référentiel cislunaire et passe d'intégrité au pôle sud lunaire (src/lunar.rs). Étend le moteur ARAIM lunaire avec la rotation MCI↔MCMF (inertiel centré sur la Lune ↔ lié à la Lune) (mci_to_mcmf / mcmf_to_mci, un modèle simplifié de rotation moyenne au taux sidéral lunaire), la latitude/longitude/altitude sélénographiques (mcmf_to_selenographic / selenographic_to_mcmf) et south_pole_hpl_pass — un récepteur posé dans la région d'Artemis face à un ensemble représentatif de relais LunaNet sur une passe de 24 h, qui quantifie honnêtement l'écart d'intégrité : avec le σ_URE de LANS nominal de 30 m, le niveau de protection est fini mais dépasse une limite d'alerte d'opérations de surface de 50 m. Reste à faire, en toute honnêteté : l'éphéméride précise de la NRHO de LANS (une orbite cislunaire à 3 corps), la libration physique / le pôle lunaire en précession (DE421/SPICE) et un scénario TOML LunaNet restent à venir.
  • Message de support d'intégrité ARAIM, SVG du diagramme de Stanford et référence ARAIM ouverte (src/raim.rs, docs/ARAIM_REFERENCE.md). Ajoute un IntegritySupportMessage explicite (σ_URA / σ_URE / b_nom / P_sat / P_const, avec les valeurs de référence WG-C GPS+Galileo et des convertisseurs .fault_priors() / .dual_fault_priors() vers les moteurs araim_raim à panne unique et araim_dual_raim à l'échelle de la constellation), un moteur de rendu autonome stanford_svg du diagramme d'intégrité de Stanford (les quatre zones, la frontière PL = error, les guides de limite d'alerte, un marqueur codé par couleur par époque), et docs/ARAIM_REFERENCE.md documentant l'algorithme, l'ISM, les hypothèses de panne, le contrat de niveau de protection et l'avantage de la bi-constellation. Des tests démontrent le gain de géométrie/redondance (la mise en commun d'une seconde constellation resserre le HPL à panne unique) et la tolérance aux pannes de constellation (l'utilisateur bi-constellation survit à la perte d'une constellation entière ; un utilisateur mono-constellation ne le peut pas). Reste à faire, en toute honnêteté : reproduire numériquement le tableau A-3 de la TN ARAIM de l'UE / le chiffre de disponibilité de 15 à 25 % par rapport à un instantané TLE réel verrouillé sur une version, un enregistrement de fixture Zenodo, et le raccordement de araim_dual_raim à l'exécuteur de fichiers de scénario.
  • Nutation IAU 2000B et réduction inertielle complète TEME→GCRS/J2000 (src/nutation.rs). Ajoute les deuxième et troisième pièces d'une véritable réduction de référentiel inertiel au-dessus de la précession IAU 2006 livrée : la série de nutation luni-solaire MHB2000 à 77 termes (nutation_iau2000b, la troncature standard IAU 2000B précise à ~1 mas) avec les arguments fondamentaux de Delaunay et la matrice de nutation iauNumat de SOFA, et la chaîne de Vallado AIAA-2006-6980 TEME→TOD (équation des équinoxes) → TOD→MOD (nutation) → MOD→GCRS (biais-précession) exposée sous la forme teme_to_gcrs(r, v, jd_tt) / gcrs_to_teme. La série, les arguments et les constantes d'unité sont transcrits de la référence nut00b de l'IAU SOFA / ERFA et validés bit pour bit par rapport au vecteur de test publié eraNut00b (Δψ, Δε à 1e-13 rad près). Reste à faire, en toute honnêteté : la série complète IAU 2000A de 678 termes (à moins de 0,1 mas), un recoupement numérique ANISE/SPICE à moins de 10 m et le mouvement du pôle restent à venir (voir ROADMAP.md).

0.12.0 - 2026-06-06#

Cette version apporte le premier propagateur d'orbite non analytique de Kshana — un intégrateur de Cowell avec un modèle de forces hiérarchique à six perturbations (deux corps + zonaux J2–J6 + troisième corps Soleil/Lune piloté par l'époque + pression de rayonnement solaire avec ombre conique et pénombre + traînée atmosphérique + correction relativiste post-newtonienne de Schwarzschild) piloté au choix par deux intégrateurs adaptatifs (RK4 à doublement de pas et la paire emboîtée de Dormand–Prince RK5(4)) — avec une couche de manœuvres / de conception de trajectoire (poussées impulsionnelles et finies, un solveur de Lambert d'Izzo et un balayage porkchop), une couche de PNT alternatif par appariement de cartes de gravité qui retrouve une trace privée de GPS de 60 minutes à moins de 500 m, une chaîne de détermination d'orbite par lots + séquentielle, et un UKF GNSS/INS à couplage serré à 17 états complet avec navigation à l'estime par CAI quantique. Chaque capacité numérique est alignée sur une vérité analytique ou une forme close dérivée à la main ; les perturbations désactivées par défaut laissent intacts les jeux de référence publiés.

Ajouté#

  • Correction relativiste post-newtonienne (de Schwarzschild) (forces::relativistic_accel + propagator::ForceModel::relativity). Ajoute la perturbation de relativité générale dominante sur une orbite proche de la Terre — le principal moteur de l'avance relativiste du périgée — sous la forme β = γ = 1 de l'IERS / Montenbruck–Gill a = (μ/c²r³)·{[4μ/r − v²]·r + 4(r·v)·v}. Comme la traînée atmosphérique, elle est dépendante de la vitesse ; elle emprunte donc le second membre de l'intégrateur (r, v) via [accel_rv], en option et désactivée par défaut. Validée de façon autonome : sur une orbite circulaire, elle se réduit à la forme close 3μ²/(c²r³)·r̂ (purement radiale et vers l'extérieur, composantes hors axe exactement nulles) ; son rapport à la force à deux corps est le ≈1.9·10⁻⁹ classique en LEO (la signature de μ/(c²r)) ; un cas à vitesse radiale concorde avec la forme simplifiée à la main μ(4μ + 3v²r)/(c²r³) ; et dans le propagateur, elle perturbe l'orbite sans la dissiper — le demi-grand axe est conservé à bien moins d'un mètre par jour, l'opposé structurel de la décroissance monotone de la traînée. Comme elle est désactivée par défaut, les jeux de référence à deux corps/J2/zonaux restent intacts. Le réglage des paramètres PPN (β,γ) et le terme d'entraînement des référentiels de Lense–Thirring restent à venir.
  • Modèle d'ombre conique à ombre + pénombre (forces::conical_shadow), désormais utilisé par la pression de rayonnement solaire. Fait passer l'éclipse binaire à cylindre d'ombre à un facteur ν ∈ [0,1] lisse : le Soleil et la Terre sont modélisés comme des disques de rayons angulaires apparents a = asin(R☉/d☉), b = asin(Rₑ/|r|) avec une séparation apparente des centres c, et ν vaut un moins la fraction du disque du Soleil occultée par le disque de la Terre (l'aire de recouvrement lenticulaire de deux cercles) — plein soleil pour c ≥ a+b, ombre totale pour c ≤ b−a, annulaire pour c ≤ a−b, et une pénombre continue entre les deux. srp_accel l'utilise désormais, de sorte que la force de pression de rayonnement diminue progressivement pendant l'éclipse au lieu de s'activer/se désactiver brutalement. Ajoute le forces::SOLAR_RADIUS nominal de l'IAU. Validé de façon autonome : ν = 1 en plein soleil et ν = 0 au cœur de l'ombre (exact), une pénombre lisse et monotone (ν passe de 0 à ~½ en c = b puis à 1 sur la bande [b−a, b+a]), et la pénombre conique s'étend au-delà du cylindre d'ombre (un point que le cylindre binaire considère comme pleinement éclairé vaut 0 < ν < 1 pour le cône). Le cylindrical_shadow plus simple reste disponible ; l'assombrissement centre-bord solaire et l'ombre de la Terre aplatie restent à venir.
  • Intégrateur emboîté Dormand–Prince RK5(4) (integrator::dopri54_step / integrator::integrate_dopri + propagator::propagate_dopri). Ajoute la paire emboîtée standard de Dormand–Prince (1980) à tableau de Butcher à côté du pilote existant RK4 à doublement de pas : sept étages FSAL fournissent une solution d'ordre 5 et une estimation d'erreur d'ordre 4 à partir d'un seul jeu d'évaluations (7 contre 11 appels de fonction par pas), une estimation d'erreur locale moins coûteuse. Le pilote adaptatif réutilise la même norme d'erreur quadratique moyenne et le même contrôleur de pas 0.9·(1/err)^(1/5), c'est donc une alternative directe ; propagator::propagate_dopri l'expose sur le modèle de forces orbital. Validé de façon autonome : l'estimation d'erreur emboîtée est en O(h⁵) (diviser le pas par deux la réduit d'un facteur ~32) ; DP5(4) intègre y' = y jusqu'à e et l'oscillateur harmonique sur 50 périodes en conservant l'énergie à moins de 1e-6 ; il atteint le même point d'arrivée à la même tolérance avec moins d'évaluations de fonction que le doublement de pas (sans sacrifier la précision) ; et propagate_dopri franchit la même barrière de vérité analytique que le chemin RK4 — sub-métrique par rapport à la solution exacte de Kepler en variables universelles sur une orbite LEO de 24 h — tandis que les deux pilotes concordent à moins de 1 m sur une orbite J2..J6 (sans forme close). Les paires emboîtées d'ordre supérieur (RKF7(8) / DOP853) restent à venir.
  • Traînée atmosphérique raccordée au propagateur comme première force dépendante de la vitesse (forces::atmospheric_density + forces::drag_accel + propagator::ForceModel::drag). Ajoute l'atmosphère exponentielle par morceaux du tableau 8-4 de Vallado ρ = ρ0·exp(−(h−h0)/H) (28 bandes du niveau de la mer jusqu'au-delà de 1000 km, bornée sous la surface) et la traînée quadratique a = −½ · ρ(h) · (C_D·A/m) · |v_rel| · v_rel par rapport à l'atmosphère en corotation v_rel = v − ωₑ ẑ × r (forces::EARTH_ROTATION_RATE = 7.2921151467e-5). Comme la traînée dépend de la vitesse, ForceModel gagne un nouveau accel_rv(t, r, v) et le second membre de l'intégrateur transmet désormais la vitesse (f(t,[r;v]) = [v; a(t,r,v)]) ; le accel_at dépendant de la seule position est inchangé, de sorte que les termes conservatifs et les jeux de référence restent intacts. Validé de façon autonome : la densité s'ancre à la valeur de 1,225 kg/m³ au niveau de la mer, est bornée sous la surface, décroît de façon monotone à travers la LEO, se situe dans la bande moyenne solaire d'environ 1e-12 kg/m³ à 400 km, et sa hauteur d'échelle locale retrouvée (≈ 58 km à 400 km) est physique ; la traînée s'oppose à la vitesse relative de corotation à la magnitude LEO d'environ 2e-6 m/s² pour C_D·A/m = 0.02 m²/kg ; et — la signature essentielle — la traînée est dissipative : une orbite à 300 km perd de l'énergie spécifique de façon monotone et son demi-grand axe décroît d'environ un km par jour, de façon bornée, alors que la référence de base dans le vide conserve l'énergie à moins de 1e-9. La densité thermosphérique NRLMSISE-00 (la clause de densité de traînée à moins de 5 %) reste à venir.
  • Pression de rayonnement solaire raccordée, pilotée par l'époque, au modèle de forces du propagateur (forces::srp_accel + propagator::ForceModel::solar_radiation). Ajoute le modèle SRP à boulet de canon a = ν · P☉ · cᵣ · (A/m) · (AU/d)² · d̂ avec un facteur d'éclipse à ombre cylindrique (forces::cylindrical_shadow, ν ∈ {0 1}) : la pression de rayonnement P☉ = Φ☉/c issue de l'irradiance solaire totale moderne de 1361 W/m² (≈ 4,5398·10⁻⁶ N/m²), la décroissance du flux en carré inverse (AU/d)² et la poussée radiale à l'opposé du Soleil. Elle emprunte le même second membre piloté par l'époque que le troisième corps, en échantillonnant l'éphéméride ephem du Soleil une seule fois à l'époque avancée epoch_jd_tt + t/86400 partagée entre le troisième corps Soleil et la SRP. Composable : with_zonals_j2_j6().third_body(true, true, epoch).solar_radiation(1.5, 0.02). Validé de façon autonome par rapport à des signatures dérivées à la main : la pression de rayonnement à 1 UA s'établit à la valeur classique ≈ 4,5398·10⁻⁶ N/m² ; la SRP d'un satellite LEO pleinement éclairé est identique bit pour bit à la formule du boulet de canon, pointe à l'opposé du Soleil et se situe dans la bande d'environ 1,36·10⁻⁷ m/s² pour cᵣ = 1,5, A/m = 0,02 m²/kg ; doubler la distance au Soleil divise la magnitude par quatre (carré inverse) ; l'ombre cylindrique n'éclipse que le cylindre d'ombre (à l'opposé du Soleil et à moins d'un rayon terrestre de la ligne Terre–Soleil) et donne une SRP exactement nulle en éclipse ; et dans le propagateur, la SRP perturbe une orbite LEO d'une faible quantité bornée qui varie à peu près linéairement avec A/m — tandis qu'un modèle sans perturbations reste indépendant du temps bit pour bit, laissant intacts les jeux de référence à deux corps/J2/zonaux. L'ombre conique à pénombre (ν lisse dans [0 1]), la traînée atmosphérique et la validation croisée externe avec GMAT/Orekit restent à venir.
  • Troisième corps Soleil/Lune piloté par l'époque, raccordé au second membre variable dans le temps du propagateur (propagator::ForceModel::third_body / accel_at). La perturbation du troisième corps n'est plus un terme de force autonome — elle est désormais intégrée par le propagateur de Cowell comme une force véritablement variable dans le temps : chaque évaluation du second membre échantillonne les positions du Soleil et de la Lune de ephem à l'époque avancée epoch_jd_tt + t/86400 (en réutilisant precession::julian_centuries_tt pour la conversion jour↔siècle), de sorte que les perturbateurs se déplacent le long de leurs orbites pendant l'intégration au lieu d'être figés au départ. Composable avec n'importe quel modèle de gravité (ForceModel::with_zonals_j2_j6().third_body(true, true, epoch)). Validé de façon autonome : le terme Soleil du second membre est identique bit pour bit à third_body_accel évalué à la position d'éphéméride de cet instant, à t = 0 comme à t = 1 day (ce qui prouve exactement le câblage 86400 s ↔ 1 jour ↔ 1/36525 siècle), le perturbateur avance d'environ 2,6·10⁹ m/jour entre les échantillons (il n'est pas figé), les magnitudes de marée instantanées en LEO atteignent les bandes classiques d'environ 5·10⁻⁷ m/s² (Soleil) et d'environ 1,1·10⁻⁶ m/s² (Lune, ≈ 2× le Soleil), chaque corps perturbe de façon mesurable la trajectoire d'une journée tout en restant borné, et le même état initial propagé à des époques espacées d'un quart d'année donne une trajectoire différente (l'axe de marée tourne de 90°) — tandis qu'un modèle sans aucun des deux corps activé est indépendant du temps bit pour bit, laissant intacts les jeux de référence à deux corps/J2/zonaux. La précision d'éphéméride de niveau DE et la validation croisée externe avec GMAT/Orekit restent à venir.
  • Éphéméride lunaire à basse précision (ephem::moon_position), qui complète la paire de troisièmes corps Soleil/Lune. Ajoute la série lunaire à basse précision de Montenbruck et Gill (§3.3.2) à côté du modèle du Soleil, de sorte que le forces::third_body_accel indépendant du corps peut désormais être piloté par l'un ou l'autre des luminaires sans noyau DE/SPK externe. Validée de façon autonome par rapport à des signatures lunaires dérivées à la main : la distance géocentrique reste dans l'enveloppe réelle périgée/apogée (~356 500–406 700 km) sur un mois et sa moyenne mensuelle retrouve le demi-grand axe d'environ 384 400 km ; la latitude écliptique ne dépasse jamais l'inclinaison orbitale lunaire d'environ 5,3° (vérifié en projetant sur le pôle de l'écliptique en coordonnées équatoriales, ce qui valide ensemble la série de latitude et la rotation d'obliquité) ; la direction de la Lune revient à moins de 1° après un mois sidéral (27,3217 j) et son mouvement quotidien reste dans la bande physique de 12 à 15°/jour ; et la perturbation lunaire du troisième corps sur un satellite LEO a la magnitude classique d'environ 1,1·10⁻⁶ m/s² (≈ le double de celle du Soleil). La précision de position de niveau DE, la traînée atmosphérique et la SRP restent à venir.
  • Gravité d'un troisième corps (le Soleil) avec une éphéméride intégrée à basse précision (forces::third_body_accel, ephem::sun_position). Ajoute la perturbation du troisième corps au modèle de forces : a = GM₃·((s−r)/|s−r|³ − s/|s|³) (attraction directe moins le terme indirect que le référentiel géocentrique doit soustraire), avec la position du Soleil fournie par la série analytique à basse précision de Montenbruck et Gill du nouveau module ephem — aucun noyau DE/SPK externe n'est nécessaire pour une exécution de faible fidélité. Validé de façon autonome : l'accélération concorde avec le gradient exact de son propre potentiel perturbateur (third_body_potential), la perturbation s'annule au géocentre et a la magnitude classique d'environ 5·10⁻⁷ m/s² sur un satellite LEO, et l'éphéméride du Soleil atteint des ancrages J2000 dérivés à la main — distance au périhélie ≈ 1,471·10¹¹ m, déclinaison ≈ −23° près du solstice de décembre, un mouvement apparent ≈ 1°/jour (≈ 90° par quart d'année), et une distance qui reste dans l'enveloppe de 0,983 à 1,017 UA de l'orbite terrestre sur une année complète. Fournit la moitié « troisième corps » de l'étape du modèle de forces de l'étape clé du propagateur numérique (la Lune est fournie dans une entrée voisine ci-dessus) ; la précision de position de niveau DE, la traînée atmosphérique et la SRP restent à venir.
  • Modèle de forces à harmoniques zonaux J2–J6 (forces::zonal_accel / zonal_potential). Étend le modèle de forces du propagateur de Cowell au-delà de J2 jusqu'au champ zonal terrestre complet jusqu'au degré 6 (les J2..J6 EGM-96 non normalisés publiés standard), raccordé au propagateur sous la forme ForceModel::with_zonals_j2_j6(). L'accélération est le gradient analytique exact du potentiel perturbateur zonal R(r) = −(μ/r)·Σ Jₙ(Re/r)ⁿPₙ(z/r) (polynômes de Legendre par récurrence ascendante), validé de trois manières indépendantes : elle se réduit au j2_accel, validé sur 666 vecteurs, à la précision machine lorsqu'elle est restreinte à [J2] ; elle concorde avec le gradient numérique de son propre potentiel sur tout le champ J2..J6 (le contrôle de référence des champs conservatifs) ; et les termes impairs J3 comparés aux termes pairs J2/J4..J6 présentent leur (anti)symétrie nord–sud caractéristique sous z → −z — l'asymétrie en forme de poire. Une orbite J2..J6 propagée conserve l'énergie totale (cinétique + centrale + potentiel zonal) à ~1e-8 près sur une journée et perturbe l'orbite J2 seul d'une faible quantité non nulle. Cela réalise l'étape 2 (« harmoniques zonaux J2–J6 ») de l'étape clé du propagateur numérique ; le champ tesséral EGM de haut degré, la traînée, la SRP, le troisième corps et la validation croisée externe avec GMAT/Orekit restent à venir.
  • Propagateur d'orbite numérique (de Cowell) (src/propagator.rs). Le premier propagateur non analytique de Kshana (le reste de la pile orbitale est du SGP4/SDP4 analytique) : il raccorde le modèle de forces à deux corps + J2 (src/forces.rs) au pilote RK4 adaptatif à doublement de pas (src/integrator.rs) sous la forme f(t,[r;v]) = [v; a(r)], avec un commutateur ForceModel. Validé par rapport à une vérité analytique plus exigeante qu'un recoupement numérique ne le serait : l'orbite non perturbée reproduit la solution exacte de Kepler en variables universelles à moins d'un mètre sur une orbite LEO de 24 heures (une barrière plus stricte que le « par rapport à une référence numérique < 10 m » qu'énonce l'étape clé), l'énergie spécifique et le moment cinétique se conservent à ~1e-9 relatif, et la régression nodale de J2 reproduit la j2_secular_rates en forme close à la théorie du premier ordre (à 2 % près, le résidu en O(J2²)). Ajoute aussi solve_kepler_checked, un solveur de Newton de l'équation de Kepler qui renvoie Err au lieu d'une réponse silencieusement fausse lorsqu'il ne converge pas dans un budget d'itérations borné (le cas e = 0.999 proche du périgée). Portée honnête : le modèle de forces est uniquement à deux corps + J2 — le champ tesséral EGM de haut degré (200×200 + chargeur), la traînée (NRLMSISE-00), la SRP, les forces de troisième corps et une validation croisée externe avec GMAT/Orekit restent à venir.
  • Appariement de cartes de gravité de 60 minutes sans GPS à < 500 m (run_gps_denied_gravity_nav). Approfondit la couche de PNT alternatif jusqu'à la cible de validation Quantum Wayfarer d'ESA NAVISP : un véhicule parcourt une trace d'environ 700 km pendant une coupure GNSS d'une heure complète — sa solution inertielle dérivant jusqu'à ≈ 70 km — et un gravimètre à atomes froids associé à un apparieur particulaire/en grille hiérarchique de grossier à fin retrouve la dérive constante de l'INS à ≈ 145 m (< 500 m), soit une réduction de > 480×. Le véritable plancher de bruit blanc du gravimètre est injecté sous la forme d'une séquence déterministe à graine fixée, de sorte que l'apparieur ne reçoit jamais une vérité sans bruit tout en gardant une exécution exactement reproductible (vérifiée identique bit pour bit, et stable à quelques mètres près d'une réalisation de bruit à l'autre). Un test de niveau régression montre que l'affinement est nécessaire — une seule grille grossière cale à ~2 km, et seul l'affinement en trois étapes franchit la barrière des 500 m. Nouveau scénario versionné scenarios/gps-denied-gravity-nav.toml. La ligne docs/CAPABILITY.md reste honnêtement partielle (toujours aucune carte EGM2008 fournie) avec ses preuves mises à jour avec le résultat de 60 min < 500 m. Portée honnête inchangée : champ en harmoniques sphériques de bas degré + masconcentrations synthétiques ; un Monte-Carlo sur des réalisations d'erreur de représentation de la carte reste à venir.
  • Registre des affirmations excessives + garde contre les régressions (docs/CLAIMS-VS-REALITY.md, tests/no_overclaims.rs). Clôt la piste d'honnêteté et de retrait des affirmations : les quatorze affirmations excessives qu'un audit antérieur avait recensées (OC-0…OC-13) sont désormais toutes GREEN — les affirmations fortes (filtre de Kalman couplé horloge+position OC-0, brouillage J/S→C/N₀→perte d'accrochage OC-2, physique du CAI de Mach–Zehnder OC-7, HPL/VPL ARAIM OC-8) sont remplacées par des capacités livrées et testées plutôt que par une formulation adoucie, et les lignes restantes voient leurs affirmations retirées pour correspondre au code. Un nouveau test de CI analyse les surfaces publiques en vigueur (README, CAPABILITY, GLOSSARY, web/) et échoue si une expression d'affirmation excessive brute retirée réapparaît sans réserve, de sorte qu'une ligne GREEN ne peut pas régresser en silence. La figure de mérite d'« intégrité » de chaque exécution reste honnêtement étiquetée autocohérence du filtre (et non intégrité aéronautique) ; les véritables HPL/VPL ARAIM sont présentés séparément afin que les deux ne soient jamais confondus.
  • Navigation par appariement de cartes de gravité (PNT alternatif sans GPS). Le nouveau src/gravimeter.rs ajoute la couche de capacités de PNT alternatif que réclament les études d'appariement de cartes de gravité Quantum Wayfarer / QT-CCI d'ESA NAVISP : un modèle de mesure de gravimètre à atomes froids dont le plancher de bruit blanc est dérivé de l'ASD de l'accéléromètre CAI (σ = ASD/√τ) ; un champ d'anomalie de gravité en harmoniques sphériques de bas degré, entièrement normalisé (validé par rapport aux fonctions de Legendre en forme close P̄₁₁=√3·cosφ, P̄₂₀=(√5/2)(3sin²φ−1), P̄₂₂=(√15/2)cos²φ et à une anomalie à un seul terme de 1,897 mGal dérivée à la main) plus des masconcentrations synthétiques pour les structures locales de haut degré ; et un filtre particulaire d'appariement de cartes de gravité (qui compose mapmatch + particle_filter) qui retrouve une trace privée de GPS à partir de la séquence d'anomalies qu'elle traverse. Un banc d'essai NAVISP versionné (scenarios/gravity-map-nav.toml) ramène une dérive inertielle libre d'environ 73 km à quelques km. Portée honnête : Kshana ne fournit pas le jeu complet de coefficients EGM2008 de 2190° — le champ est de bas degré + masconcentrations, et non une véritable carte à haute résolution ; le chargeur EGM/EIGEN, la carte magnétique, le SLAM assisté par relief et le raccordement de kind= au moteur de scénarios avec un graphique SVG de dérive restent à venir. docs/CAPABILITY.md « Navigation par carte de gravité / PNT alternatif » → partiel.
  • Modélisation des manœuvres et tête de pont de la conception de trajectoire. Le nouveau src/maneuver.rs ajoute la première couche de conception de trajectoire au-dessus de SGP4 : des nœuds de ΔV impulsionnels qui appliquent une discontinuité de vitesse et reportent une covariance 6×6 (poussée déterministe ⇒ transition d'état identité ; la covariance d'erreur d'exécution est tournée du référentiel de la poussée — ECI ou LVLH — vers le bloc de vitesse), une intégration de poussée finie (poussée constante sur un arc de poussée avec la masse comme état) dont le ΔV obtenu est vérifié par rapport à l'équation de fusée de Tsiolkovski en forme close à mieux que 0,01 %, un solveur de Lambert d'Izzo-2015 à une seule révolution (r1, r2, temps de vol ⇒ v1, v2), un propagateur de Kepler exact en variables universelles (vérité à deux corps) et un balayage porkchop qui met en correspondance une grille époque de lancement × époque d'arrivée avec le C3 de départ et le V∞ d'arrivée, émis sous forme de tableau JSON 2-D pour un rendu de contours dans le navigateur. La validation est autonome et plus exigeante qu'une simple lecture de tutoriel : chaque sortie de Lambert est renvoyée en aller-retour dans le propagateur de Kepler (elle doit retomber sur r2), et le minimum du porkchop est vérifié par rapport au plancher analytique de C3 d'un transfert de Hohmann entre deux orbites circulaires coplanaires. Kshana positionne ceci comme la couche de simulation de performance au-dessus de GMAT/Orekit, et non comme un remplacement (les branches à plusieurs révolutions et une véritable éphéméride planétaire restent hors périmètre). Dix tests.
  • UKF GNSS/INS à couplage serré à 17 états complet avec navigation à l'estime par CAI quantique. Le nouveau src/fusion/tightly_coupled17.rs porte l'état complet de navigation inertielle qu'estime un filtre à couplage serré — [position, velocity, attitude-error, accelerometer bias, gyro bias, clock bias, clock drift] (17 états) — propagé à travers la mécanisation en repère lié (strapdown) pilotée par la force spécifique et la vitesse angulaire mesurées, avec la rotation corps→inertiel aux petits angles C ≈ I + [ψ×] afin que l'erreur d'attitude se couple à l'accélération horizontale (le couplage d'inclinaison standard de l'INS). Pendant une coupure GNSS, il navigue en marche libre sur l'IMU seule ; le bruit de processus de marche aléatoire de vitesse est le q_va dérivé de l'accéléromètre à interféromètre à atomes froids (crate::inertial::quantum_imu), de sorte que la dérive à l'estime est celle qui est limitée par le capteur quantique — une coupure de 120 secondes reste bornée à quelques centaines de mètres, contre les kilomètres qu'atteindrait un INS libre de qualité navigation. La mise à jour pseudodistance/vitesse radiale passe par le filtre non parfumé partagé (avec α = 1 pour des poids bien conditionnés à cette taille d'état). Cinq tests : identité du modèle de mesure, intégration à vitesse constante avec IMU parfaite, assistance GNSS, estimation du biais d'accéléromètre et banc d'essai de coupure de 120 s limitée par le CAI.

0.11.0 - 2026-06-05#

Modifié#

  • Formulation honnête du positionnement quantique. Le descripteur principal est désormais un « simulateur de résilience PNT avec modèles de performance de capteurs quantiques », de façon cohérente dans l'accroche du README, la ligne de citation, CITATION.cff (titre + résumé) et l'illustration de la bannière — en remplacement de la formulation marketing plus vague « simulateur PNT hybride quantique/classique ». La section Ce que c'est / ce que ce n'est pas du README gagne un énoncé de portée explicite « Ce n'est pas (encore) » (pas un moteur de physique d'interférométrie atomique issu des premiers principes, pas un récepteur GNSS/solveur PVT, pas un outil de conception de mission), et un nouveau ROADMAP.md de premier niveau fait de la couche de physique quantique un élément P2 (phase CAI de Mach–Zehnder, bruit de projection, tenseur de vibration) afin que les lecteurs sachent que la physique issue des premiers principes est prévue et à venir, et non abandonnée. Aucun changement de comportement ni d'API.

Ajouté#

  • Étude de compromis de conception de constellation : balayage de conception Walker avec front de Pareto, JSON des temps de revisite et validation sub-kilométrique de la formule de Walker. src/walker.rs gagne walker_design_sweep, qui exécute une grille planes × sats_per_plane (par exemple un compromis 3×3) à inclinaison fixe et tabule, pour chaque conception, la fraction de couverture, le PDOP du pire cas et l'écart de revisite maximal/moyen ; pareto_front signale les conceptions non dominées (moins de satellites, plus de couverture, PDOP plus faible, revisite plus courte), et WalkerDesignReport::to_json sérialise les cellules et le front de Pareto — champs de temps de revisite inclus — en JSON. Une nouvelle validation aligne le générateur sur la formule de Walker i:T/P/F : les satellites de même emplacement dans des plans adjacents se révèlent se correspondre par une rotation R_z(2π/P) exacte à moins de 1 km sur 24 h complètes de propagation SGP4 (la respiration à courte période de J2 est de mode commun et s'annule), et les emplacements dans le plan sont confirmés espacés de 2π/S en moyenne. S'appuie sur l'instantané Celestrak réel gps-ops du 2021-07-28 versionné (scenarios/orbit-sgp4-gps.toml, exercé par les tests de couverture de scénarios et d'aller-retour SP3).
  • Transfert avancé de temps et de fréquence : TWSTFT, vue commune GNSS, PPP, optique, ajustement en loi de puissance IEEE-1139 et ensemble d'horloges. Le nouveau src/timetransfer_adv.rs construit les méthodes de transfert opérationnelles sur les formes closes de Sagnac/vue commune livrées et sur les outils de stabilité d'Allan. twstft_sagnac donne la correction de Sagnac du transfert de temps et de fréquence par satellite bidirectionnel (TWSTFT) comme la somme de la boucle à trois sauts, exactement égale à la forme close du BIPM Δt = 2·A·ω_E/c² (recoupée par le twstft_sagnac_bipm indépendant) ; run_twstft émet une série T_A − T_B d'un jour et son TDEV. gnss_common_view_series prend la différence simple de deux stations au sol synthétiques de sorte que l'horloge du satellite s'annule. iono_free_combination + ppp_receiver_clock sont la combinaison sans ionosphère du PPP et la résolution de l'horloge du récepteur par rapport à une vérité (synthétique) de qualité SP3, qui annule exactement l'ionosphère du premier ordre. rytov_variance, fried_parameter et le modèle lognormal_fading à moyenne unitaire décrivent la scintillation due à la turbulence d'une liaison optique en espace libre. fit_power_law_psd est un ajustement complet par moindres carrés à cinq coefficients h_α selon l'IEEE-1139 de la courbe de variance d'Allan (les cinq processus de bruit canoniques à la fois), le processus dominant étant indiqué par décade de τ. ensemble_timescale forme une échelle de temps papier pondérée par l'inverse de la variance, dont l'écart-type d'Allan tombe strictement sous celui de la meilleure horloge contributrice. 31 tests unitaires ; les cibles de validation sont des formes closes et une vérité synthétique — l'ingestion d'une véritable Circular-T du BIPM / d'un SP3 de l'IGS reste à faire.
  • Cartes d'ionosphère IONEX : analyseur de fichier, interpolation temporelle et correspondance d'obliquité oblique. src/ionex.rs gagne parse_ionex, qui lit le format de fichier IONEX (définition de la grille d'en-tête + blocs START/END OF TEC MAP) pour en faire une séquence de IonexMap — en normalisant l'ordre des latitudes du fichier, du nord au sud, en une TecGrid à pas positif et en mettant les valeurs à l'échelle par 10^EXPONENT. interpolate_tec_in_time mélange deux cartes successives à une époque demandée, et obliquity_factor / slant_tec projettent le TEC vertical sur un rayon oblique par le facteur de coque mince à couche unique M(z) = 1/cos z′ (sin z′ = (Rₑ/(Rₑ+H))·sin z). Avec le modèle de grille livré, cela transforme une carte mondiale d'ionosphère mesurée de l'IGS en un retard oblique utilisable.
  • Conception de constellation : dimensionnement en rues de couverture + comparaison de multiconstellations. src/walker.rs gagne min_satellites_streets_of_coverage, un solveur idéalisé du nombre minimal de satellites en rues de couverture — à partir du demi-angle de couverture λ livré et de la demi-largeur de rue c, il dimensionne la constellation quasi polaire pour une couverture mondiale simple continue à p = ⌈π/(2c)⌉ plans (par exemple, un plan de 4 satellites à l'altitude du GPS nécessite 2 plans, soit 8 satellites), et renvoie None lorsque les satellites sont trop épars pour former une rue continue. compare_constellations est l'outil de comparaison de multiconstellations : il évalue chaque conception de Walker nommée sur la même station/fenêtre via pdop_sweep et renvoie côte à côte leur couverture / PDOP / taille. Portée honnête : la correction exacte de Rider à la couture, à la frontière entre plans à rotation inverse, et un globe de couverture 3D restent à venir.
  • Détection de leurrage multicouche : détecteur de parité de cohérence RAIM + fusion des couches. src/spoof_monitors.rs gagne la troisième et dernière couche de détection ainsi que l'étape de fusion : parity_raim_test ajuste par moindres carrés la solution de position/horloge à un jeu redondant de pseudodistances et compare la somme des carrés des résidus pondérés restante à son seuil du χ² à (m−4) degrés de liberté — en signalant un sous-ensemble biaisé de satellites tout en laissant correctement un biais de mode commun (absorbé par l'horloge du récepteur) invisible au RAIM, sans le masquer. fuse_spoof_layers combine les couches de parité, d'AGC et de SQM en une seule décision pondérée qui consigne les couches qui se sont déclenchées. Un Monte-Carlo caractérise le détecteur : P_fa ≈ 0,068 empirique face à un point de conception de 0,05, avec une non-détection qui passe de 0,885 pour un biais de leurrage de 2σ à 0,16 à 8σ. Portée honnête : la validation croisée avec des vecteurs de test de leurrage publiés spécifiques (Spirent / ION GNSS+) exige ces jeux de données externes et reste à venir.
  • Ensemble de validation de Kalman couplé contre découplé. Un Monte-Carlo de 100 essais dans src/fusion/coupled.rs quantifie la valeur du maintien de la covariance croisée position↔horloge : une référence de base découplée fidèle, intégrée (validée bit pour bit par rapport au CoupledPntFilter livré), traite les mêmes données avec les blocs croisés mis à zéro, et après des pseudodistances quasi dégénérées plus une correction d'horloge seule, le filtre couplé retrouve la position à 2,97 m RMS contre 48,8 m pour le filtre découplé, en gagnant 97 essais sur 100 — la correction d'horloge n'affine la position que par la corrélation que le paquet découplé écarte. Cela achève la suite de validation de l'exactitude de Kalman (forme de Joseph, sûreté de semi-définition positive, cohérence NEES/NIS, et maintenant l'ensemble du filtre couplé).
  • Chaîne de détermination d'orbite (par lots + séquentielle). Le nouveau src/orbit_determination.rs retrouve l'état orbital [r, v] d'un satellite à partir du suivi en distance par une station au sol, en composant trois éléments livrés : le modèle de forces à deux corps + J2 (src/forces.rs) et l'intégrateur RK4 (src/integrator.rs) propagent un état candidat sur l'arc, un modèle de mesure de distance prédit la distance de chaque station, et le correcteur par lots de Gauss–Newton (src/batch_ls.rs) amène le candidat sur l'état d'ajustement optimal (determine_orbit_batch). La même dynamique et le même modèle de distance pilotent aussi une détermination récursive séquentielle sur le filtre non parfumé livré (determine_orbit_sequential). Quatre tests la valident : la prédiction de distance sur l'arc ; la récupération par lots à moins d'un mètre / mm·s⁻¹ à partir de distances sans bruit ; la récupération par lots à ~2 m avec un résidu après ajustement au plancher de bruit de 5 m (la signature d'un ajustement par moindres carrés cohérent) ; et la récupération séquentielle à quelques dizaines de mètres près. Portée honnête : les mesures de vitesse radiale/Doppler et d'angle, une matrice de transition d'état analytique de J2 et le masquage de visibilité des stations restent à venir.
  • Navigateur UKF GNSS/INS à couplage serré. Le nouveau src/fusion/tightly_coupled.rs raccorde le noyau de Kalman non parfumé livré (src/fusion/ukf.rs) à un navigateur à couplage serré fonctionnel sur le [px,py,pz,vx,vy,vz,b,d] à huit états (position/vitesse ECEF plus biais et dérive de l'horloge du récepteur en unités de distance). Il ingère les mesures brutes des satellites — pseudorange (ρ = |p − sᵢ| + b) et range_rate/Doppler (ρ̇ = (p − sᵢ)·(v − ṡᵢ)/|p − sᵢ| + d) — plutôt qu'une position déjà calculée, de sorte que TightlyCoupled (avec propagate/propagate_orbital/ update_gnss) continue de corriger avec moins de quatre satellites et navigue en marche libre pendant les coupures GNSS sur sa dynamique propagée. Cinq tests le valident de bout en bout, y compris les scénarios d'acceptation de l'étape clé : la géométrie pseudodistance/Doppler par rapport à des valeurs calculées à la main ; la convergence sans bruit à un niveau sub-métrique avec cinq satellites ; un cas à trois satellites qui converge de ~212 m à ~13 m là où une position instantanée PVT ne peut même pas être formée ; une coupure de 120 secondes à vitesse constante à moins de 50 m ; et — l'acceptation principale — un passage LEO courbe de 30 minutes (véritable orbite à deux corps + J2) avec une coupure GNSS de 120 secondes, tenu à 0,77 m RMS sur le passage et 2,9 m dans le pire des cas pendant la coupure. Cette navigation orbitale en marche libre compose le modèle de forces de gravité livré (src/forces.rs) et l'intégrateur RK4 (src/integrator.rs) dans le modèle de processus de l'UKF (propagate_orbital), de sorte que le filtre suit la courbure de l'orbite — ce qu'une marche libre à vitesse constante ne peut pas faire (la courbure seule représente ~58 km sur 120 s en LEO). Portée honnête : la navigation orbitale en marche libre utilise le modèle de forces à deux corps + J2 plutôt que la force spécifique brute de l'IMU (pour une plateforme orbitale non propulsée, les deux coïncident) ; l'intégration d'un état d'erreur d'IMU en repère lié et de corrections iono/tropo dans la boucle restent à venir.
  • Modèle de mesure d'appariement de cartes (navigation référencée au relief / à la gravité). Le nouveau src/mapmatch.rs fournit le modèle de mesure qui transforme le filtre particulaire à échantillonnage d'importance séquentiel livré (src/particle_filter.rs) en un navigateur fonctionnel sans GPS : field_likelihood (une vraisemblance gaussienne d'appariement de champ) et map_match_likelihood, qui échantillonne n'importe quel champ de référence géoréférencé — élévation du relief (TRN) ou anomalie de gravité — à la position d'une particule et la pondère selon son accord avec la valeur mesurée du véhicule. Le champ est n'importe quel échantillonneur Fn(lat, lon) -> value, de sorte qu'il se compose avec la grille bilinéaire de src/ionex.rs ou une fermeture. Deux tests l'ancrent — la vraisemblance culmine (=1) pour un appariement parfait et tombe à e^(−½) à un sigma, et un filtre particulaire sur une zone de relief synthétique distinctive retrouve la position vraie à 0,1 près. Portée honnête : les véritables cartes de référence (élévation SRTM, anomalie de gravité EGM/EIGEN) et leurs chargeurs restent à venir.
  • Intégrité du PNT cislunaire (ARAIM lunaire). Le nouveau src/lunar.rs applique le moteur ARAIM MHSS côté Terre à un service de navigation lunaire de type LunaNet avec les paramètres lunaires (σ_URE ≈ 30 m contre 0,6 m pour le GPS, P_sat ≈ 1e-4) : constantes lunaires, base Est/Nord/Haut sélénocentrique et assistant de géométrie du ciel, et lunar_araim (HPL/VPL). Trois tests l'ancrent — la base sélénocentrique orthonormée, la géométrie de distance oblique et la mise à l'échelle linéaire exacte du niveau de protection avec σ_URE (le σ lunaire de 30 m donne un niveau de protection 50× plus grand que la même géométrie avec le σ du GPS de 0,6 m — la raison quantitative pour laquelle l'intégrité du PNT lunaire est difficile). Portée honnête : l'éphéméride précise de la NRHO de LANS, le budget d'erreur du signal dans l'espace et la réduction de référentiel MCI↔MCMF restent à venir.
  • Dates juliennes en deux parties (haute précision). Le nouveau src/jd2.rs ajoute Jd2, une date julienne scindée en un day entier et un frac fractionnaire dans [0,1) (la convention de SOFA/hifitime), avec new/from_parts/add_seconds/diff_seconds/total. Les différences entre époques voisines restent exactes jusqu'au plancher de f64 là où une date julienne en un seul f64 perd ~50 µs près de J2000. Quatre tests l'ancrent : l'aller-retour, la normalisation de la fraction, la récupération exacte à la microseconde (l'échec du f64 unique étant démontré à côté), et l'arithmétique additive/réversible des secondes.
  • Rédacteur CCSDS OMM (Orbit Mean-Elements Message). Le nouveau src/omm.rs complète le rédacteur d'éphéméride oem par le message d'éléments moyens : OmmFile::from_tle met en correspondance les éléments moyens SGP4/TLE avec les unités OMM (moyen mouvement en tours/jour, angles en degrés, plus BSTAR), et to_omm_kvn sérialise la forme KVN CCSDS 502.0-B-2 de la voie des normes — de sorte qu'une orbite de Kshana peut être consommée par n'importe quel outil compatible OMM plutôt que sous la forme d'un TLE sur mesure. Deux tests ancrent la conversion d'unités TLE→OMM (≈ 15,5 tours/jour, inclinaison de 51,6°, etc.) et la présence des mots-clés KVN requis. Portée honnête : la forme KVN et la correspondance avec le TLE sont livrées ici ; le rendu XML (ndm/omm) et un aller-retour avec un analyseur de référence restent à venir.
  • Filtre particulaire à rééchantillonnage d'importance séquentiel. Le nouveau src/particle_filter.rs ajoute l'estimateur non linéaire et non gaussien qui sous-tend la navigation sans GPS assistée par carte (appariement de relief ou de cartes de gravité) : predict (propager les particules à travers la dynamique + un bruit de processus gaussien), update (repondérer par une vraisemblance de mesure par particule), resample systématique, le moniteur de dégénérescence effective_sample_size et l'estimation par moyenne pondérée. Six tests ancrent exactement le noyau déterministe — l'ESS couvrant 1…N, le rééchantillonnage systématique qui choisit des indices proportionnellement au poids, la combinaison convexe de la moyenne pondérée, une vraisemblance gaussienne qui tire l'estimation vers la mesure, le comportement de rééchantillonnage vers l'uniforme et le déterminisme de la prédiction à graine fixée. Portée honnête : le moteur est livré ici ; les cartes de référence (élévation SRTM, anomalie de gravité EGM) et le modèle de mesure de carte restent à venir (l'échantillonneur grille+bilinéaire de ionex servirait aussi bien pour une carte de gravité/relief).
  • Cartes d'ionosphère TEC de type IONEX. Le nouveau src/ionex.rs ajoute l'alternative d'ionosphère mesurée au modèle de Klobuchar diffusé : une TecGrid (une grille régulière lat/lon de TEC vertical, une carte mondiale d'ionosphère de l'IGS) avec interpolation bilinéaire en un point de perforation (vtec_at, bornée hors de la grille) et le retard du premier ordre Δ = 40.3·TEC/f² (vtec_to_delay_m, delay_at). Quatre tests l'ancrent : 1 TECU ≈ 0.162 m en L1 avec la mise à l'échelle en 1/f², l'interpolation exacte aux nœuds, des points milieux bilinéaires qui moyennent les coins, et des requêtes hors grille bornées au bord. Portée honnête : la grille et l'interpolation sont livrées ici ; l'analyse du format de fichier IONEX, l'interpolation temporelle entre cartes et la fonction de projection oblique restent à venir.
  • Corrections géométriques du transfert de temps (Sagnac + vue commune GNSS). Le nouveau src/timegeo.rs ajoute les deux effets déterministes dont une véritable comparaison d'horloges doit tenir compte, en complément du modèle stochastique bidirectionnel de timetransfer : sagnac_correction (Δt = (ω_E/c²)·(x₁y₂ − x₂y₁), le retard dû à la rotation de la Terre — des dizaines de ns pour des lignes de base continentales) et common_view_offset, la différence simple en vue commune GNSS qui annule exactement l'erreur d'horloge du satellite et retrouve le décalage entre stations. Trois tests les ancrent sur des références exactes : le Sagnac d'environ 33 ns d'un quart de tour équatorial, l'antisymétrie et les cas radial/polaire nuls, et l'annulation exacte de l'horloge du satellite. Portée honnête : un budget complet de transpondeur/de retard matériel TWSTFT et une solution de transfert de temps PPP sans ionosphère restent à venir.
  • Modèle de forces orbitales (deux corps + J2). Le nouveau src/forces.rs ajoute le modèle d'accélération qu'intègre un propagateur numérique : two_body_accel (−μ·r/|r|³), la perturbation d'aplatissement j2_accel (la forme close en ECI) et gravity_accel qui les additionne — à associer à src/integrator.rs sous la forme f(t,[r;v]) = [v; a(r)]. Il expose aussi les taux séculaires analytiques de J2 (j2_secular_rates) : la régression nodale Ω̇, la rotation des apsides ω̇ et la dérive d'anomalie moyenne Ṁ. Six tests ancrent la physique sur des références exactes : μ/r² pour le terme à deux corps, la forme close de J2 à l'équateur (~10⁻³ de la magnitude à deux corps), l'inclinaison critique (63,4349°) qui fige le périgée (ω̇ = 0), la régression nodale de l'ISS (Ω̇ ≈ −5°/day) et la dérive vers l'est d'une orbite héliosynchrone rétrograde. Portée honnête : uniquement deux corps + J2 ; J3–J6, la traînée, la SRP et le troisième corps restent à venir.
  • Liens permanents de scénarios partageables. Le nouveau src/permalink.rs ajoute un codec Base64 RFC 4648 sans dépendance (alphabet standard +/ avec remplissage, et alphabet -_ sûr pour les URL, sans remplissage) et des enveloppes encode_scenario / decode_scenario, de sorte qu'un TOML du bac à sable peut être encodé dans un paramètre de requête ?s= et partagé sous forme d'URL. Exposé au navigateur sous la forme de liaisons wasm encode_permalink / decode_permalink. Quatre tests l'ancrent sur les vecteurs canoniques de la RFC 4648 ("foobar" → "Zm9vYmFy", etc.), un aller-retour de scénario sûr pour les URL (aucun +///= à échapper), le rejet de symboles invalides et un aller-retour sur les 256 octets. Portée honnête : le codec et les liaisons sont livrés ici ; l'interface du bouton Partager du bac à sable, le graphique multi-séries Plotly/D3 et le mode de comparaison A/B restent à venir.
  • Moindres carrés par lots de Gauss–Newton (le correcteur différentiel par lots). Le nouveau src/batch_ls.rs ajoute le noyau d'estimation sur lequel repose une détermination d'orbite par lots (ou tout ajustement de paramètres) : gauss_newton linéarise un modèle h(x) fourni par l'utilisateur avec une jacobienne par différences finies centrées, forme et résout les équations normales pondérées (HᵀWH)·Δx = HᵀW·(z − h(x)) (en réutilisant l'inverse de matrice testé) et itère jusqu'à la convergence avec des poids par mesure. Quatre tests l'ancrent : un ajustement de droite linéaire qui atteint la solution exacte des moindres carrés pondérés, un ajustement non linéaire a·exp(b·t) qui retrouve les vrais paramètres, une multilatération de distances en 3D qui retrouve une position connue à partir de distances sans bruit (la variante détermination d'orbite) et le rejet d'entrées sous-déterminées ou incohérentes. Portée honnête : c'est le moteur de correcteur générique ; le modèle de mesure de distance/vitesse radiale/azimut-élévation propre à l'orbite, la matrice de transition d'état analytique de J2 et la validation sur des cas publiés restent à venir.
  • Moniteurs de leurrage de la couche RF (puissance AGC et SQM). Le nouveau src/spoof_monitors.rs ajoute deux détecteurs de leurrage indépendants en entrée de récepteur, qui complètent le moniteur de leurrage temporel assisté par l'horloge de spoof : un moniteur de puissance AGC (somme de puissances incohérente combine_power_dbm + AgcMonitor) qui signale la puissance reçue en excès qu'ajoute un émetteur de leurrage au-delà d'une marge en dB configurable, et un moniteur de qualité du signal (autocorrélation triangulaire du code bpsk_autocorr + SqmMonitor) qui signale le déséquilibre de corrélateur Early moins Late qu'introduisent les trajets multiples, le meaconing et le rejeu. Quatre tests ancrent les formes closes exactes (3,01 dB pour un doublement de la puissance, l'agrégat 10·log10(N), le R(τ)=1−|τ| triangulaire et le seuil d'alerte Early/Late de 10 %). Portée honnête : le détecteur de leurrage par parité de cohérence RAIM complet, la fusion multicouche des sorties des moniteurs et la validation par rapport aux vecteurs de leurrage publiés Spirent/ION GNSS+ restent à venir.
  • Intégrateur adaptatif d'EDO numérique. Le nouveau src/integrator.rs ajoute la première pièce d'un propagateur numérique (la propagation d'orbite de Kshana étant par ailleurs du SGP4/SDP4 analytique) : un pas de Runge–Kutta générique d'ordre quatre (rk4_step) sur tout système du premier ordre y' = f(t, y), et un pilote adaptatif (integrate) qui contrôle l'erreur locale par doublement de pas (extrapolation de Richardson) avec le contrôleur de pas standard 0.9·(tol/err)^(1/5) et la logique d'acceptation/rejet. Six tests l'ancrent sur des solutions exactes : l'exponentielle y' = y → e à < 1e-9 près, la réduction d'erreur d'environ 16× à chaque pas divisé par deux, qui prouve la convergence d'ordre quatre, la conservation de l'énergie et du retour de l'oscillateur harmonique sur une période complète, et le pilote adaptatif qui respecte une tolérance serrée avec des pas variables. Portée honnête : c'est le noyau de l'intégrateur et son contrôle d'erreur ; les tableaux emboîtés de Dormand–Prince RK5(4)/RKF7(8) et le modèle de forces orbitales hiérarchique (deux corps + J2–J6 + traînée + SRP + troisième corps) qui en font un NumericalPropagator restent à venir.
  • Filtre de Kalman non parfumé (à points sigma). Le nouveau src/fusion/ukf.rs ajoute le filtre de Kalman non parfumé à échelle (Julier et Uhlmann ; Wan et van der Merwe) comme estimateur général à n états sur des fonctions de processus et de mesure fournies par l'utilisateur — l'estimateur à points sigma qu'utilise un navigateur GNSS/INS à couplage serré lorsque le modèle de pseudodistance/Doppler est fortement non linéaire et que la jacobienne d'un EKF se dégrade. Il comprend l'algèbre linéaire dense de soutien (facteur de Cholesky pour l'étalement des points sigma, inverse de Gauss–Jordan pour la covariance d'innovation) et une mise à jour P⁺ = P⁻ − K S Kᵀ sans forme de Joseph. Six tests le verrouillent, les principaux exploitant la propriété exacte selon laquelle, pour un modèle linéaire, la transformation non parfumée reproduit le filtre de Kalman à la précision numérique (prédiction, mise à jour et cycle complet prédiction+mise à jour tous comparés à un KF linéaire exécuté à la main, plus une vérification analytique bayésienne a posteriori en 1-D et les identités de Cholesky/de l'inverse). Portée honnête : c'est le moteur d'estimation ; le navigateur GNSS/INS à couplage serré à 17 états, le modèle de mesure de pseudodistance/Doppler et le scénario de validation de coupure restent à venir.
  • Niveaux de protection ARAIM bi-constellation. Le nouveau araim_dual_raim étend le RAIM avancé à panne unique (araim_raim) avec le mode de panne à l'échelle de la constellation de l'ARAIM de l'UE / DO-316 : à côté des hypothèses sans panne et par satellite, chaque constellation (étiquetée par satellite) apporte une hypothèse qui retire d'un coup tous ses satellites, avec l'a priori P_const (un nouveau DualFaultPriors { p_sat, p_const }). Chaque hypothèse ajoute un terme à la même somme d'intégrité MHSS, de sorte que VPL/HPL sont les plus petites bornes dont le P_HMI total respecte le budget sur les pannes sans défaut + un seul SV + par constellation (la répartition de fausse alerte de Bonferroni porte sur les N + C hypothèses). Avec P_const = 0, le résultat est identique bit pour bit à araim_raim ; un utilisateur mono-constellation obtient None face à la panne de sa propre constellation (elle ne peut pas être exclue) — c'est exactement pourquoi la couverture bi-constellation importe. Quatre tests couvrent l'équivalence, l'élargissement du niveau de protection, l'indisponibilité mono-constellation et la validation des entrées, en réutilisant le mécanisme existant de sous-solutions à séparation de solutions.
  • Précession IAU 2006 (angles de Fukushima–Williams et matrice de biais-précession). Le nouveau src/precession.rs implémente la précession IAU 2006 (P03 ; Capitaine, Wallace et Chapront 2003) : les quatre angles de Fukushima–Williams (γ̄, φ̄, ψ̄, ε̄_A) sous forme de polynômes en siècles juliens TT (fw_angles), et la matrice de rotation de biais-précession GCRS→moyen à la date construite à partir d'eux par la construction iauFw2m de SOFA (precession_matrix, avec les assistants gcrs_to_mod / mod_to_gcrs). C'est la première pièce de référentiel inertiel au-dessus de la réduction frames existante fondée sur GMST. Huit tests valident par rapport à des ancrages en forme close — l'obliquité moyenne J2000 ε̄ = 84381.406″ = 23.4392794°, les termes constants des angles publiés, l'accumulation de précession générale ψ̄ ≈ 5039.998″ sur un siècle, l'orthonormalité de la matrice et det = +1, la valeur quasi identité (biais de référentiel seul) à J2000, et l'angle de rotation nette ≈ 1.40°/siècle. Portée honnête (ROADMAP.md) : précession seulement — la nutation IAU 2000A à 678 termes, la chaîne complète TEME→GCRS et un recoupement numérique SOFA/ANISE à µas/<10 m restent à venir.
  • Physique de l'accéléromètre à interféromètre à atomes froids (CAI) issue des premiers principes. src/inertial/quantum_imu.rs modélise à partir des premiers principes un interféromètre atomique de Mach–Zehnder à trois impulsions plutôt qu'à partir d'une fiche technique : vecteur d'onde effectif k_eff = 4π/λ, phase de l'interféromètre Φ = k_eff·a·T², bruit de projection quantique (de grenaille) σ_Φ = 1/(C·√N), sensibilité en accélération par tir, décroissance du contraste C(t) = C₀·e^(−t/τ) et — c'est l'essentiel — CaiAccelerometer::q_va(), qui dérive la DSP d'accélération blanche déjà consommée par le AccelModel classique à partir du nombre d'atomes, du temps d'interrogation et du contraste. Le modèle couvre désormais aussi le couplage des vibrations — le terme dominant des dispositifs réels : la fonction de transfert accélération→phase de l'interféromètre |H(ω)| = (4/ω²)sin²(ωT/2) (accel_transfer_function), la variance de phase à DSP blanche σ_Φ² = k_eff²·S_a·T³/3 (vibration_phase_variance_white, avec un recoupement numérique par intégrale de bande vibration_phase_variance_band), la projection beam_axis_projection de rang 1 le long du faisceau, et CaiAccelerometer::vibration_phase_noise / vibration_limited_accel (ce dernier se réduisant au plancher √(S_a/(3T)) indépendant de k_eff). Onze tests vérifient la physique à la main (Rb-87 k_eff ≈ 1.61×10⁷, Φ(1 g) ≈ 1.58×10⁴ rad, plancher de bruit de grenaille de σ_a ≈ 0.13 µg/tir contre un plancher de vibration d'environ 5,9 µg, les lois d'échelle en 1/T², 1/√N et T³). Portée honnête dans docs/QUANTUM.md : cela couvre le plancher de bruit de projection et le régime limité par les vibrations au-dessus ; le bruit de phase du laser, les systématiques de Coriolis et de déplacement lumineux, et les scénarios de validation PHARAO/CARIOQA restent à venir.
  • Accéléromètre à CAI quantique raccordé au scénario inertiel. Un accéléromètre dans un scénario de navigation inertielle à l'estime se résout désormais en un nouveau ImuKind — Classical (le capteur existant à coefficients de fiche technique) ou QuantumCai lorsqu'il porte un bloc [cai] facultatif (CaiCfg : longueur d'onde, séparation des impulsions, nombre d'atomes, contraste, temps de cycle et une vibration_psd de plateforme facultative). La DSP de marche aléatoire de vitesse q_va d'un capteur quantum_cai est dérivée de la physique de l'interféromètre — le plancher de bruit de grenaille plus, lorsqu'une DSP de vibration est fournie, la contribution limitée par les vibrations en quadrature — au lieu d'un coefficient fourni, et la provenance de l'exécution consigne que le bruit est issu de la physique. Le champ cai est skip_serializing_if = "Option::is_none", de sorte que les scénarios existants l'omettent et se sérialisent à l'identique octet pour octet (le hachage du scénario est inchangé). Cinq tests couvrent la dérivation, la somme quadratique des vibrations, la sélection Classical/QuantumCai, la sérialisation stable du hachage et une exécution de bout en bout pilotée par le CAI.
  • Optimiseur de conception de constellation et géométrie en rues de couverture. src/walker.rs gagne optimize_walker_design, un optimiseur par grille sans gradient qui explore l'espace de conception {planes × sats × inclination} et renvoie la meilleure conception de Walker selon un DesignObjective choisi — MinSatellitesForCoverage, MaxCoverage ou MinWorstPdop — sur le balayage PDOP déjà validé (un test confirme qu'il renvoie le gagnant par force brute). Plus les formes closes analytiques en rues de couverture coverage_half_angle_rad (λ = arccos(Re/r·cos ε) − ε) et street_half_width_rad (cos c = cos λ / cos(π/s), Rider/Beste), vérifiées à la main par rapport à la géométrie des manuels et détectant l'écart de sous-peuplement. Le solveur complet de Rider du nombre minimal de satellites pour une couverture mondiale, un globe 3D dans le bac à sable et un recoupement du DOP avec un outil externe restent à venir.
  • Export d'éphéméride précise SP3 depuis la CLI. Un scénario d'orbite/de constellation propagé peut désormais être écrit dans un fichier SP3-c : kshana <orbit.toml> --export-sp3 out.sp3, ou export_sp3 = true dans le scénario écrit automatiquement <scenario>.sp3 (api::export_sp3 / auto_export_sp3, OrbitClockScenario::to_sp3_string, epoch facultatif). Un test d'aller-retour (tests/sp3_export_roundtrip.rs) propage l'instantané Celestrak réel gps-ops, l'exporte, le réanalyse et confirme que les positions ECEF retrouvées concordent avec la vérité SGP4 sur 24 h à < 0,5 m (bien dans la tolérance de 10 m de qualité TLE). Le README documente le rôle d'interopérabilité (RINEX → RTKLIB/gLAB, SP3 → Ginan/produits d'orbite précise).
  • Filtre de Kalman couplé horloge+position (covariance inter-blocs). src/fusion/coupled.rs CoupledPntFilter est un unique filtre [pos, vel, phase, freq] empilé (mises à jour sous forme de Joseph) dont la mesure de pseudodistance ρ = g·pos + c·phase + noise couple véritablement les blocs de position et d'horloge — contrairement aux deux filtres à deux états indépendants du paquet de fusion historique, qui maintiennent la covariance inter-blocs exactement nulle. Validé : une pseudodistance partagée rend P[pos,phase] non nul ; deux géométries distinctes résolvent conjointement des décalages injectés de position+horloge qu'une seule distance ne peut pas séparer ; une correction d'horloge seule affine la position grâce à la covariance croisée (le gain que des filtres découplés ne peuvent pas procurer) ; et le NEES Monte-Carlo est cohérent avec χ²(4). C'est la réalisation à 1 degré de liberté (la dimensionnalité du paquet de fusion) ; l'extension à 8 états en 3D et le raccordement au paquet exécutable sont suivis comme travaux à venir.
  • Surveillance de l'état de santé par cohérence du filtre de Kalman (NIS/NEES). La mise à jour de covariance du filtre d'horloge à deux états est désormais sous forme stabilisée de Joseph `P⁺ = (I−KH)P(I−KH)ᵀ
    • KRKᵀ, which stays positive-semidefinite under extreme Q/R ratios (Cholesky-checked in CI at R=1e-26 / Q≈1e-30). A new src/filter_health.rsruns a Monte-Carlo consistency assessment (Bar-Shalom §5.4): pooled **NIS** (normalised innovation², target 1) and **NEES** (normalised estimation error², target 2) against 95% χ² bands, surfaced as afilter_health { nis_mean, nis_chi2_lower_95, nis_chi2_upper_95, nees_mean, nees_chi2_lower_95, nees_chi2_upper_95, consistent } block in the clock result JSON and as a green/amber card in the playground. A Q/R-mismatch sweep test proves the monitor flips to inconsistent when the process noise is mistuned by ×0.1–×10. Adds a general χ² quantile (detection::chi2_inv_cdf`, Wilson–Hilferty, vérifié par table).
  • docs/PROVENANCE.md — un tableau de provenance citable unique. Regroupe chaque paramètre de capteur (horloges, inertiel, transfert de temps), chaque modèle physique/algorithmique (orbite, systèmes de temps, référentiels, iono/tropo, intégrité, détection, brouillage, Allan) et chaque jeu de données de validation (AIAA 2006-6753, Celestrak gps-ops) avec sa source publiée — fiche technique, article, ICD ou norme — et une étiquette de maturité honnête (qualifié pour le vol / laboratoire au sol / objectif spatial sur matériel au sol). Lié depuis l'introduction du README et le tableau de documentation ; complète les chaînes provenance par exécution qui voyagent déjà dans le JSON du résultat.
  • API de scénarios typée. La répartition se fait désormais sur une énumération typée ScenarioKind au lieu d'une comparaison de chaînes kind brutes (ScenarioKind::classify + répartition exhaustive), de sorte que l'ajout d'un paquet est vérifié à la compilation. De nouvelles surfaces typées s'ajoutent à run_toml, inchangée et renvoyant une chaîne : run_scenario(src) -> Result<RunOutput, KshanaError> avec une taxonomie d'erreurs structurée (InvalidInput / NonConvergence / Unsupported / IoError, chacune avec un kind_tag() stable) ; un trait Scenario et un point d'extension ExternalPack (le paquet jamming y est raccordé comme exemple concret) ; et l'introspection list_scenario_kinds() (nom, description, champs obligatoires/facultatifs par type de scénario). Les liaisons Python et WebAssembly gagnent list_kinds() et error_kind(). Documenté dans docs/ARCHITECTURE.md.
  • Constellation GPS réelle + couverture de l'enveloppe de fonctionnement. scenarios/orbit-sgp4-gps.toml fournit désormais un instantané Celestrak gps-ops réel (2021-07-28, 30 satellites) au lieu de TLE Walker synthétiques, avec strict_checksum = true de sorte qu'il ne se charge que si chaque somme de contrôle de TLE est valide ; scripts/fetch_tles.sh documente l'actualisation reproductible et le README cite la source de données ouvertes. Le nouveau tests/scenario_coverage.rs exerce chaque paquet sur ≥5 variantes d'enveloppe en vérifiant une sortie finie/bornée, confirme que le plancher de bruit de fréquence de scintillation dégrade mesurablement la marche libre d'une horloge lorsqu'il est activé (désormais défini dans trois scénarios livrés), et confirme que le filtre de fusion converge avec un biais d'accéléromètre réaliste non nul (à moins de 3× le cas à biais nul), ce qui comble l'écart de réalisme « la fusion ne fonctionne qu'avec des biais nuls ». docs/VALIDATION.md gagne un tableau d'enveloppe de fonctionnement.
  • Simulation GNSS dans le domaine des mesures (type de scénario gnss-sim). Un modèle direct au niveau de la pseudodistance : pour chaque satellite visible, il synthétise ρ = geometric range + c·δt_rx − c·δt_sv + I + T + noise + multipath et le Doppler L1, avec l'ionosphère monofréquence de Klobuchar (IS-GPS-200 §20.3.3.5.2.5) et la troposphère zénithale de Saastamoinen projetée par la fonction de projection de Niell (1996) — exposées sous forme de blocs TOML [iono] et [tropo]. Les résidus alimentent le RAIM instantané pour des HPL/VPL à chaque époque, et un tableau JSON gnss_measurements[] porte, pour chaque SV, la pseudodistance, le Doppler, le C/N₀ et les corrections iono/tropo. Une exécution sans bruit reproduit la géométrie + les corrections à un niveau sub-millimétrique (test de CI). Nouveaux src/gnss_sim.rs et scenarios/gnss-sim-raim.toml.
  • Détecteur stochastique de leurrage temporel (type de scénario spoof). Le paquet de leurrage exécute désormais un véritable détecteur au lieu d'une comparaison déterministe rampe contre borne : quatre formes d'injection (linear_ramp, step_jump, meaconing, replay), un test d'énergie / de Neyman–Pearson bilatéral en χ²₁ sur la statistique du moniteur assisté par l'horloge, avec le seuil fixé à partir d'un budget cible de fausses alarmes target_pfa, et la probabilité de non-détection P_md rapportée à la fois en forme close et par Monte-Carlo (mc_runs essais par hypothèse — les deux concordent à quelques ×1/√N près). La figure de mérite de sécurité est désormais 1 − P_md à la magnitude opérationnellement nuisible (spécification). Nouveau src/detection.rs (fonctions de queue gaussiennes, test NP/d'énergie, P_fa/P_md Monte-Carlo) et scenarios/spoof-meaconing.toml. Rétrocompatible : un simple [attack] rate_ns_per_s reste accepté comme rampe linéaire.

Modifié#

  • Définition de la figure de mérite de sécurité (type de scénario spoof) : de la borne analytique de détectabilité 1 − min_detectable/threshold au 1 − P_md du détecteur stochastique. Le champ security du paquet d'horloge reste le substitut analytique plus rapide.

Ajouts (suite)#

  • Modèle de brouillage RF (type de scénario jamming). Un modèle d'interférence par bilan de liaison qui transforme la puissance et la géométrie d'un brouilleur en perte d'accrochage par satellite : le rapport brouilleur/signal à partir de l'affaiblissement en espace libre et du gain d'antenne de réception par direction, le C/N₀ effectif par l'équation anti-brouillage standard (gain de traitement de désétalement × le facteur de séparation spectrale Q ; Kaplan et Hegarty §9,4), et un seuil de poursuite configurable, évalué sur une constellation de Walker comme figure de mérite availability_under_jamming. Nouveaux src/jamming.rs et scenarios/jamming-demo.toml. La portée honnête (ni trajets multiples, ni masquage par le relief, ni AGC, ni annulation adaptative) est documentée dans docs/CAPABILITY.md / docs/VALIDATION.md.
  • Balayage de paramètres N-D générique sur n'importe quel type de scénario (sweep-nd). Le balayage N-D précédent ne concernait que le paquet d'horloge. sweep-nd fait varier des clés TOML pointées d'un scénario [base] sur le produit cartésien de ses axes, relance chaque nœud de la grille par le chemin d'exécution normal et extrait une ou plusieurs métriques du résultat par chemin JSON pointé — il fonctionne donc pour tous les paquets (inertiel, gnss-ins, intégrité, leurrage, …) sans se coupler au type Rust de chaque paquet. Les nœuds de la grille sont évalués en parallèle sur des threads du système d'exploitation sur les cibles natives (sans dépendance ajoutée) ; wasm se rabat sur le séquentiel. Déterministe et en ordre ligne par ligne quel que soit le nombre de threads. Nouvel exemple scenarios/sweep-nd-inertial.toml.
  • Modèle d'erreur d'IMU déterministe configurable en TOML dans le paquet gnss-ins. La chaîne d'erreur à trois axes en repère lié (facteur d'échelle, désalignement, sensibilité à g, quantification, rampe de vitesse ; IEEE Std 952-1997 §A.2, Groves 2013 §4,3) est désormais accessible pour chaque capteur depuis un fichier de scénario par un bloc [imu_*.error_model] facultatif, superposé aux biais constants de mise en marche. L'omission du bloc laisse chaque capteur à l'état de source de biais constant pure, de sorte que les exécutions gnss-ins existantes sont inchangées. Cela raccorde le modèle d'erreur jusque-là réservé à la bibliothèque à un paquet exécutable et à une figure de mérite.

0.10.0 - 2026-06-04#

Modifié#

  • Validation sur données réelles. L'analyseur de navigation RINEX multi-GNSS, le propagateur RK4 GLONASS et le lecteur SP3 sont désormais exercés sur de véritables fichiers IGS/DLR (un véritable fichier de navigation diffusé mixte RINEX 3 et un produit d'orbite IGS SP3-c), et pas seulement sur des échantillons rédigés en interne — en vérifiant des ensembles de satellites non vides et des positions ECEF finies et de taille physique. Les fixtures sont réservées aux tests (exclues de la crate publiée) ; voir tests/fixtures/igs/NOTICE.
  • RAIM sur une géométrie d'orbite de référence réelle. Les noyaux de RAIM instantané, de séparation de solutions (MHSS) et de niveau de protection ARAIM sont désormais validés par rapport à la géométrie d'orbite précise IGS (SP3) réelle, et non plus seulement à des constellations synthétiques : la géométrie de visée est construite à partir de la première époque SP3 à une véritable station au sol, et les tests vérifient des niveaux de protection métriques, disponibles pour l'APV-I, qu'un biais de pseudodistance de 60 m déclenche le moniteur du χ², que la séparation de solutions identifie le satellite en panne et que les niveaux de l'ARAIM respectent le P_HMI alloué. Comble l'écart « validé uniquement sur géométrie synthétique » (la parité avec gLAB dans le domaine du récepteur sur un arc RINEX complet reste un élément de la feuille de route — elle exige une solution de pseudodistance).

Ajouté#

  • Intervalles de confiance par nœud pour le balayage de paramètres N-D (sweep::nd_sweep_ensemble). Chaque nœud de grille du balayage à produit cartésien N-dimensionnel peut désormais être évalué comme un ensemble Monte-Carlo de graines, en rapportant la moyenne de la métrique, ses percentiles et un IC bootstrap par percentiles à 95 % par nœud (pour les deux horloges) — un balayage statistiquement honnête plutôt qu'un seul tirage par nœud. Réutilise la mécanique d'ensemble/de bootstrap (metric_stat) ; déterministe ; runs = 1 se réduit exactement au nd_sweep à graine unique. (La généralisation du balayage à tous les paquets, liée à la refonte du Scénario typé, et l'exécution parallèle restent à faire.)
  • Validation croisée NaveGo de la chaîne de bruit de l'IMU (tests/navego_imu_crossval.rs). Un recoupement externe avec NaveGo (la boîte à outils INS/GNSS open source de R. Gonzalez) : il reproduit l'aller-retour synthétique de navego_example_allan.m sur son profil de référence publié du Microstrain 3DM-GX3-35, et confirme que notre estimateur d'ADEV à recouvrement retrouve les coefficients de marche aléatoire de vitesse et d'angle de NaveGo (ADEV(1 s) = σ·√dt) à moins de 5 % près, avec la pente attendue de −1/2 du bruit blanc. (Le journal STIM300 enregistré de 40 Mo au format .mat n'est pas ingéré : format binaire non pris en charge.)
  • Mise à jour GNSS/INS à couplage serré (pseudodistance). GnssInsEkf::update_tightly_coupled (et l'enveloppe ClosedLoopInsGnss::fuse_tightly_coupled) implémentent la mesure dans le domaine des distances, jusque-là réduite à une ébauche : l'innovation est la distance prédite entre la position de l'INS et chaque satellite, comparée à la pseudodistance mesurée, avec un jacobien de ligne de visée sur l'erreur de position. Comme chaque satellite constitue une mesure scalaire, le filtre continue de corriger avec moins de quatre satellites, là où une solution PVT à couplage lâche n'existe pas. Cinq tests couvrent l'annulation à quatre satellites, la correction à deux satellites (aucun PVT possible), l'observabilité le long de la ligne de visée avec un seul satellite, et la validation des entrées. Pseudodistance uniquement ; la phase de la porteuse et un état explicite d'horloge du récepteur restent sur la feuille de route. La fonctionnalité cargo tight_coupling, inutilisée (elle conditionnait l'ancienne ébauche d'erreur), est supprimée.
  • Paquet de scénarios GNSS/INS à couplage lâche (kind = "gnss-ins", src/fusion/pack.rs). Il relie le navigateur strapdown à trois axes et l'EKF à état d'erreur à 15 états (closed_loop / gnss_ins_ekf) dans un scénario exécutable doté d'une figure de mérite : l'EKF asservit la mécanisation sur des positions GNSS bruitées tant que la couverture est disponible, puis poursuit à l'inertie pendant l'interruption, en remplaçant la réinitialisation sur la vérité terrain du paquet scalaire à 1 degré de liberté d'origine par une véritable fusion. Le résultat fournit la série d'erreur horizontale fusionnée, la figure de mérite de position notée (disponibilité / RMS pendant l'interruption / holdover), et le RMS de l'INS libre en boucle ouverte à titre de comparaison ; une paire d'IMU quantique/classique ne diffère que par le biais réel. Lancé depuis le point d'entrée CLI/Python/wasm, avec un exemple scenarios/gnss-ins.toml. Cadrage honnête : couplage lâche uniquement, une seule trajectoire déterministe, et l'erreur fusionnée pendant l'interruption est limitée par un plancher dû à l'erreur d'attitude au moment du passage de relais (on ne prétend donc pas qu'elle évolue avec le biais) ; les résultats robustes sont que la fusion fait mieux que l'estime sans assistance pour un capteur biaisé, et qu'un capteur à biais plus faible offre la meilleure marche à l'inertie sans assistance.
  • Conception de constellation sur le noyau SGP4 validé (src/walker.rs). Un nouveau module walker produit un motif Walker-delta conçu (i: T/P/F) sous forme d'éléments moyens SGP4, de sorte que la constellation synthétique se propage par le même chemin SGP4 que celui validé à 4,12 mm près par rapport aux vecteurs AIAA 2006-6753, et non par le générateur képlérien analytique. Par-dessus : pdop_sweep tabule la couverture et le PDOP médian/pire sur une grille de conception {planes × sats × inclination}, et coverage_revisit fournit la fraction de couverture et les intervalles de revisite (pire/moyen) en un point au sol. Validé par les monotonies physiques qu'un compromis doit respecter (plus de satellites ⇒ couverture plus élevée, PDOP plus bas, revisite plus courte). Par ailleurs, un véritable instantané TLE Celestrak gps-ops (2021-07-28, 30 satellites GPS opérationnels) est ajouté comme jeu d'essai réservé aux tests, et le chemin géométrique TLE réel → SGP4 → ECEF est validé par rapport à lui (couche MEO complète à 1 % près, neuf satellites tous en vue avec un PDOP de 1,64), en plus des chemins de données réelles SP3 et RINEX existants.
  • Degrés de liberté effectifs propres au type de bruit pour les intervalles de confiance d'Allan. allan::edf_overlapping_adev implémente les formes closes du tableau 5 de NIST SP 1065 (l'ensemble simple de Stable32) pour les cinq types canoniques de bruit en loi de puissance (PM blanc/flicker, FM blanc/flicker, FM à marche aléatoire), en remplaçant le décompte conservateur sans recouvrement comme degrés de liberté du χ². Une nouvelle énumération PowerLawNoise et classify_power_law identifient le type dominant à partir de la pente de l'écart-type d'Allan modifié de l'enregistrement (la MDEV sépare le PM blanc du PM flicker là où l'ADEV ne le peut pas), et overlapping_adev_curve associe désormais à chaque point de la courbe d'ADEV exportée le type de bruit identifié, son edf et une bande de confiance à 95 % (AdevPoint gagne noise/edf/ci_lo/ci_hi, de façon additive avec des valeurs par défaut serde). Validé de deux façons : les cinq formules concordent avec des valeurs évaluées à la main à 1e-12 près, et un ensemble Monte-Carlo de 4 000 enregistrements de FM blanc confirme que la formule prédit l'edf du khi-deux réel de l'estimateur à 20 % près (et qu'elle fait nettement mieux que le décompte conservateur). Huit nouveaux tests.
  • Modèle stochastique du transfert de temps bidirectionnel. timetransfer::TwoWayLink remplace l'échantillonneur à bruit blanc seul par un modèle fondé sur la physique : le retard de trajet réciproque (mode commun) s'annule dans l'estimation (m_AB - m_BA)/2 (two_way_offset_estimate, de sorte que deux mesures unidirectionnelles indépendantes se moyennent en 1/sqrt(2)), et le résidu est le retard différentiel non réciproque, modélisé comme un processus coloré FM blanc + FM à marche aléatoire (l'ClockModel validé), ce qui donne à la série d'erreur de synchronisation une signature d'Allan réaliste (sigma_y^2(tau) = q_rw*tau/3) au lieu d'un bruit blanc plat. LinkCfg gagne q_wf_s/q_rw_s (valeur par défaut serde 0 ⇒ le comportement historique à bruit blanc seul, bit à bit), la figure de mérite de la liaison fournit adev_tau0 (l'écart-type d'Allan du modèle au pas de base), et le scénario et la CLI timetransfer l'exposent. Figure de mérite de référence (golden) refigée. Six tests dérivés à la main (annulation du mode commun, le gain bidirectionnel en racine de 2, la loi RWFM en tau/3 via le propre step() de la liaison, l'équivalence avec l'ancien comportement à q=0, le déterminisme, et l'exposition de bout en bout de la figure de mérite).
  • Parité numérique avec Stable32 pour les estimateurs de la famille d'Allan (NBS14). tests/allan_reference.rs valide l'ADEV à recouvrement, l'ADEV modifié, l'écart temporel et le Hadamard à recouvrement par rapport aux écarts-types de référence de Stable32 pour le jeu de données canonique NBS14 (W. J. Riley, Handbook of Frequency Stability Analysis, NIST SP 1065, ~p.107) à tau = 1, 2, avec une tolérance relative de 1e-4 ; l'accord réel est d'environ 1e-6. Cela ancre les mathématiques des estimateurs sur l'implémentation de référence de fait, et non seulement sur l'auto-cohérence analytique des estimateurs eux-mêmes. Seuls les chiffres de référence publics sont utilisés ; aucun code tiers.
  • Diagramme de Stanford vertical d'intégrité exporté par le scénario integrity. Le type de scénario integrity exécutable exporte désormais un diagramme de Stanford(-ESA) vertical en plus de la carte de disponibilité HPL/VPL : à chaque époque protégée, un tirage reproductible, avec graine, d'erreur de distance sans panne est converti par la géométrie en une erreur de position verticale réelle, puis classé par rapport au VPL et à la limite d'alerte verticale (Available / System-Unavailable / Misleading / Hazardously-Misleading). Le diagramme (points par époque + décomptes par région) est porté dans le JSON du résultat, et les décomptes d'événements d'intégrité / IHM dans le résumé de la CLI, de sorte que le classificateur de Stanford, auparavant réservé à la bibliothèque, est accessible de bout en bout. IntegrityScenario gagne un champ seed (valeur par défaut 0) qui commande la réalisation de l'erreur ; la carte de disponibilité elle-même reste purement géométrique et indépendante de la graine.
  • Budget de risque d'intégrité (P_HMI) ARAIM pour les niveaux de protection. raim::araim_raim déduit les niveaux de protection horizontal et vertical d'un budget explicite de risque d'intégrité plutôt que d'un multiplicateur K_md fixe : pour la solution toutes satellites en vue et pour chaque sous-solution excluant un seul satellite, il construit le triplet (prior, detection threshold, σ) de chaque mode sur chaque axe, puis araim_protection_level détermine le plus petit PL dont la probabilité cumulée d'informations dangereusement trompeuses (araim_integrity_risk, P_HMI = Σ_k p_fault,k · Q((PL − T_k)/σ_k), Blanch et al., Baseline ARAIM) respecte la valeur P_HMI allouée. Le résultat indique le risque d'intégrité que les niveaux atteignent réellement, de sorte qu'un utilisateur peut arbitrer explicitement entre intégrité et limite d'alerte. Six tests dérivés à la main (formes closes à mode unique sans panne et avec seuil, sommation/monotonie multi-modes, protection de bout en bout sans panne avec un budget 10⁵ fois plus serré qui relève le PL, détection/identification de panne, et plancher de redondance à six satellites). La MHSS à panne unique est la référence de base ARAIM ; les pannes simultanées de sous-ensembles de plusieurs SV, le mode de panne touchant toute la constellation et la validation sur le jeu de données de référence gLAB sont des extensions documentées.
  • Compensation du coning/sculling à deux cadences pour la mécanisation strapdown. inertial::mechanization::coning_sculling_compensate extrait les termes à haute cadence de coning (attitude) et de rotation+sculling (vitesse) des incréments d'IMU ordonnés des sous-intervalles d'une mise à jour grossière, de sorte qu'un NavState::step_increments à cadence modérée reproduit le mouvement rectifié par les vibrations qu'un pas grossier appliqué aux sommes brutes manque. Un test de validation soumet un environnement de coning+sculling à 10 Hz pendant 60 s et compare la vérité à cadence fine, l'intégration grossière naïve et l'intégration grossière avec repliement : le repliement réduit l'erreur de position d'environ 18 fois (de mètres de dérive naïve à moins du décimètre), ce qui confirme que les termes de coning/sculling sont déterminants. Un alias de type ScalarErrorBudget désigne l'ancien AccelModel à 1 degré de liberté pour ce qu'il est, distinct du navigateur à trois axes NavState.
  • Analyseur de fichiers d'observation RINEX. Le nouveau module rinex_obs lit le fichier d'observation RINEX 3.0x / 4,00, c'est-à-dire les mesures réelles du récepteur, et complète ainsi la paire RINEX aux côtés de l'analyseur de messages de navigation existant. parse_obs décode l'en-tête (version/type, listes SYS / # / OBS TYPES par système avec lignes de continuation, position approchée, intervalle, instant de la première observation) et les enregistrements par satellite de chaque époque : pseudodistance, phase de la porteuse, Doppler et intensité du signal, indexés par leur code d'observation RINEX 3 (C1C, L1C, …) avec les indicateurs de perte de verrouillage (LLI) et d'intensité du signal (SSI), un champ vide étant conservé comme absent plutôt que comme zéro. Périmètre honnête : il s'agit de l'ingestion au format normalisé (un vrai journal d'observation de station RTKLIB/gLAB/IGS en entrée, des mesures typées en sortie), et non d'un moteur de positionnement : ni solution de pseudodistance, ni PPP, ni RTK ici.
  • Écrivain CCSDS OEM (Orbit Ephemeris Message). Le nouveau module oem exporte une constellation propagée sous la forme d'un message CCSDS 502.0-B OEM 2,0 valide, le format d'éphéméride KVN qu'ingèrent GMAT, Orekit, STK et la plupart des outils de dynamique du vol. OemFile::from_propagators échantillonne sur une grille temporelle l'état inertiel (TEME) de chaque satellite, position et vitesse, pris directement du propagateur sans rotation terrestre, contrairement à l'export SP3, et OemFile::to_oem_string sérialise l'en-tête CCSDS_OEM_VERS/CREATION_DATE/ ORIGINATOR ainsi qu'un segment META_START … META_STOP par satellite (OBJECT_NAME/OBJECT_ID/CENTER_NAME/REF_FRAME = TEME/TIME_SYSTEM = GPS/ START_TIME/STOP_TIME) suivi de ses lignes epoch X Y Z X_DOT Y_DOT Z_DOT (km, km/s). La CREATION_DATE est fournie par l'appelant, jamais lue sur l'horloge murale, de sorte que la sortie est identique à l'octet près d'une exécution à l'autre (le contrat de reproductibilité). C'est le pendant, pour les éphémérides d'engins spatiaux, de l'export SP3 GNSS : une orbite Kshana peut désormais être transmise à un outil de dynamique du vol dans un format standard.
  • Éphéméride précise SP3 comme source de propagation. Sp3File::interpolator construit, pour chaque satellite, un Sp3Interpolator qui comble la position entre les époques SP3 tabulées avec un polynôme de Lagrange d'ordre 9 (pratique IGS standard) et la fait pivoter dans le référentiel TEME partagé, exposé sous le nom Propagator::Sp3Precise. Un fichier d'orbites précises d'un centre d'analyse IGS peut désormais alimenter le même pipeline de géométrie/visibilité/intégrité que les propagateurs diffusés et analytiques. Aller-retour validé : une orbite képlérienne écrite en SP3 puis relue par l'interpolateur concorde avec l'originale à moins d'un mètre aux nœuds et à < 100 m en milieu d'intervalle. L'interpolation de l'horloge vient ensuite.
  • Éphéméride diffusée GLONASS (complète la navigation RINEX multi-GNSS). Nouveau module glonass : GLONASS ne diffuse pas d'éléments képlériens mais un vecteur d'état PZ-90 lié à la Terre (position, vitesse, accélération luni-solaire). parse_glonass_nav lit les enregistrements RINEX 3 R, et la position du satellite à un instant quelconque s'obtient par intégration de Runge–Kutta d'ordre 4 des équations du mouvement de l'ICD GLONASS (gravité centrale + J2 + termes de Coriolis/centrifuge dus à la rotation de la Terre + accélération diffusée). Exposé sous le nom Propagator::Glonass, de sorte que les satellites GLONASS traversent le pipeline constellation/visibilité/intégrité aux côtés des systèmes képlériens ; un même bloc de constellation rinex peut désormais mêler GPS, Galileo, QZSS, BeiDou et GLONASS.
  • Navigation RINEX multi-GNSS (GPS, Galileo, QZSS, BeiDou). L'analyseur de navigation RINEX 3 décode désormais les enregistrements Galileo (E), QZSS (J) et BeiDou (C, MEO/IGSO) en plus de GPS (G) : ils partagent la même disposition képlérienne et le même algorithme utilisateur, chacun étant évalué avec sa propre constante gravitationnelle et sa propre vitesse de rotation de la Terre (μ de Galileo/BeiDou, Ω̇ₑ de BeiDou). Un fichier à constellations mixtes les fournit toutes, et elles traversent le pipeline constellation/visibilité/intégrité sous le nom Propagator::Rinex. Les satellites géostationnaires BeiDou utilisent une rotation de coordonnées différente et sont ignorés, en attendant un jeu de référence par rapport auquel les valider. Le parcours des enregistrements utilise des nombres de lignes propres à chaque système, ce qui corrige un bogue latent où les enregistrements GLONASS/SBAS de quatre lignes étaient sautés comme s'ils en comptaient huit. GLONASS (un modèle à vecteur d'état) vient ensuite.
  • Lecteur et écrivain d'éphémérides précises SP3-c/d. Le nouveau module sp3 analyse les fichiers d'orbites précises SP3 des centres d'analyse IGS (parse_sp3), produit ECEF position/horloge post-traité que les moteurs PPP (Ginan, RTKLIB, gLAB) traitent comme référence, pour en faire un Sp3File structuré (en-tête, grille d'époques, position par satellite km→m, horloge µs, et vitesse dm/s→m/s pour les produits V), en préservant les valeurs sentinelles de mauvaise donnée de SP3. Le sens inverse est également couvert : Sp3File::from_propagators construit un SP3 à partir d'une constellation propagée (TEME→ECEF à chaque époque) et to_sp3_string le sérialise, de sorte que les orbites Kshana peuvent être exportées dans le format qu'ingèrent les outils PPP externes : l'aller-retour lecture↔écriture. L'interpolation d'époque et une source de propagateur SP3 viennent ensuite.
  • Éphéméride diffusée RINEX comme source de constellation exécutable. Une constellation accepte désormais un bloc rinex en ligne (texte de navigation GPS RINEX 3) en plus de l'option tle existante, de sorte qu'un vrai fichier de diffusion pilote un scénario de bout en bout depuis la CLI, Python ou le bac à sable dans le navigateur : RINEX en entrée, géométrie PNT en sortie. Le nouveau scenarios/orbit-rinex.toml démontre la disponibilité GNSS et le DOP à partir de huit satellites GPS construits directement à partir des enregistrements diffusés. (GPS LNAV uniquement ; le multi-GNSS et SP3 viennent ensuite.)
  • Éphéméride diffusée RINEX comme source de propagation. Un RinexEphemeris analysé se convertit désormais en orbit::Propagator (Propagator::Rinex) : la position est l'orbite diffusée IS-GPS-200 pivotée de l'ECEF vers le référentiel inertiel TEME partagé (sv_position_teme, avec un temps GPS→UT1 exact vis-à-vis des secondes intercalaires), la vitesse est obtenue par différence finie centrée, et la période orbitale est képlérienne. Des données de diffusion GPS réelles peuvent désormais alimenter le même pipeline de géométrie, de visibilité et d'intégrité (RAIM) que les propagateurs analytiques SGP4/képlériens. (Pas encore exposé comme type de scénario à fichier RINEX ; cela, ainsi que le multi-GNSS/SP3, vient ensuite.)

0.9.2 - 2026-06-03#

Ajouté#

  • DOI d'archivage. Les versions sont désormais déposées sur Zenodo et reçoivent un DOI citable.

0.9.1 - 2026-06-03#

Modifié#

  • Documentation. Le README a été remis à niveau institutionnel : un aperçu des capacités de l'ensemble de la pile v0.9.0, une section Versions et publications, un en-tête épuré avec la nouvelle marque, et une ligne d'état concise. Aucun changement du moteur.

0.9.0 - 2026-06-03#

Cette version ajoute trois domaines de capacité substantiels au-dessus du substrat SGP4 0.8.0 : un véritable INS strapdown à trois axes, un EKF à état d'erreur GNSS/INS à couplage lâche avec rétroaction en boucle fermée, un véritable RAIM d'instantané et à séparation de solutions (de type ARAIM) avec HPL/VPL et un scénario integrity exécutable, et la première étape de l'interopérabilité des formats GNSS (ingestion d'éphémérides GPS RINEX-3).

Ajouté#

  • Analyseur de messages de navigation GPS RINEX 3 (src/rinex.rs). Première étape vers l'interopérabilité des formats GNSS : parse_nav lit un fichier de navigation RINEX 3.x et décode chaque enregistrement d'éphéméride diffusée GPS (G), le bloc de huit lignes SV/époque + BROADCAST ORBIT, en un RinexEphemeris d'éléments képlériens et de corrections d'horloge, avec les noms de champs et les unités selon IS-GPS-200. Il gère le format de flottant Fortran à exposant D (parse_d) et la disposition en colonnes de largeur fixe ; les enregistrements des systèmes autres que GPS sont ignorés, non rejetés, de sorte qu'un fichier mixte fournit quand même ses éphémérides GPS. Quatre tests : analyse de l'exposant D (y compris blancs et erreurs), un enregistrement complet décodé par rapport à des valeurs de champs connues avec un contrôle de vraisemblance du demi-grand axe GPS (√A² ≈ 26 560 km), l'omission des systèmes autres que GPS, et le cas du fichier vide.
  • Éphéméride diffusée GPS → position ECEF (src/rinex.rs). RinexEphemeris::sv_position_ecef(t_tow) évalue la position du satellite dans le repère terrestre à partir de l'éphéméride analysée, via l'algorithme utilisateur IS-GPS-200 §20.3.3.4.3.1 : résolution de Newton de l'équation de Kepler pour l'anomalie excentrique, corrections de second harmonique de l'argument de latitude / du rayon / de l'inclinaison, et rotation vers l'ECEF tenant compte de la rotation de la Terre depuis l'époque de référence (avec le μ et le Ω̇ₑ GPS imposés par la spécification, et un repliement tk pour le changement de semaine). Trois tests : le rayon géocentrique reste dans la bande GPS (≈ 26 560 km), la vitesse dans le repère terrestre est d'environ 3,9 km/s, et l'évaluation à une semaine entière d'écart redonne la même position.
  • Biais d'horloge de SV GPS avec la correction relativiste (src/rinex.rs). RinexEphemeris::sv_clock_bias_s(t_tow) évalue le polynôme d'horloge diffusé af0 + af1·Δt + af2·Δt² autour de Toc plus le terme relativiste d'excentricité F·e·√A·sin Ek (IS-GPS-200 §20.3.3.3.3.1). Un nouveau EpochUtc::gps_time_of_week convertit l'époque calendaire de l'enregistrement en temps de semaine GPS par un calcul en jours juliens depuis l'époque GPS (1980-01-06), et la résolution de Kepler est partagée avec l'évaluation de position. Tests : le temps de semaine GPS pour un dimanche/mardi/samedi (limites de semaine), et le biais d'horloge dominé par af0 avec un terme relativiste présent et borné. Le délai de groupe L1 TGD est exposé mais délibérément non intégré. Périmètre honnête : une source Propagator, Galileo/BeiDou/GLONASS et SP3 restent des étapes à venir. (docs/CAPABILITY.md mis à jour en conséquence.)
  • Type de scénario integrity exécutable par l'utilisateur (scenarios/integrity-raim.toml). La capacité de disponibilité RAIM est désormais accessible depuis la CLI/TOML comme tous les autres paquets : kind = "integrity" analyse un IntegrityScenario (orbite de l'utilisateur, une ou plusieurs constellations GNSS, masque d'élévation et configuration d'intégrité (sigma, P_fa, P_md, AL_H, AL_V)), exécute constellation_raim_availability et produit la carte de disponibilité HPL/VPL par époque en JSON ainsi qu'un SVG autonome : niveaux de protection au fil du temps par rapport aux limites d'alerte, avec une bande de disponibilité verte/rouge. kshana scenarios/integrity-raim.toml écrit le JSON, le graphique et un rapport HTML. Le scénario fourni (Walker à 24 satellites, télémétrie double fréquence à 1 m, limites APV-I) indique une disponibilité d'environ 95 % ; il documente que le RAIM monofréquence ne satisfait pas la limite verticale APV-I avec une seule constellation, ce qui explique que le guidage vertical recourt à SBAS/double fréquence/ARAIM. Les tests couvrent la répartition, le JSON de la carte de disponibilité et le SVG.
  • Disponibilité RAIM exécutable sur une constellation (src/raim.rs). Le module d'intégrité n'avait aucun appelant : constellation_raim_availability en fait un véritable point d'entrée de bout en bout : à chaque époque d'une grille temporelle, il propage les satellites visibles (les mêmes Propagator SGP4/képlériens que ceux du moteur), calcule les niveaux de protection sans panne et juge la disponibilité par rapport aux limites d'alerte horizontale/verticale, en renvoyant un RaimAvailabilityReport sérialisable en serde (n_visible/HPL/VPL/available par époque plus la fraction de disponibilité). Un RaimConfig regroupe (sigma, P_fa, P_md, AL_H, AL_V), et le raim_availability_epoch par époque est exposé pour les appelants qui résolvent leur propre géométrie. Trois tests : une époque jugée disponible selon les limites APV-I sur une géométrie de dix satellites, rendue indisponible par une limite impossiblement serrée, et des niveaux None en dessous de cinq satellites ; et une exécution de bout en bout sur une constellation Walker de 24 satellites qui produit une carte de disponibilité finie et se sérialise. (Six satellites, le plancher de redondance du RAIM résiduel, ne satisfont honnêtement pas APV-I, même avec une télémétrie à 1 m ; la disponibilité APV-I exige la géométrie plus dense qu'utilise le test.)
  • Accumulateur du diagramme d'intégrité de Stanford(-ESA) (src/raim.rs). La manière standard de résumer un moniteur d'intégrité sur de nombreuses époques : il trace l'erreur de position réelle (x) en fonction du niveau de protection (y) et classe chaque époque, d'après la diagonale y = x et la limite d'alerte, en Available (le PL borne l'erreur, dans la limite d'alerte), SystemUnavailable (le PL borne l'erreur mais dépasse la limite d'alerte : sûr, inutilisable), MisleadingInformation (PL < erreur ≤ AL) ou HazardouslyMisleadingInformation (PL < erreur et erreur > AL : la défaillance dangereuse). classify_stanford est le classificateur pur ; StanfordDiagram accumule des points (error, PL) par rapport à une limite d'alerte fixe, en exposant les décomptes par région, la disponibilité, les totaux d'événements d'intégrité et des points sérialisables en serde pour le tracé/l'export JSON. Quatre tests : chaque région (y compris la frontière bornée error == PL), l'accumulation des décomptes/de la disponibilité, et l'aller-retour JSON. C'est la surface de rapport des niveaux de protection RAIM ; son raccordement au scénario de constellation et sa validation sur un jeu de données public restent des éléments de la feuille de route.
  • RAIM à séparation de solutions (de type ARAIM) (src/raim.rs). Un moniteur d'intégrité à hypothèses multiples, en plus du snapshot_raim existant fondé sur le khi-deux des résidus/de la parité. Pour la solution des moindres carrés toutes satellites en vue et pour chaque sous-solution excluant un seul satellite, il forme la séparation Δ_k = x_k − x₀, gaussienne centrée en l'absence de panne, de covariance Cov(x_k) − Cov(x₀) (l'identité des estimateurs emboîtés, valable parce que la solution toutes satellites en vue est BLUE), et il détecte ainsi une panne et identifie le satellite défaillant (celui dont l'exclusion donne la plus grande séparation normalisée). Les niveaux de protection horizontal/vertical suivent l'allocation MHSS standard PL = max(K_md·σ₀, max_k[K_fa·σ_ss,k + K_md·σ_k]), avec K_fa = Φ⁻¹(1−P_fa/2), K_md = Φ⁻¹(1−P_md). De nouveaux normal_cdf/normal_quantile sans dépendance, construits sur la fonction gamma incomplète régularisée déjà présente dans le module (erf(x) = P(½,x²)). Quatre tests dérivés à la main : fonction de répartition / quantile normaux par rapport aux valeurs des manuels (Φ(1,95996)=0,975, la queue à 1e-7 = 5,1993, symétrie) ; une géométrie sans panne qui ne déclenche pas d'alarme et donne des HPL/VPL finis et positifs ; un biais de 60 σ sur un seul satellite qui est détecté et correctement identifié (excluded_sv == 2) ; et le plancher de redondance à six satellites. Cela clôt, côté algorithme, l'écart P0 de l'audit « intégrité tautologique : pas de vrai RAIM/HPL/VPL » ; la validation sur le jeu de données gLAB et l'accumulateur du diagramme de Stanford restent des éléments de la feuille de route.
  • Intégration GNSS/INS en boucle fermée (src/fusion/closed_loop.rs). ClosedLoopInsGnss relie le noyau EKF à état d'erreur à la mécanisation strapdown à trois axes : chaque échantillon d'IMU est corrigé par les estimations de biais courantes, mécanisé vers l'avant, et la covariance de l'EKF est propagée dans le temps avec le contexte de navigation correspondant ; chaque position/vitesse GNSS forme l'innovation INS−GNSS et réinjecte dans la solution la position, la vitesse, l'erreur d'attitude (ψ, sous forme de rotation par quaternion) et les biais d'accéléromètre/gyroscope estimés, en remettant à zéro la moyenne de l'état d'erreur. Réinjecter l'attitude (et pas seulement les biais) est nécessaire à la stabilité : l'inclinaison et le biais d'accéléromètre forment un couple couplé, de sorte que corriger l'un sans l'autre diverge. L'INS et le GNSS sont comparés dans un repère NED de plan tangent local en utilisant les rayons de courbure propres à la mécanisation (nouveau mechanization::radii_of_curvature ; NavState::omega_ie_n/omega_en_n exposés). C'est le remplacement honnête de la réinitialisation sur la vérité terrain du paquet hybride. Trois tests : une boucle fermée qui annule une erreur de position injectée de 8 m / −5 m à <0,1 m ; une solution assistée qui reste bornée au mètre (<6 m) sur une trajectoire en conduite pendant qu'un INS en roue libre diverge au-delà de 100 m ; et le banc d'essai jalon : le RMS de position Monte-Carlo de la solution fusionnée pendant une interruption GNSS de 60 s fait mieux, d'un facteur >2, qu'un estimateur à l'estime en boucle ouverte sans assistance (≈4× selon les graines). Limite honnête documentée dans le module : en mode à couplage lâche, le biais d'accéléromètre et l'inclinaison ne sont que faiblement séparables (tous deux se couplent par la gravité), de sorte que la valeur fournie est l'état borné et corrigé et une entrée propre dans l'interruption, et non un étalonnage inertiel précis ; une dynamique plus riche et l'extension à couplage serré restent des éléments de la feuille de route.
  • Noyau EKF à état d'erreur GNSS/INS à couplage lâche (src/fusion/gnss_ins_ekf.rs). Un filtre de Kalman étendu à état d'erreur à 15 états, δx = [δp, δv, ψ, b_a, b_g], avec la dynamique d'erreur strapdown de Groves 2013 §14,2 (couplage force spécifique/inclinaison, Coriolis, projection du biais du repère porteur vers le repère de navigation, modèles de biais de Gauss–Markov), une transition discrète du premier ordre Φ = I + F·dt, et une mise à jour de mesure position+vitesse à couplage lâche (H = [I₃ 0 0 0 0; 0 I₃ 0 0 0]) sous forme de Joseph. Algèbre linéaire dense sans dépendance (inverse de Gauss–Jordan, mise à jour de covariance de Joseph). Une fonctionnalité cargo tight_coupling conditionne une mise à jour pseudodistance/Doppler documentée, non encore implémentée. 7 tests aux résultats attendus dérivés à la main : l'identité de l'antisymétrique/du produit vectoriel, un inverse 3×3 vérifié, une covariance qui reste symétrique/PSD pendant la prédiction (avec une incertitude de position qui croît sans assistance), une position qui réduit la covariance de position, la récupération exacte d'une erreur de position connue au gain de Kalman analytique P/(P+R), et des corrections plus faibles sous un bruit de mesure plus fort. C'est le noyau qui remplacera la réinitialisation sur la vérité terrain en boucle ouverte du paquet hybride par une rétroaction en boucle fermée (raccordement du paquet et validation NaveGo à suivre).
  • Modèle déterministe d'erreurs d'IMU pour le navigateur strapdown à 3 axes (src/inertial/imu_errors.rs). ImuErrorModel déforme une paire (ω, f) vraie dans le repère porteur en une paire mesurée au moyen de cinq catégories systématiques (IEEE Std 952-1997 §A.2 ; Groves 2013 §4,3, tableau 4,1) : facteur d'échelle (erreur de gain par axe en ppm), désalignement / couplage croisé (non-orthogonalité hors diagonale du trièdre), sensibilité à g (un biais de vitesse angulaire du gyroscope proportionnel à la force spécifique), quantification (arrondi au LSB de sortie) et rampe de vitesse (une dérive linéaire dans le temps, la troisième région d'Allan), plus un biais constant à la mise sous tension. Chaque terme vaut zéro par défaut, de sorte que ImuErrorModel::ideal() est un simple passage transparent et que les scénarios existants ne sont pas affectés. Chaque source d'erreur a un test d'isolement (échelle linéaire à <0,01 % près, désalignement inter-axes au-dessus du plancher VRW, biais de sensibilité à g, grille de LSB, rampe linéaire), et un test de bout en bout fait produire une erreur de navigation à la mécanisation à partir d'une IMU déformée. Non modélisés : l'erreur de rectification par les vibrations et la dérive due au gradient de température. (Le paquet de scénarios inertial livré exécute toujours l'ancien budget scalaire à 1 degré de liberté ; ce modèle alimente la bibliothèque à 3 axes.)
  • Compensation du coning et du sculling pour l'intégrateur strapdown. Le chemin d'attitude ajoute le coning_increment à deux échantillons (½ Δθ_prev × Δθ_cur) ; il est vérifié qu'une intégration à cadence grossière (30 Hz, 5 échantillons par cycle) d'un environnement de coning à 5 Hz suit la vérité à cadence fine au moins 3 fois mieux avec la correction qu'avec une simple somme d'incréments. Le chemin de vitesse ajoute sculling_increment (½ Δθ × Δv, éq. 5,82 de Groves) et résout l'incrément de vitesse du repère porteur au moyen d'une nouvelle mise à jour par incréments NavState::step_increments utilisant la rotation relative au repère porteur Δθ_rel = Δθ_b − C_n^b ζ, de sorte qu'une plateforme liée à la Terre ne subit aucun sculling parasite alors qu'une vraie vibration déclenche le terme complet.
  • Mécanisation strapdown complète à trois axes dans le repère NED (src/inertial/mechanization.rs). NavState { q, v_ned, p_llh } est avancé par step(gyro_b, accel_f_b, dt) à l'aide des équations NED standard dans le repère terrestre (Groves §5,4) : attitude repère porteur→NED corrigée de la vitesse angulaire inertiel-vers-navigation ω_in = ω_ie + ω_en (rotation de la Terre + vitesse de transport) ; force spécifique résolue repère porteur→NED par la DCM ; vitesse intégrant v̇ = f_n − (2 ω_ie + ω_en) × v + g_n (Coriolis/transport + gravité) ; et position géodésique par les rayons de courbure méridien/transverse. La gravité est la gravité normale (fil à plomb) de Somigliana en forme close WGS-84, avec une correction d'altitude en air libre NIMA, et jamais une constante codée en dur. C'est le véritable navigateur à trois axes qui supplante le chemin scalaire à 1 degré de liberté fondé sur un budget d'erreur. Vérifié par des invariants physiques : une plateforme boulonnée à la Terre en rotation à 45° N (percevant la vitesse de rotation de la Terre + 1 g) reste à moins de 1 mm pendant 60 s ; une force spécifique horizontale vers le nord donne v_N ≈ a·t et un déplacement ½ a t² ; la gravité normale concorde avec les valeurs de surface connues à l'équateur/au pôle/à 45° et avec le gradient en air libre.
  • Représentation d'attitude à trois axes pour l'INS strapdown (src/inertial/attitude.rs). Un type de quaternion unitaire Quaternion (scalaire en premier, convention de Hamilton) portant la rotation repère porteur→navigation, avec une vue DCM (to_dcm/from_dcm par la méthode de Shepperd), le produit de Hamilton, des constructeurs axe-angle et vecteur de rotation (application exponentielle exacte), et la cinématique des quaternions : à la fois une mise à jour de vitesse RK du premier ordre (q̇ = ½ q ⊗ ω) et une mise à jour du vecteur de rotation corrigée du coning. Le coning_increment à deux échantillons (Savage / Bryan–Lewantowski, ½ Δθ_prev × Δθ_cur) fournit le terme de couplage croisé de vitesse de rotation que l'estime scalaire omet. C'est le socle d'attitude de la mécanisation complète à 3 axes qui remplace l'ancien chemin à budget d'erreur à 1 degré de liberté. Vérifié par rapport à des rotations en forme close : la propagation à vitesse constante concorde avec le quaternion axe-angle à 1e-6 près, les DCM sont orthonormées de déterminant unité, et le coning s'annule pour un mouvement à axe unique. (src/inertial.rs est désormais le répertoire de module src/inertial/ ; le chemin public crate::inertial est inchangé.)
  • Visibilité d'une station au sol géodésiquement correcte (src/frames.rs). elevation, is_visible et visible_count calculent l'élévation d'un satellite au-dessus de l'horizon d'une station au sol par rapport à la normale à l'ellipsoïde WGS-84 (la vraie verticale locale), et non par rapport à la direction radiale géocentrique : les deux diffèrent jusqu'à environ 0,19° de déviation géodésique, ce qui suffit à faire entrer ou sortir d'un masque d'élévation des satellites proches de l'horizon. Vérifié de bout en bout (une constellation Walker propagée, pivotée de TEME vers ECEF, puis comptée depuis un site géodésique) et par rapport à l'approximation géocentrique.

Modifié#

  • Fiabilité de la CI. Le job test-python-bindings construit désormais la wheel avec PyO3/maturin-action (conteneur manylinux) au lieu d'un maturin build brut sur l'hôte, ce qui élimine un conflit rustup intermittent rustfmt-preview/cargo-fmt sur l'image du runner. Le job deny installe cargo-deny sous forme de binaire précompilé via taiki-e/install-action au lieu de l'action cargo-deny-action fondée sur Docker, ce qui supprime un délai d'attente dépassé lors du téléchargement depuis le registre Docker Hub. Aucun de ces changements n'affecte les vérifications effectuées.

0.8.0 - 2026-06-02#

Ajouté#

  • La vitesse inertielle est exposée en aval. Propagator::velocity_eci et Propagator::state_eci (qui renvoie StateEci { r_m, v_m_s }) transmettent aux appelants, en m/s, la vitesse TEME analytique que SGP4 calcule déjà et qui était jusque-là écartée ; Orbit::velocity_eci donne au chemin képlérien une vitesse cohérente. Le test de vérification AIAA 2006-6753 contrôle désormais aussi la vitesse pour chaque ligne de référence (pire erreur de vitesse 1.85e-9 km/s sur l'ensemble des 666 états) et fixe le nombre de lignes comparées à exactement 666.

  • Analyse TLE plus stricte et sans panique. Les lignes doivent être en ASCII et sont découpées en toute sécurité (plus de paniques d'index d'octet sur une entrée multi-octets) ; les éléments sont soumis à un contrôle de plage (inclinaison, excentricité, mouvement moyen) ; la somme de contrôle de la colonne 69 peut être imposée via ParseOpts { strict_checksum } / parse_propagators_opts et le nouvel indicateur strict_checksum de ConstellationCfg (tolérant par défaut).

  • Courbe d'écart-type d'Allan dans la sortie. Chaque exécution d'horloge fournit désormais une adev_curve ([{tau_s, adev, n_samples}]), et le bac à sable du navigateur affiche un graphique log-log « Stabilité de l'horloge (ADEV) ».

  • Validation des entrées de la grille temporelle. TimeCfg::validate rejette une grille temporelle non finie, nulle, négative ou démesurée (un pas supérieur à la durée, ou plus de MAX_TIME_STEPS échantillons) avant toute allocation, de sorte qu'un scénario mal formé renvoie une erreur au lieu de paniquer ou d'épuiser la mémoire.

  • Ensembles Monte-Carlo pour le paquet inertiel. runs = N sur un scénario inertiel exécute N graines et fournit pour chaque métrique la moyenne, l'écart-type, les percentiles et un intervalle de confiance à 95 % par bootstrap de percentiles (ensemble). Chaque exécution inertielle porte désormais un indicateur monte_carlo, de sorte qu'une figure de mérite à réalisation unique ne soit plus prise pour une distribution. (CEP/2DRMS ne sont volontairement pas fournis : ils exigent le modèle à 3 axes qui figure sur la feuille de route.)

  • Mode bac à sable guidé. Le bac à sable du navigateur ne vous jette plus devant un mur de TOML brut : un bandeau « Commencer ici » de cartes de scénarios en un clic charge et exécute un exemple travaillé, des curseurs exposent les paramètres universels (graine, seuil de synchronisation temporelle) sans toucher au TOML, une note « Comment lire ceci » explique le résultat, et le TOML complet se déplie en un clic. Chaque exécution est partageable : Copier le lien de partage encode tout le scénario dans le fragment d'URL (rien n'est téléversé), de sorte qu'un lien reproduit l'exécution exacte au chargement. Le codec est testé unitairement (web/share.test.mjs, exécuté en CI).

  • Balayages de paramètres à N dimensions (src/sweep.rs). nd_sweep évalue une métrique sur le produit cartésien complet de plusieurs plages SweepAxis (l'étude de compromis multiparamètre), dans l'ordre ligne par ligne, de façon déterministe. Additif : l'API de balayage 1-D existante est inchangée. Les intervalles de confiance par bootstrap à chaque nœud et la généralisation au-delà du paquet d'horloge restent sur la feuille de route.

  • RAIM d'instantané réel (src/raim.rs). Une véritable surveillance autonome de l'intégrité par le récepteur dans le domaine des positions : il construit la géométrie de ligne de visée vers les satellites visibles, forme la solution des moindres carrés et les résidus, exécute un test de détection de panne par le χ² des résidus (seuil exact issu d'un χ²/χ² non central à gamma incomplète sans dépendance), et calcule des niveaux de protection horizontal et vertical fondés sur la pente (HPL/VPL), avec le biais de détection manquée dérivé pour les P_fa/P_md configurés. Cela se distingue de la figure d'intégrité d'auto-cohérence du filtre du pipeline de scénarios, et n'y est pas encore raccordé ; l'exclusion de panne, le budget limite d'alerte/P_HMI et l'ARAIM restent sur la feuille de route.

  • Suite de stabilité de fréquence : MDEV, TDEV, HDEV + intervalles de confiance (src/allan.rs). En plus de l'ADEV à recouvrement : l'écart-type d'Allan modifié (qui sépare le bruit de phase blanc du bruit de phase flicker), l'écart temporel (TDEV = tau/sqrt(3) * MDEV) et l'écart-type de Hadamard (qui rejette exactement la dérive linéaire de fréquence et converge pour les types de bruit rouge divergents). Les intervalles de confiance fondés sur le χ² (deviation_ci) utilisent une paire quantile normal/χ² sans dépendance (Acklam + Wilson-Hilferty) avec un edf conservateur sans recouvrement ; l'edf propre au type de bruit et la parité numérique avec Stable32 restent sur la feuille de route.

  • Réduction de référentiel (src/frames.rs). Rotation TEME↔ECEF fondée sur le GMST (avec le même temps sidéral IAU-1982 que le propagateur), conversion géodésique↔ECEF WGS-84 exacte avec un inverse itératif initialisé par Bowring (précision machine à toutes les altitudes, y compris MEO/GEO), et un observateur de station au sol géodésique qui renvoie azimut / élévation / distance dans le repère local Est-Nord-Haut. Le mouvement du pôle et la nutation inférieure à la seconde d'arc ne sont pas appliqués (GMST seul, précision sub-kilométrique sur la trace au sol) ; une chaîne CIO précise à l'ITRF figure sur la feuille de route.

  • Fondation des échelles de temps (src/timescales.rs). Une API de dates juliennes sans dépendance (calendrier grégorien ↔ JD, MJD), l'historique complet des secondes intercalaires entières de l'IERS (UTC↔TAI, 10 s en 1972 à 37 s depuis 2017), le décalage TAI→TT défini, la correction UT1 au moyen d'un DUT1 fourni, et l'angle de rotation de la Terre IAU-2000. C'est le substrat temporel sur lequel repose la réduction de référentiel terrestre (prévue). Les instants sont des dates juliennes en f64 unique (résolution d'environ 50 µs près de l'époque actuelle ; un JD en deux parties figure sur la feuille de route), et l'ère de la seconde élastique antérieure à 1972 n'est pas modélisée ; les deux points sont documentés dans le module.

  • Reproductibilité et provenance. Un générateur de SBOM CycloneDX déterministe (scripts/gen-sbom.sh) et une attestation de provenance de construction SLSA sur le binaire de la version et sur le SBOM ; la chaîne d'outils de la version est épinglée pour correspondre à la CI. Les garanties de déterminisme, la réserve libm entre plateformes et l'approche d'épinglage des valeurs de référence (golden) sont documentées dans docs/REPRODUCIBILITY.md.

  • Tests fondés sur les propriétés et tests de fuzzing (tests/property.rs). Des tests aléatoires déterministes (sans nouvelle dépendance) vérifient des invariants sur des milliers d'entrées : les analyseurs de TLE et de scénarios ne paniquent jamais sur une entrée aberrante, non ASCII, mutée ou tronquée ; TimeCfg::validate ne panique jamais sur des grilles NaN/inf/négatives ; la somme de contrôle TLE est cohérente et ne porte que sur la colonne 69 ; les allers-retours géodésique↔ECEF et la rotation TEME→ECEF conservent la norme sur tout le globe et sur une large bande d'altitudes.

Modifié#

  • Les tests de référence (golden) épinglent désormais les figures de mérite champ par champ pour les quatre scénarios de référence (avec une tolérance qui absorbe la gigue libm entre plateformes), en remplacement des anciens contrôles par simple inégalité, de sorte qu'une régression numérique silencieuse soit détectée immédiatement.
  • schema_version dans les artefacts de résultats passé de 0.1 à 0.7 (il était figé alors que le moteur évoluait).
  • cargo-deny refuse désormais (et n'avertit plus pour) les dépendances retirées (yanked).
  • Nouvelle documentation : CAPABILITY.md (carte honnête du périmètre), SCHEMA.md (référence des champs de résultat), INTEGRITY.md, QUANTUM-MODELS.md, REAL_TLE_GUIDE.md. Un garde-fou de CI échoue si le badge de version du README s'écarte de Cargo.toml.

0.7.0 - 2026-06-02#

Ajouté#

  • Propagation d'orbite SGP4/SDP4. Une implémentation complète et sans dépendance du propagateur standard à perturbations simplifiées : SGP4 pour le proche de la Terre, avec l'extension SDP4 pour l'espace lointain (perturbations luni-solaires séculaires et périodiques et résonance du géopotentiel à 12 h / 24 h). Il est validé par rapport aux vecteurs de vérification officiels AIAA 2006-6753 (« Revisiting Spacetrack Report #3 ») : les 666 états de référence couvrant les cas proche de la Terre, espace lointain, résonant et codes d'erreur concordent, avec une erreur de position au pire cas d'environ 4 mm. C'est le modèle par rapport auquel les jeux d'éléments à deux lignes sont définis, il représente donc de vraies constellations, notamment les orbites GNSS d'environ 12 h, qui relèvent de l'espace lointain et sont résonantes, et que l'ancien modèle à deux corps + J2 séculaire ne peut pas capter.
  • Une constellation fournie sous forme de jeux complets d'éléments à deux lignes (ligne 1 + ligne 2) est désormais propagée avec SGP4/SDP4 ; une constellation fournie sous forme d'éléments de ligne 2 seule conserve la propagation képlérienne analytique à deux corps, inchangée. Les deux formes peuvent être mêlées dans un même bloc. Nouveau scénario de référence orbit-sgp4-gps.toml (une constellation MEO de type GPS au vrai format à deux lignes, propagée avec SGP4) : intégrez un jeu « gps-ops » de Celestrak à jour pour étudier la constellation réelle.

0.6.0 - 2026-06-02#

Ajouté#

  • Démonstrateur actif d'attaque par leurrage. Un nouveau type de scénario spoof injecte un leurrage temporel faux à rampe croissante et exécute pour chaque horloge son moniteur d'intégrité assisté par l'horloge, en indiquant si et quand le leurrage est détecté et s'il atteint la spécification opérationnelle sans être détecté, ce qui transforme la figure de mérite de sécurité en une démonstration concrète d'attaque/défense. Nouveau scénario de référence spoof-attack.toml.
  • Disponibilité multi-constellation. Un scénario d'orbite peut combiner plusieurs constellations (une liste [[constellations]] aux côtés de la [constellation] principale) pour la disponibilité multi-GNSS et la dilution de précision, par exemple GPS plus Galileo. Nouveau scénario de référence orbit-multignss.toml.

0.5.0 - 2026-06-02#

Ajouté#

  • Rapport de tableau de bord HTML. Chaque exécution produit désormais aussi un tableau de bord HTML autonome et de marque : le résumé en une ligne, le graphique (intégré sous forme d'image data-URI inerte) et le JSON complet, écrits par la CLI à côté du JSON et du SVG. Un artefact partageable en un seul fichier pour un livrable d'étude ou une annexe.
  • Estimateur conjoint de fusion de capteurs. Un nouveau type de scénario fusion exécute un unique filtre de Kalman récursif comme solution de navigation, en fusionnant l'état d'horloge [phase, frequency] et l'état de position [position, velocity], asservi par le GNSS (qui apprend le décalage de fréquence et la vitesse) et assisté par le transfert de temps optique pendant l'interruption, plutôt que de composer des prédicteurs indépendants. Il fournit un holdover de synchronisation temporelle/de position fusionné et une intégrité à covariance conjointe. Nouveau scénario de référence fusion-pnt.toml.
  • Modèle de bruit d'IMU plus complet. L'accéléromètre modélise désormais les termes restants de la variance d'Allan au-delà du biais constant et de la marche aléatoire de vitesse : l'instabilité de biais (un plancher de flicker en 1/f au coefficient standard d'instabilité de biais d'Allan, réutilisant la synthèse de flicker de l'horloge) et la marche aléatoire d'accélération. Nouveaux champs facultatifs bias_instability et q_aa de scénario inertiel ; une nouvelle fixation GNSS réétalonne la dérive de biais résiduelle.
  • Géométrie réelle de constellation à partir de TLE. Une constellation peut être fournie sous forme d'un bloc de jeux d'éléments à deux lignes (le format standard NORAD/Celestrak) via un champ tle, de sorte que la disponibilité et la dilution de précision utilisent la géométrie publiée d'une constellation réelle plutôt qu'un motif Walker synthétique. Le moteur lit les éléments képlériens moyens de chaque TLE et les propage à deux corps, et non avec SGP4, ce qui est valable pour une étude instantanée à partir d'une époque commune. Nouveau scénario de référence orbit-real-tle.toml.

0.4.0 - 2026-06-02#

Ajouté#

  • Balayages de paramètres pour études de compromis. Un nouveau type de scénario sweep fait varier un paramètre (threshold_ns, duration_s, quantum_q_wf ou classical_q_wf) sur une plage linéaire ou logarithmique et enregistre une figure de mérite choisie en chaque point pour les deux horloges, ce qui produit le graphique comparatif « comment le holdover évolue-t-il avec la stabilité de l'horloge ? » dont un compromis de conception a besoin. Nouveau scénario de référence sweep-clock-stability.toml.
  • Bandes de confiance Monte-Carlo. Le scénario de holdover d'horloge peut exécuter de nombreuses réalisations (nouveau champ facultatif runs) : chaque figure de mérite est alors fournie sous forme de moyenne avec un étalement du 5ᵉ au 95ᵉ percentile, et le graphique ombre l'enveloppe d'erreur de 5 à 95 % autour de la médiane pour chaque horloge. Une exécution unique reste le comportement par défaut. Nouveau scénario de référence clock-ensemble.toml.
  • Orbites excentriques et dérive J2. Le type d'orbite est désormais une orbite képlérienne complète (demi-grand axe, excentricité, inclinaison, RAAN, argument du périgée, anomalie moyenne), propagée par résolution de l'équation de Kepler, avec en option la régression nodale séculaire due à J2 et la précession apsidale. Nouveaux champs facultatifs eccentricity, argp_deg et j2 de scénario, et un scénario de référence orbit-molniya.toml (un utilisateur à orbite fortement excentrique et à inclinaison critique, de 12 h). Les orbites circulaires conservent le chemin d'origine en forme close, bit à bit.
  • Le paquet hybride (PNT combiné) fournit désormais l'intégrité et la sécurité, de sorte que les quatre paquets couvrent l'ensemble complet des figures de mérite opérationnelles. L'intégrité est le confinement dans la borne de protection du canal de synchronisation temporelle, issu d'un estimateur de Kalman asservi à la vérité terrain tant que le GNSS est nominal et réancré (plus lâchement) à chaque resynchronisation optique ; sa borne inclut le plancher de bruit de mesure de la liaison, de sorte qu'une horloge bien meilleure que la liaison est notée par rapport au bruit réel de la solution délivrée. La sécurité est le score de détection de leurrage assistée par l'horloge par rapport à la spécification de synchronisation temporelle.

Modifié#

  • Les notes de version sont désormais générées à partir de la section CHANGELOG organisée pour l'étiquette (scripts/changelog-extract.sh), de sorte que chaque version GitHub met en avant ce qui a changé au lieu de lister les commits bruts.

0.3.0 - 2026-06-02#

Ajouté#

  • Figure de mérite de sécurité (jusque-là non renseignée) : un score de détection de leurrage assistée par l'horloge pour les paquets d'horloge en holdover et d'orbite. Il modélise un moniteur d'intégrité qui recoupe le temps issu du GNSS avec la prédiction à l'inertie de l'horloge elle-même sur une fenêtre cohérente ; le plancher de détection combine le bruit de mesure moyenné et l'incertitude de marche à l'inertie de l'horloge, de sorte qu'une horloge plus silencieuse détecte des leurrages temporels plus petits et plus lents. Le score est exprimé dans [0, 1] par rapport à la spécification de synchronisation temporelle, ce qui complète les six figures de mérite opérationnelles.
  • Précision de position dérivée de la géométrie pour le paquet d'orbite : à partir de la géométrie de ligne de visée vers les satellites visibles, il forme la matrice de conception et son facteur de covariance Q = (HᵀH)⁻¹, ce qui donne les facteurs de dilution de précision (GDOP/PDOP/HDOP/VDOP/TDOP). La précision de position est le DOP de position mis à l'échelle par une erreur de distance équivalente utilisateur configurable (nouveau champ facultatif de scénario sigma_uere_m). Un résultat d'orbite porte désormais un résumé de géométrie (fraction d'échantillons avec une position, meilleur PDOP et PDOP médian, et sigma de position).
  • Un bac à sable dans le navigateur (web/) qui exécute le moteur côté client en WebAssembly : choisissez un scénario de référence ou modifiez le TOML, exécutez-le, et consultez le résumé, le graphique et le JSON complet, sans rien téléverser. Un workflow pages le construit et le publie sur GitHub Pages, et un nouvel export WebAssembly summary alimente l'affichage.
  • Axes y étiquetés sur les graphiques SVG : lignes de grille, étiquettes numériques de graduation et titre d'axe avec les unités (via un assistant chart partagé), de sorte que les ordres de grandeur soient lisibles.
  • Workflow de publication de paquets (publish) pour crates.io, PyPI et npm, chacun conditionné par son jeton de registre et déclenché par une version publiée.

0.2.0 - 2026-06-02#

Ajouté#

  • Plancher de FM flicker (1/f) pour le modèle d'erreur d'horloge, synthétisé comme une somme de processus d'Ornstein-Uhlenbeck à espacement logarithmique et étalonné pour que le plancher plat de l'écart-type d'Allan se situe à un niveau configurable. Désactivé par défaut ; activé par horloge via le champ facultatif flicker_floor du scénario.
  • Canal gyroscopique pour le modèle inertiel : le biais gyroscopique résiduel et la marche aléatoire angulaire engendrent une erreur d'attitude (inclinaison) qui couple la gravité à une erreur de force spécifique horizontale, le principal mécanisme de croissance d'erreur du strapdown. Désactivé par défaut ; activé par capteur via les champs facultatifs gyro_bias et q_arw.
  • Estimateur de Kalman d'horloge à deux états (phase, fréquence) avec discrétisation exacte de van Loan du bruit de processus. Une marche à l'inertie à partir d'un état connu reproduit exactement la croissance analytique de l'erreur de holdover (q_wf*T + q_rw*T^3/3), et le filtre fournit en outre une borne d'incertitude à 1 sigma en ligne.
  • L'exécution d'horloge fournit désormais la figure de mérite d'intégrité (jusque-là non renseignée) : la fraction des échantillons de l'interruption dont l'erreur reste à l'intérieur de la borne de protection à 3 sigma du filtre, présentée dans le résultat JSON et dans le résumé de la CLI.
  • Disponibilité GNSS dérivée de la géométrie : la propagation d'orbite circulaire, un générateur de constellation Walker-delta et la visibilité en ligne de visée (occultation par la Terre plus masque d'élévation) produisent la chronologie de disponibilité à partir de la véritable géométrie orbitale. Nouveau type de scénario orbit et scénario de référence orbit-gnss-challenged.toml (un engin spatial à l'intérieur de la couche GNSS avec une couverture intermittente).
  • Extension Python facultative (PyO3, abi3) exposant run, run_full et version, empaquetée avec maturin (pyproject.toml) et construite pour Linux, macOS et Windows par un workflow wheels déclenché par l'étiquette de version. La liaison est une dépendance facultative conditionnée par une fonctionnalité : la construction par défaut, les tests et la porte d'audit des dépendances ne sont pas affectés.
  • Module WebAssembly facultatif (wasm-bindgen) exposant run, chart_svg et version, construit avec wasm-pack sous la fonctionnalité wasm ; getrandom est conditionné par la cible pour utiliser la source d'entropie du navigateur sur wasm32.
  • Répartition api::run_toml partagée utilisée par la CLI et les deux liaisons, de sorte que la ligne de commande et les liaisons ne puissent pas diverger.

Modifié#

  • La notation du holdover tient désormais compte des segments : les chronologies d'interruption sont découpées en segments contigus à chaque réacquisition GNSS, et le holdover indiqué est la marche à l'inertie la plus défavorable (la plus courte) parmi eux. Les scénarios à interruption unique sont inchangés. S'applique aux évaluateurs d'horloge, inertiel et hybride.
  • Le kind indiqué par le modèle inertiel est désormais inertial (il était accelerometer), ce qui reflète les canaux combinés d'accéléromètre et de gyroscope.

0.1.0 - 2026-06-01#

Première version.

Ajouté#

  • Moteur de simulation déterministe pour un PNT hybride quantique/classique : une interface commune de modèles d'erreur, des scénarios déclaratifs de disponibilité GNSS, des estimateurs de holdover / d'estime, et une notation par figures de mérite selon les critères opérationnels PNT standard. Les résultats sont reproductibles à partir de scenario + seed + engine version (JSON versionné et autodescriptif avec un hachage du scénario) et rendus sous forme de graphiques SVG. La CLI répartit les scénarios selon kind.
  • Quatre paquets de capteurs, chacun étalonné sur des données publiées et validé par rapport à la relation standard :
    • Holdover d'horloge : FM blanc, FM à marche aléatoire et vieillissement linéaire ; validé par l'écart-type d'Allan à recouvrement (Riley, NIST SP 1065). Horloge atomique à l'échelle d'une puce contre horloge optique à réseau de strontium.
    • Navigation à l'estime inertielle : biais résiduel + marche aléatoire de vitesse, doublement intégrés en erreur de position ; validée par rapport aux relations de croissance d'erreur de Groves. Accéléromètre à atomes froids contre accéléromètre de qualité navigation.
    • Transfert de temps : gigue de synchronisation temporelle d'une liaison optique contre une liaison RF → précision de synchronisation → télémétrie à sens unique.
    • Fusion hybride (clé de voûte) : une suite PNT combinée qui doit tenir à la fois la synchronisation temporelle et la position, avec une assistance facultative de l'horloge par transfert de temps optique inter-satellites.
  • Un scénario de référence cité par paquet sous scenarios/, chaque paramètre numérique portant une provenance relue par des pairs.
  • Garde-fous de reproductibilité et d'hygiène du dépôt ; CI (format, clippy, tests, garde-fous, MSRV) et une chaîne de publication déclenchée par étiquette qui réexécute tous les contrôles.
  • Documentation : README avec schémas d'architecture, rapport d'état de validation, guide de contribution, politique de sécurité et code de conduite ; licence Apache-2.0 ; modèles de tickets/PR et configuration Dependabot.
  • Neutre vis-à-vis des fournisseurs partout ; les citations scientifiques et métrologiques relues par des pairs sont conservées.
  • Hygiène de licence Apache-2.0 : en-têtes SPDX sur toutes les sources, un fichier NOTICE avec mention de marque, validation par signature du Developer Certificate of Origin (DCO) pour les contributions, et application par cargo-deny des licences/avis des dépendances en CI.
  • Positionnement open-core (README) : un moteur Apache-2.0 gratuit, plus un support commercial, une intégration et des extensions propriétaires disponibles auprès d'Ashforde OÜ, financés par des services et non par des frais de licence.
  • CITATION.cff afin que le logiciel puisse être cité.