Перейти к содержанию

CLI sim

Точка входа: консольный скрипт simgeoscan_sim.cli:main (simulate/pyproject.toml:24-25).

cd simulate
uv sync
uv run sim --help

Вывод (2026-09-18, этот worktree):

Usage: sim [OPTIONS] COMMAND [ARGS]...

  Geoscan simulator CLI (`sim`).

Options:
  --help  Show this message and exit.

Commands:
  batch       Run N scenarios × M plans; emit CSV and JSON summaries.
  identities
  mutate
  run
  serve
  validate
  verdict     Tri-state stand verdict for a completed run.

sim run — headless-прогон

Синхронный прогон плана в каталог артефактов (cli/__init__.py:66-159run_plan_headless).

uv run sim run fixtures/plans/s01.json \
  --seed 42 \
  --output /tmp/sim-out \
  --world m0-synthetic-flat
Опция По умолчанию Смысл
--seed 42 Seed сценария
--output simulate-out Каталог журнала
--world m0-synthetic-flat world_snapshot_id
--strict off Зоны без altitude_frame → fatal ZONE_ALT_FRAME_REQUIRED

Успешный выход

В stdout — JSON-сводка путей и хешей (runner.py, эхо в cli/__init__.py:158):

{
  "fact_report": "/tmp/sim-out/fact_report.json",
  "manifest": "/tmp/sim-out/run_manifest.json",
  "telemetry": "/tmp/sim-out/telemetry.jsonl",
  "telemetry_sha256": "e11273715f65affb7987923aeb444d85ded8c8919264af05a2cf446cf4b62371",
  "frames_written": 380,
  "frames_raster_count": 0,
  "preflight_codes": [],
  "world_snapshot_id": "24e205faab997a835132abc87aeaf74d8e2760e528ec35d2c013c277af0c11a3",
  "t_out_of_link_max_s": 0.0
}

Код выхода 0 (SimExit.OK), если после прогона нет кодов preflight (cli/exit_codes.py:30-42).

Ошибки на stdout

При фатальной ошибке контракта CLI печатает одну или несколько строк JSON с полями code, severity, path, message (cli/__init__.py:27-30, structured_error в contracts/loader.py:177-186).

Коды выхода процесса (cli/exit_codes.py:10-14):

Код Имя Когда
0 OK Прогон завершён, нет нарушений preflight
1 FATAL Не читается план, fatal preflight без прогона, UnknownFleetEntityError
2 VIOLATIONS Прогон был, но preflight_codes не пуст
3 INTERNAL Неожиданное исключение движка

Логика «запускать ли симуляцию при preflight»: should_run_with_preflight — violation/warning допускают прогон даже при fatal (exit_codes.py:45-52).


sim serve — HTTP API

uv run sim serve --host 127.0.0.1 --port 8080 --workers 2 --no-auth
Опция Описание
--runs-dir Каталог прогонов (default simulate/data/runs через create_app)
--workers Размер ProcessPoolExecutor (default 2)
--api-key / SIMULATE_API_KEY Ключ для /api/*
--no-auth Без проверки ключа (dev)

Нельзя одновременно --no-auth и --api-key (cli/__init__.py:197-198).

Подробности ручек — http-api.md.


sim validate — эталонная таблица

Без флагов команда завершается с кодом 2 и подсказкой использовать --reference (cli/__init__.py:42-47).

uv run sim validate --reference

Печатает таблицу V-1…V-14 и выходит с кодом из reference_exit_code(rows) (validator/runner.py).


sim mutate — матрица мутантов

uv run sim mutate --set base

Выводит матрицу обнаружения мутантов; код 0, если все мутанты детектированы и базовый план s01 не даёт ложного срабатывания (cli/__init__.py:53-63).


sim identities — алгебраические тождества

uv run sim identities

Строки name: PASS|FAIL (detail); код 1, если хотя бы один FAIL (cli/__init__.py:220-227).


sim batch — пакет сценариев × планов

Последовательный прогон пар «сценарий + план» из двух каталогов; на выходе batch.csv и batch.json (cli/__init__.py:233-295batch/runner.py).

uv run sim batch --help
Опция Обязательна Смысл
--scenarios да Каталог манифестов сценариев (s01.json …)
--plans да Каталог планов, сопоставление по scenario_id
--seed нет (default 42) Seed для всех заданий пакета
--output нет (default batch-out) Корень артефактов прогонов
--report-dir нет Куда писать отчёты (default = --output)

В stdout — JSON с путями к отчётам и числом заданий. Коды выхода:

Код Когда
0 Все задания пакета завершились с exit_code == 0
1 Хотя бы одно задание с ненулевым exit_code
2 ValueError (некорректные каталоги, несопоставимые пары)

Пула воркеров и checkpoint/resume в пакете нет — см. LIMITATIONS.md.


sim verdict — вердикт по завершённому прогону

Читает артефакты каталога прогона (или runs-dir + UUID) и печатает тот же payload, что GET /api/v1/runs/{id}/verdict (cli/__init__.py:298-328verdict.compute_verdict).

uv run sim verdict --run /tmp/sim-out --json
Опция Смысл
--run UUID прогона или путь к каталогу с run_manifest.json
--runs-dir База для API-прогонов (simulate/data/runs), если --run — id
--json Полный JSON вместо краткой строки вердикта

Код выхода процесса всегда 0 (включая «прогон не найден» — тогда в JSON блокер RUN_NOT_FOUND). Трёхзначный NO_GO / NO_FINDINGS при низкой полноте слоёв не выдаётся: типичный ответ UNRESOLVED + LAYER_COMPLETENESS_LOW, как в http-api.md.

Регистрация подкоманд проверяется в tests/defects/test_b6_stand.py::test_sim_batch_subcommand_registered и test_sim_verdict_subcommand_emits_tri_state.


Сравнение CLI и HTTP

Задача CLI HTTP
Один прогон в каталог sim run POST /runs + poll + скачать JSONL ручками
Пакет N×M сценариев/планов sim batch --scenarios … --plans … нет одной ручки (серия POST /runs)
Вердикт прогона sim verdict --run <uuid или каталог> GET /api/v1/runs/{id}/verdict
Preflight без движка нет отдельной команды POST /preflight
Справочник V-1…V-14 sim validate --reference GET /reference
Каталог fleet/worlds нет GET /fleet, GET /worlds
Метрики Prometheus нет GET /metrics

Для CI и интеграции с планировщиком обычно: HTTP для оркестрации, CLI для локальной отладки и воспроизводимых артефактов в каталоге.