Машинный перевод, не проверенный носителем языка. Эталоном служит английская версия.

СценарииПравить на GitHubИсточник: docs/SCHEMA.md

Схема результата — как читать *.result.json Kshana

Каждый прогон записывает рядом со сценарием версионированный самоописывающийся артефакт JSON (JavaScript Object Notation). Эта страница — написанное вручную руководство читателя по конверту обмена и по формам результатов для часов и орбиты: единица каждого поля, где оно вычисляется в исходном коде и как его читать. Канонический тип — RunResult в src/report.rs; показатели качества — FoMScores в src/fom.rs.

Это не полный справочник по полям. Движок диспетчеризует по гораздо большему числу видов, чем эти два, и каждый выдаёт собственный пакет. Полный справочник — единица, класс происхождения и определение для каждого числового поля каждого встроенного вида — формируется, а не пишется вручную: см. ниже Единицы и происхождение для каждого поля каждого вида.

Конверт обмена (KIF, Kshana Interchange Format) — распознавание артефакта и проверка версии#

Артефакты Kshana можно обернуть в нейтральный самоописывающийся конверт обмена, чтобы сторонний инструмент мог распознать файл и решить, может ли он его прочитать, до того, как возьмётся за схему полезной нагрузки. Канонический тип — Envelope в src/interchange.rs.

Ключ Тип Значение
format строка Всегда "kshana-interchange" (FORMAT_TAG) — так сторонний инструмент распознаёт артефакт Kshana.
schema_version строка Версия схемы MAJOR.MINOR (SCHEMA_VERSION, единый источник истины для всего крейта).
kind строка Вид артефакта, например "scenario", "run-result", "trade-study" — позволяет потребителю направлять данные, не разбирая тело.
engine_version строка Версия крейта (Cargo.toml), создавшего полезную нагрузку.
payload объект Обёрнутый артефакт в виде канонического JSON (Scenario, RunResult, …).

Контракт совместимости. Версии имеют вид MAJOR.MINOR. Новые поля добавляются с #[serde(default)] (аддитивная дисциплина), поэтому читатель может разобрать любой артефакт той же основной версии и такой же или более старой дополнительной (Compatible). Строго более новая дополнительная версия (ForwardIncompatible) может содержать поля, которые этот читатель не может учесть, а другая основная версия (MajorIncompatible) — структурный разрыв; оба случая отклоняет Envelope::parse, которая проверяет метку формата и версию на границе, а не молча неверно разбирает чужие входные данные.

Детерминированность. В конверте нет отметки времени — этого требует обещание воспроизводимости Kshana (scenario + seed + engine_version воспроизводит прогон). Происхождение хранится в engine_version и в собственном scenario_hash полезной нагрузки.

Типизированное обратное чтение (Envelope::payload_as::<T>()) работает для любой полезной нагрузки, реализующей Deserialize (например, Scenario). Артефакты результатов по замыслу только сериализуются и читаются как необработанное значение JSON payload.

Верхний уровень (пакеты часов и орбиты)#

