CLI sim¶
Точка входа: консольный скрипт sim → geoscan_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-159 → run_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-295 → batch/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-328 → verdict.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 для локальной отладки и воспроизводимых артефактов в каталоге.