Repository navigation
MuMuManager CLI Menu v1.21.3
MuMuManager CLI Menu v1.21.3
Интерактивное PowerShell-меню для управления MuMu Emulator через MuMuManager.exe.
Что нового
v1.21.3 (15.09.2026)
- Экспорт журнала
[J](issue #23) — новый пункт[J] -> 5 Exportзаписывает выбранные события в Markdown (таблица для issue, экранирование|), RFC-4180 CSV (заголовок + кавычки для ячеек с запятой/кавычкой/переводом строки) или JSON (объект верхнего уровняgenerator/count/events, поля без изменений). Формат → диапазон (последние 20 / весь / только ошибки, как в просмотре) → путь (Enter =update-journal-YYYYMMDD-HHMMSS.<ext>рядом с журналом). Вывод — UTF-8 с BOM (правило #535), сам журнал не изменяется, повторные экспорты байт-в-байт идентичны - JSON — объект верхнего уровня, а не голый массив: массивы верхнего уровня по-разному парсятся в некоторых потребителях PowerShell 5.1 (проверено живьём — python видел 3 элемента, а pipeline-форма 5.1 оборачивала массив); свойство объекта парсится единообразно в PS 5.1/7, jq и Python. JSON — компактная одна строка; MD/CSV — человеко-форматы
- Тесты: 6 golden-тестов (заголовок/экранирование MD, кавычки CSV, round-trip JSON, BOM + идемпотентность + неприкосновенность журнала, диапазон «только ошибки», ошибка неизвестного формата); набор 54 зелёный на PowerShell 5.1 и pwsh 7
v1.21.2 (15.09.2026)
- Сингл-флайт блокировка обновлений (issue #24) —
[U]иbootstrap-update.ps1перед изменением файлов установки захватывают.update-lock(PID + timestamp) атомарнымCreateNew: два параллельных обновлятора (меню в двух окнах, меню + bootstrap) больше не могут повредить.version/скрипты/журнал или применить обновление дважды. Отказ печатает PID держателя и возраст блокировки, пишет в журналupdate-skippedи выходит, ничего не меняя. Блокировка старше 10 минут считается остатком упавшего процесса и безопасно ломается (create-then-break через.update-lock.newзакрывает гонку break/recreate). Снимается вfinally, включая Ctrl+C [J]:update-skippedподсвечивается жёлтым (пропуск — не ошибка), сообщение «ошибок нет» считает пропуски успешными событиями- Тесты: 6 новых Pester-тестов + блок T10 в bootstrap-регрессионном наборе (включая межскриптовые проверки проводки); набор 48 зелёный; проверено живьём (отказ в одном процессе, кросс-процессный отказ через дочерний PowerShell, stale-break, повторный захват после снятия)
v1.21.1 (15.09.2026)
- Fix регрессии v1.21.0 в
[F]: пин тега перезаписывал$TagSHA-коммитом — семантическое сравнение.versionотключалось, и здоровый маркер давал ложный DRIFT на каждой проверке (поймано живьём на установке сразу после релиза v1.21.0). Теперь$Tagостаётся читаемым тегом для семантического сравнения, а фетчи контента идут через отдельный закреплённый$FetchRef; добавлен Pester-страж, проверяющий это разделение
v1.21.0 (15.09.2026)
[U]/[F]/лечение: закрепление тега за коммитом (issue #22) — все фетчи содержимого?ref=<тег>переписываются на?ref=<sha-коммита>: contents API резолвит ссылку в момент запроса, поэтому CDN-граница может отдать блоб предыдущего коммита минуты после пуша тега (класс багов v1.20.3–v1.20.6); SHA-коммит неизменяем — устаревшее чтение невозможно по построению. Если резолв не удался — проверка идёт по обычному URL тега- ETag-кеш с replay 304 в
Invoke-GitHubGet— повторные фетчи того же URL в одной сессии меню отправляютIf-None-Matchи на304 Not Modifiedвозвращают кешированное тело без передачи; кешируются только реальные тела (не ошибки API) bootstrap-update.ps1: тот же пин тега → SHA — в получении эталонных хешей и в цикле загрузки; резерв — верификация SHA-256 каждого скачанного файла- Исправлено мёртвое лечение
[U]: блок version-fix ссылался на не присвоенные$localText/$remoteText— лечение не могло сработать; теперь локальный текст читается, а фетч закрепляется за коммитом тега - Откат идеи «дешёвых хешей»: media type
application/vnd.github.shaне поддерживается contents API (проверено живьём) — эталонные хеши по-прежнему считаются из тела; повторные фетчи дешевле за счёт ETag-кеша
v1.20.6 (15.09.2026)
- Полировка журнала
[J]: пустое полеfromрендерится как(new) -> vX.Y.Z(событие на свежей установке без маркера), а события одного запуска (одинаковые timestamp+actor, напримерupdate-ok+updater-refresh) группируются — продолжение печатается с ASCII-меткой-вместо повторной строки timestamp/actor; глифы боксов не используются (не входят в OEM-кодировки консоли)
v1.20.5 (15.09.2026)
- Fix «лечения» маркера
.versionпри запуске: контент, полученный с CDN-границы GitHub, должен сам заявлятьscriptVerтега, иначе лечение отменяется — устаревший блоб предыдущего релиза перестаёт поднимать маркер до тега, чей контент не пришёл (живой случай на v1.20.4: установка «залипла» на «Up to date» с контентом v1.20.3 и маркером v1.20.4; лечение[U]/[F]при расхождении контента остаётся прежним)
v1.20.4 (15.09.2026)
[F]: маркер.versionсравнивается семантически — локальный маркер, равный или более новый, чем отстающий маркер тега (бот синхронизации версий приземляется после тега), больше не даёт ложный DRIFT (поймано живьём на v1.20.3)[F]: один повторный запрос перед вердиктом DRIFT — CDN-граница GitHub может отдать устаревший блоб минуты после пуша тега (живой случай:bootstrap-update.ps1был байт-идентичен тегу, а фетч вернул старое содержимое); настоящий дрейф по-прежнему остаётся дрейфом[F]→ проверка ZIP: отсутствующий файл — это не подмена — «No ZIP found … nothing to verify» вместо пугающего «FAILED - do not install»
v1.20.3 (15.09.2026)
- Fix пост-проверки хешей bootstrap (v1.20.2): эталонное содержимое тега получалось через
cmd /c-захват вывода curl, который декодирует в консольной OEM-кодировке — кириллица в README/SKILL.md искажалась, и каждый файл давал ложныйHASH MISMATCH(поймано живым прогоном; защита сработала как задумано — обновление было остановлено). Эталоны теперь считаются через байт-точный raw-фетч (curl → temp-файл → UTF-8), как в меню; регресс-тест T9 проверяет не-ASCII тело
v1.20.2 (15.09.2026)
Warning
В bootstrap этого релиза есть баг пост-проверки хешей (OEM-кодировка искажает эталонные SHA-256) — каждый файл даёт ложный HASH MISMATCH. Fail-closed, вреда нет; исправлено в v1.20.3. Если вы на v1.20.2: bootstrap-update.ps1 -NoVerify один раз.
- Пост-проверка хешей в
bootstrap-update.ps1(паритет с[U]): после загрузки каждый файл сверяется с ожидаемой SHA-256 из содержимого тега —OK (hash OK)/HASH MISMATCH; расхождение останавливает обновление (.versionне двигается, самоприменение обновлятора отменяется, событиеupdate-failв журнале) - Тот же hashing-контракт, что и в меню (CR/BOM/симметричный TrimEnd) — вынесено в
Get-ContentHash/Get-ExpectedHashes; JSON-ошибки API (rate limit) никогда не принимаются за эталон - Опция
-NoVerifyдля отключения; при недоступности хешей обновление продолжается с пометкойunverifiedв журнале - Регресс-тест T9: векторы SHA-256, симметричный TrimEnd, пропуск rate-limit JSON, wiring
-NoVerify
v1.20.1 (15.09.2026)
- Fix post-download hash-проверки
[U](v1.20.0): локальная сторона сверялась без TrimEnd, тогда как ожидаемые хеши считались от TrimEnd-нутого ответа API — любой файл с переводом строки на конце давал ложныйHASH MISMATCHи отменял легитимное обновление. TrimEnd перенесён внутрьGet-ContentHash, все потребители симметричны по построению; регресс-тест в Pester-сьюте
v1.20.0 (15.09.2026)
- Прозрачность обновления (issue #17): подтверждение
[U]показывает таблицу ожидаемых SHA-256 всех 5 файлов (из VT-вердиктов релиза), а после загрузки каждый файл сверяется со своей ожидаемой суммой — расхождение останавливает установку до распаковки - Pester-покрытие хелперов (issue #20):
tests/mumu-menu.Tests.ps1— 26+ юнит-тестов чистых функций (Get-ContentHash,Test-InstallationIntegrity,Test-ReleaseZip,ConvertTo-ShellSafe,Compare-ScriptVersion,Format-JournalEvent); отдельный jobpester-unitв CI (tests.yml) - Новый раннер
tests/run-pester.ps1для локальных запусков на PS 5.1 (неинтерактивная установка Pester 5.x)
v1.19.6 (15.09.2026)
Сравнение
| Предыдущая версия | v1.21.2 |
| Текущая версия | v1.21.3 |
| Коммитов | 2 |
Коммиты
599c1ce feat(journal): [J] export to MD/CSV/JSON (issue #23)
a9de442 chore: auto-sync .version v1.21.1 -> v1.21.2
Установка
Быстрый запуск (одна команда):
irm https://raw.githubusercontent.com/genrihx2/MuMuManager-CLI-Menu/main/mumu-menu.ps1 -OutFile $env:TEMP\mumu-menu.ps1; & $env:TEMP\mumu-menu.ps1Git clone (с автообновлением через [U]):
git clone https://github.com/genrihx2/MuMuManager-CLI-Menu.git
cd MuMuManager-CLI-Menu
.\mumu-menu.ps1Верификация
curl -sL https://github.com/genrihx2/MuMuManager-CLI-Menu/releases/download/v1.21.3/MuMuManager-CLI-Menu-v1.21.3.zip.sha256 -o MuMuManager-CLI-Menu-v1.21.3.zip.sha256
Get-FileHash MuMuManager-CLI-Menu-v1.21.3.zip -Algorithm SHA256 | Select -Expand Hash
# Сравнить с содержимым MuMuManager-CLI-Menu-v1.21.3.zip.sha256Метрики
| Размер ZIP | 102 KB |
| Файлов | 5 |
| SHA256 | 448d033501b3ef2c... |
Требования: Windows 10/11 · PowerShell 5.1+ · MuMu Emulator 6.x
VirusTotal verdicts
| File | SHA-256 | Malicious | Suspicious | Harmless | Report |
|---|---|---|---|---|---|
MuMuManager-CLI-Menu-v1.21.3.zip |
448d033501b3ef2c1f30f56be3b77e637859e9452e7b668c71674fe871cf9d13 |
0 | 0 | 0 | report |
mumu-menu.ps1 (from ZIP) |
03e63aa14d0fa1257211c73242e1dfb52731cd351ce68abb7aa1d5ae8dedcb28 |
0 | 0 | 0 | report |
SKILL.md (from ZIP) |
28fbc26d4ee36bcae0fca6380d80d51986225ad21cffc1ebd1fdabd16c0dc44c |
0 | 0 | 0 | report |
Status: CLEAN - 0 malicious / 0 suspicious (CI scan 2026-09-15, scan run)
Verify the download yourself
sha256sum -c MuMuManager-CLI-Menu-v1.21.3.zip.sha256