Ключ Тип / единица Значение Источник
schema_version строка Версия схемы результата (не зависит от версии движка). report.rs
engine_version строка Версия крейта (Cargo.toml), создавшего файл. report.rs
scenario_hash шестнадцатеричная строка SHA-256 (SHA: Secure Hash Algorithm) по каноническому JSON сценария — прогон воспроизводится по scenario + seed + engine_version. report.rs:hash_scenario
seed u64 Начальное значение ГСЧ (генератора случайных чисел) для квантового прогона (классический использует seed + 0x9e3779b97f4a7c15). run.rs
threshold_ns наносекунды Требование к синхронизации: ошибка в пределах ±threshold_ns «в допуске». сценарий
quantum объект (ClockRun) Прогон квантового датчика (см. ниже). report.rs
classical объект (ClockRun) Прогон классического датчика для сравнения. report.rs
units объект Карта единиц и происхождения каждого поля этого документа по пути поля. См. ниже §Единицы и происхождение. field_schema.rs:units_block
evidence объект (0,40) Метка доказательств прогона: tier (VALIDATED, MODELLED или PARTNER: самый слабый статус среди строк, так что она никогда не заявляет больше, чем самая слабая строка), matrix (docs/VERIFICATION-MATRIX.md), id_rule и rows, по одной на каждую строку матрицы верификации, задействованную прогоном (строки, которые перечисляет его расширенный отчёт, из advanced_report::KIND_CAPABILITIES): id (VM- и первые 8 шестнадцатеричных цифр SHA-256 текста требования строки), requirement и status, всё считывается из матрицы, ничего не вводится вручную. Добавляется функцией api::run_toml к результату каждого вида, перед завершающим блоком figure_tiers, если он есть (этот блок остаётся последним ключом); evidence_label::strip_json удаляет её байт в байт. SVG-диаграмма и CSV-таблица того же прогона несут ту же метку (<metadata id="kshana-evidence"> и видимая строка под диаграммой; строки комментариев # evidence: в начале CSV). Члены кампании, встроенные в результат другого вида, не несут метки: она есть у внешнего документа. Чисел не содержит. evidence_label.rs
figure_tiers объект Уровень верификации каждого указанного показателя качества и всегда последний ключ документа. figures содержит по одной записи на каждый присутствующий показатель: path (например, quantum.fom.timing_p95_ns), tier (VALIDATED = проверено по независимому внешнему оракулу, MODELLED = из первых принципов, внутренне проверено тестами), requirement (строка матрицы верификации, из которой считывается уровень) и applicable. applicable равно false с reason для security в каждом сценарии, где атака не настроена: граница остаётся в fom.security, но не отвечает на вопрос, который задаёт сценарий. untiered перечисляет любые показатели, которыми не владеет ни одна строка матрицы (показатели положения hybrid и fusion), вместо присвоения им уровня. Его выдают виды clock (одиночный прогон и ансамбль Монте-Карло), orbit, hybrid и fusion, которые строят его внутри своего прогона, а также (0,36, RM-04) все остальные виды для своих ключевых показателей, добавляя после прогона из таблицы видов fom_label::kind_figures; api::without_figure_tiers побайтово возвращает документ к виду без уровней. Не выдаётся видом lunar-station-coverage, результат которого — замороженный заранее зарегистрированный прогноз (docs/predictions/lunar-reference-station.md): у этого вида нет figure_tiers, пока новый датированный прогноз не заменит его. Не выдаётся также видами leo-ppp, solar-system, optical-atmosphere (0,37; массивы по пунктам), sweep и sweep-nd, у которых нет скалярного ключевого показателя, видом lunar-attack-surface, документ которого — компактный JSON (fom_label::KINDS_EXCLUDED_FROM_FIGURE_TIERS указывает каждую причину), и встроенными документами участников кампании. Чисел не содержит. fom_label.rs:figure_tiers, fom_label.rs:kind_figure_tiers
geometry объект, необязательный Сводка геометрии пакета орбиты: samples_total, samples_with_fix, sigma_uere_m (м, смоделированный бюджет ошибки дальности для каждого спутника), best_pdop / median_pdop (безразмерные) и best_position_sigma_m / median_position_sigma_m (м, PDOP (геометрический фактор по положению) × sigma_uere_m). Только пакет орбиты. orbit.rs
eci_track массив [x, y, z] км, необязательный Распространённая в земной инерциальной системе траектория пользовательского космического аппарата, по одной записи на каждый выбранный момент времени. Только пакет орбиты; иначе опускается. Только выходные данные — не хешируется. report.rs
meta объект (StudyMeta), необязательный Дополнительные метаданные отчёта (название исследования, отметка формирования, автор, оговорка). Опускаются, когда отсутствуют, поэтому прогон без метаданных побайтово идентичен прежнему выводу. Только выходные данные — не хешируется. report.rs

ClockRun (каждый из quantum / classical)#

Ключ Тип / единица Значение
spec.id строка Идентификатор датчика (например, optical-sr-lattice).
spec.kind строка Вид модели (например, clock).
spec.provenance строка Ссылка на источник параметров датчика.
spec.params объект Использованные исходные параметры модели.
series массив {t, error_ns, gnss} Временной ряд по шагам: t — секунды, error_ns — ошибка времени в наносекундах, gnss — одно из nominal/degraded/denied.
fom объект (FoMScores) Оценённые показатели качества (ниже).
adev_curve массив {tau_s, adev, n_samples, noise, edf, ci_lo, ci_hi} Перекрывающаяся девиация Аллана: tau_s — время усреднения (с), adev — безразмерная стабильность дробной частоты σ_y(τ), n_samples — число перекрытий в основе этой точки, noise — тип степенного закона, определённый по наклону MDEV (модифицированная девиация Аллана) (например, WhiteFm), edf — эффективное число степеней свободы для данного типа шума, а ci_lo/ci_hi — доверительная полоса 95% по χ² для adev при этом τ. Вычисляется в allan.rs:overlapping_adev_curve.
filter_health объект, необязательный Оценка согласованности фильтра Калмана (NIS/NEES (NIS: нормированный квадрат инновации; NEES: нормированный квадрат ошибки оценки) относительно их полос χ²), вычисляется в filter_health.rs; опускается для прогонов, которые её не оценивают.

FoMScores (объект fom)#

Поле Единица Значение Источник Оговорка
timing_rms_ns нс СКЗ (среднеквадратическая) ошибка фазы часов (времени) за время отказа. fom.rs:score метрика времени, а не положения
timing_p95_ns нс 95-й процентиль ошибки времени за время отказа. fom.rs:score
holdover_s s Наихудший (наименьший) выбег в допуске по участкам отказа. fom.rs:worst_case_holdover ограничено сеткой — нижняя граница при разрешении шага по времени
resilience_slope_ns_per_s ns/s Скорость роста |ошибки| за время отказа по методу наименьших квадратов. fom.rs:score
availability доля [0 1] Доля всего прогона с решением в допуске. fom.rs:score
integrity доля [0 1] или null Самосогласованность фильтра: доля отсчётов отказа, в которых истинная ошибка остаётся в пределах границы k-σ фильтра Калмана. run.rs НЕ целостность HPL/VPL/RAIM (HPL: горизонтальный уровень защиты; VPL: вертикальный уровень защиты; RAIM: автономный контроль целостности приёмником) — см. INTEGRITY.md
security доля [0 1] или null Аналитическая граница обнаруживаемости спуфинга по стабильности часов. run.rs + security.rs имеет смысл только при настроенной атаке, поэтому пакеты часов и орбиты (в которых её нет) помечают её applicable: false в figure_tiers и выводят как n/a (no attack) в сводке; это не многоспутниковый детектор RAIM

Как выглядит «хороший» результат#

  • Более стабильные часы (меньше adev_curve) дают более длинный holdover_s и более высокую границу обнаруживаемости security — в этом контраст квантового и классического вариантов.
  • availability, близкое к 1,0, означает, что система оставалась в допуске почти весь прогон; при долгом отказе оно снижается для более шумных часов.
  • integrity, близкое к 1,0, означает, что собственная граница неопределённости фильтра честно отражала его ошибку — это утверждение о самосогласованности, а не гарантия безопасности жизни.

Другие виды сценариев#

Каждый другой вид выдаёт собственную форму результата. Несколько распространённых:

  • inertial: показатели качества в области положения в метрах (pos_rms_m, pos_p95_m) — одноосевые (1-DOF (DOF: степень свободы)), с одним начальным значением (seed) (см. CAPABILITY.md).
  • hybrid / fusion: timing_spec_ns и position_spec_m на верхнем уровне, а для каждой стороны показатели времени и положения одного набора датчиков (position_p95_m, position_holdover_s и pnt_holdover_s — время до нарушения любого из требований), с блоком figure_tiers, как в пакете часов, в котором показатели положения перечислены как untiered.
  • spoof: смещение спуфинга на каждом шаге относительно границы обнаружения часов, а также достигло ли смещение допуска до обнаружения (src/spoof.rs).
  • skyline (orbit и integrity с user_site, gnss-sim, jamming, leo-pvt, leo-pass; присутствует только если в сценарии есть раздел [skyline], поэтому сценарий без него не меняется): объект верхнего уровня skyline с source (строка: preset:<name>, preset:<name>+overrides или custom), open_fraction (доля [0 1] телесного угла верхней полусферы выше max(mask_deg, skyline)) и provenance (строка); для каждого отсчёта masked_by_skyline (число спутников выше маски, но за линией горизонта: epochs[] для integrity и jamming, gnss_measurements[] для gnss-sim, joint.epochs[] для leo-pvt); а для leo-pass — satellites[].pass.epochs_masked_by_skyline (число эпох). Их единицы и классы происхождения указаны в блоке units (src/skyline.rs UNITS; SKYLINE.md).

Точный набор полей любого вида смотрите в его записи в field-units-schema.json (ниже), в разделе этого вида в SCENARIOS.md или в соответствующей структуре *Result в src/.

Другие файлы, которые записывает прогон#

Помимо <scenario>.result.json, CLI (интерфейс командной строки) записывает <scenario>.chart.svg, печатный <scenario>.report.html и тот же отчёт как <scenario>.report.json, блок reproducibility которого фиксирует версию движка, SHA-256 файла сценария, seed, платформу и точную команду (см. REPORTS.md и REPRODUCIBILITY.md). Виды, публикующие таблицу воспроизводимости, также записывают <scenario>.table.csv (CSV: значения, разделённые запятыми). --export записывает файлы обмена (см. INTEROP.md), а --animate — анимацию (см. ANIMATION.md).

Единицы и происхождение для каждого поля каждого вида#

Эта страница написана вручную и охватывает пакеты часов и орбиты. Машиночитаемый аналог охватывает каждый встроенный вид:

  • В самом результате. Документ результата каждого сценария несёт объект units верхнего уровня, сопоставляющий путь выдаваемого поля с {"unit", "provenance", "note"}. Грамматика путей (массив даёт один сегмент с суффиксом [], общий для его строк; * — подстановочный знак одного сегмента для объектов с ключами из данных) и закрытый словарь происхождения определены в src/field_schema.rs.
  • Единым файлом. field-units-schema.json — собранное объединение: для каждого вида каждое числовое поле, которое он выдаёт в заявленном источнике, с его единицей, классом происхождения, уровнем доказательств и определением — а также, с указанием имён, а не с пропуском, каждое поле, у которого этого пока нет. Его блок coverage содержит счётчики.

Оба обеспечивает tests/field_units_global.rs, который запускает каждый зарегистрированный вид и завершается ошибкой, если у выдаваемого числового поля нет единицы и класса происхождения. Виды, ещё не охваченные, названы по отдельности в UNCOVERED_KINDS этого файла с причиной, по которой каждый остаётся открытым, а число закреплено, так что список может только сокращаться.

Сформируйте JSON заново после любого изменения формы отчёта или блока units:

cargo test --test field_units_global zzz_emit_field_units_schema -- --ignored