Решили: читать bundleVersion только с якорем на начало строки (^\s*bundleVersion:) и добавить в steam-publish.ps1 отказ, когда bundleVersion и старший тег v* разошлись.

Почему: обе дороги выкладки — локальный скрипт и steam-deploy.yml — искали строку без якоря, и первым совпадением шёл visionOSBundleVersion: 1.0 двумя строками выше. VisionOS мы не собираем, и число там не меняется никогда, поэтому в Steam уезжали сборки 1.0-dev.<sha>, пока ProjectSettings держал 0.1.0. Ошибка молчаливая по построению: подставленная версия выглядит правдоподобно, а сверить её не с чем — обе стороны читают одну и ту же кривую строку.

Гейт расхождения — механический, а не «правило в голове»: то же рассуждение, по которому владельцем версии релиза вообще стал тег (2026-08-02-the-tag-names-the-version-so-nobody-has-to-remember). Обойти можно явным -Version, потому что аварийная выкладка не должна упираться в номер.

Грабли: диагноз выглядел как «забыли поднять версию» и «тег назначает номер, а тегов не ставили» — в этом даже была своя правда (теги стояли на v0.0.3 при bundleVersion 0.1.0). Настоящая причина нашлась только потому, что при написании гейта я напечатала прочитанное значение и увидела 1.0 там, где на диске лежит 0.1.0. Вывод общий: скрипт, который что-то ВЫЧИТЫВАЕТ из чужого формата, обязан это прочитанное печатать — иначе ошибка чтения неотличима от ошибки человека.

Владелец правды: scripts/steam-publish.ps1 (секция «Версия: владелец — тег»), .github/workflows/steam-deploy.yml (шаг Version).