github Leadaxe/singbox-launcher v0.8.8.3
release v0.8.8.3

5 hours ago

Release v0.8.8.3

Downloads

macOS (Universal) - Supports both Apple Silicon and Intel

Option 1: Installation Script (Recommended)

Install with a single command (version v0.8.8.3):

curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v0.8.8.3

The script will:

  • Download the release archive
  • Extract and install to /Applications/
  • Fix macOS quarantine attributes and permissions
  • Launch the application automatically

Option 2: Manual Installation

  1. Download: singbox-launcher-v0.8.8.3-macos.zip
  2. Extract the ZIP file
  3. Remove quarantine attribute (required):
    xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
  4. Double-click singbox-launcher.app to run
    • If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
    • Alternatively, right-click the app and select "Open" (first time only)

Windows (amd64)

  1. Download: singbox-launcher-v0.8.8.3-win64.zip
  2. Extract the ZIP file to a folder, for example: C:\Program Files\singbox-launcher\
  3. Run singbox-launcher.exe from that folder
    • You may need administrator rights to install to Program Files
    • The launcher will automatically download sing-box and wintun.dll on first launch

Windows 7 (x86, legacy)

  1. Download: singbox-launcher-v0.8.8.3-win7-32.zip
  2. Extract the ZIP file to a folder and run singbox-launcher-win7-32.exe
    • For Windows 7 / 32-bit or legacy compatibility only

Linux Support

⚠️ Linux build temporarily unavailable - мы ищем тестировщика для ручного тестирования перед включением автоматической сборки.

Checksums

See checksums.txt for SHA256 checksums of all files.

What's New from 0.8.6

Version 0.8.8.3 Release Notes — Cumulative

This document rolls up everything that landed since v0.8.6 — across v0.8.7, v0.8.8, v0.8.8.1 (hotfix), and v0.8.8.3 (hotfix follow-up). Inline tags [v0.8.7] / [v0.8.8] / [v0.8.8.1] / [v0.8.8.3] mark which sub-release introduced or changed each item.

Note: version v0.8.8.2 was used internally during work on the v0.8.8.3 hotfix and never reached a published release — the third override-loader bug (wrong JSON key) was surfaced on review before the tag was created. v0.8.8.3 is the first follow-up published after v0.8.8.1.

Version timeline at a glance

Version Theme
v0.8.7 Big release: Debug API, Settings tab, subscription source toggle, atomic writes, keyboard shortcuts, Linux/Windows wake-from-sleep, URLTest as template vars
v0.8.8 NaïveProxy support, macOS wake-from-sleep, honest Update toast, shortcut tooltips, URLTest object-form fix
v0.8.8.1 Hotfix: @urltest_* placeholders no longer leak into config.json (sing-box couldn't start on fresh installs)
v0.8.8.3 Hotfix follow-up: Settings-tab user override now actually applies; path invariants consolidated

EN

Highlights

  • NaïveProxy (naive+https:// / naive+quic://) support in subscription parser and share-URI encoder. [v0.8.8] Parses user/pass, extra-headers, and QUIC vs HTTP/2 transport per the de-facto DuckSoft URI spec; emits sing-box "type": "naive" outbound with TLS block limited to server_name. padding= URI param is logged and ignored. Right-click → Copy link round-trips back to a valid URI (extra-headers keys sorted lexicographically). Requires sing-box ≥ 1.13.0 built with with_naive_proxy. See SPEC 044.

  • Debug API (localhost-only). [v0.8.7] Optional HTTP server on 127.0.0.1:9269. Off by default. Read endpoints /ping, /version, /state, /proxies; action endpoints /action/{start,stop,update-subs,ping-all} (POST-only). Bearer-token auth (32-byte crypto/rand, constant-time compare). Toggle + "Copy token" button on the Diagnostics tab. Listener strictly 127.0.0.1. Primary use-case: backing service for MCP wrappers so AI agents (Claude / Cursor / etc.) can read and drive the launcher. See SPEC 038.

  • New ⚙️ Settings tab between Servers and Diagnostics. [v0.8.7] Consolidates launcher-wide preferences: language selector + "Download locales" (moved from Help), Auto-update subscriptions, Auto-ping on connect. Fixes a latent data-loss bug in the old language handler — previously SaveSettings({Lang: code}) wiped every other settings field. See SPEC 039.

  • Subscription source toggle. [v0.8.7] Per-row on/off in Wizard → Sources. Disabled sources are skipped by the parser (no fetch, no parse) but stay in the file. ProxySource.Disabled with omitempty keeps legacy configs compatible. See SPEC 037.

  • Auto-ping after VPN connect (default ON). [v0.8.7] 5 seconds after sing-box enters running state, the Servers tab auto-pings all proxies. Cancelled if you stop sing-box inside the window. Persisted as auto_ping_after_connect_disabled in settings.json.

  • Subscription auto-update global toggle (default ON). [v0.8.7] Off skips all scheduled refreshes; manual Update always works. Re-enabling from UI also resets the consecutive-failure counter.

  • URLTest parameters as template vars. [v0.8.7] auto-proxy-out.url / interval / tolerance hoisted to @urltest_url / @urltest_interval / @urltest_tolerance; editable in Wizard → Settings. Object-form options (with display titles distinct from values) added. See SPEC 040. (See Fixed section for the substitution-related hotfixes that followed.)

  • Keyboard shortcuts. [v0.8.7] Cmd/Ctrl+R reconnect, Cmd/Ctrl+U update subscriptions, Cmd/Ctrl+P ping-all. Modifier resolves automatically per platform. Tooltips on Update / Restart buttons (hover shows the shortcut symbol) added in [v0.8.8]. See SPEC 042.

  • Wake-from-sleep re-sync — closes SPEC 011 on all platforms. After resume the launcher resets the Clash API HTTP transport, refreshes the proxies list, and re-pings nodes if auto-ping is on.

    • [v0.8.7] Windows + Linux. Linux uses systemd-logind PrepareForSleep over system DBus (no new dependencies); on systems without logind the listener silently no-ops.
    • [v0.8.8] macOS. New internal/platform/power_darwin.go registers with IOKit via IORegisterForSystemPower; CFRunLoop runs on a runtime.LockOSThread-pinned goroutine. Sleep transitions auto-acknowledged via IOAllowPowerChange so the system doesn't stall.
  • Atomic writes for config.json and settings.json. [v0.8.7] Stage to .tmp / .swap then atomic os.Rename — a crash, kill -9, or power loss mid-write can no longer truncate your live config. Wizard keeps its existing .bak for manual recovery. See SPEC 041.

Added — Resilience & observability

  • 100 MB download cap on sing-box core downloads. [v0.8.7] Pre-flight Content-Length check + mid-stream cumulative counter. Legitimate sing-box archives are < 20 MB.
  • HTTP status humanization in subscription-fetch errors. [v0.8.7] 401 → "unauthorized — token may have expired", 403 → "forbidden — provider blocked", 404 / 410 / 429 / 5xx each with a hint.
  • "(subs: Xh ago)" freshness hint next to config.json on Core Dashboard. [v0.8.7] How long since the last successful subscription update. Session-scoped.
  • Dirty-config marker (*) on Update button when wizard saved changes the parser hasn't applied. [v0.8.7] See SPEC 043. Current implementation is minimal — fires on any wizard save; semantic split tracked in SPEC 045.
  • Per-source counts in the Update toast. [v0.8.8] When at least one source returned an error or zero nodes, the toast reads Config updated: 2/3 source(s) succeeded (1 failed) instead of a blanket "successfully". Silent-empty is treated as failure.

Added — Security hygiene

  • Clash API token redaction in debug logs. [v0.8.7] LoadClashAPIConfig used to log the full bearer token on every start; now logs token=ab***89. Token still visible in Settings UI via Copy button. Pasting debug logs no longer leaks the secret.

Fixed

  • @urltest_* placeholders no longer leak into config.json. [v0.8.8.1] v0.8.7's SPEC 040 introduced template variables @urltest_url / @urltest_interval / @urltest_tolerance in the auto-proxy-out URLTest selector — but the parser code path that copies these options into the final config.json never ran the substitution. sing-box failed outbounds[1].interval: time: invalid duration "@urltest_interval". Fresh installs of v0.8.7 / v0.8.8 couldn't start at all. Fix: core/config/SubstituteParserConfigPlaceholders is invoked at the entry of GenerateOutboundsFromParserConfig, walks all option maps under parser_config.outbounds[] and parser_config.proxies[].outbounds[], replaces @varname strings via a 3-level resolver (state-override → template default → hard-coded fallback). Existing broken state.json files are healed transparently — no manual action required.

  • @varname Settings-tab override now actually applies. [v0.8.8.3] v0.8.8.1's BuildVarSubstituterFromDisk had three independent bugs in the override branch (loadStateSettingsVars) that together silently dropped user overrides — urltest_interval = 1m set in the UI never made it into the generated config. The other two resolution levels (template default_value, hard-coded fallback) were intact, so sing-box still got valid values; users who didn't customize URLTest saw no breakage. But anyone who did customize quietly got the template default. The three bugs:

    1. Wrong file path. v0.8.8.1 looked at bin/state.json; actual path is bin/wizard_states/state.json.
    2. Wrong JSON shape. The list was decoded as map[string]string; on disk it's [{name, value}, ...].
    3. Wrong JSON key. The block was looked up under "settings_vars" / "SettingsVars"; the wizard writes it under "vars" (see WizardStateFile.Vars with json:"vars" in ui/wizard/models/wizard_state_file.go).

    See SPEC 048 for the full retrospective.

  • Wizard template object-form options no longer corrupts substituted values. [v0.8.8] Previously, type: "text" + object-form options rendered as a free-text combo widget. Picking "5m (default)" for urltest_interval ended up writing "interval": "5m (default)" instead of "5m", and sing-box rejected the config. Fix: at JSON-unmarshal time, any options element in object form forces Type = "enum" regardless of the declared type. Strict dropdowns can't be typed into. Legacy plain-string options (["a","b"]) are unaffected.

  • STUN settings dialog clipping on Windows (issue #54). [v0.8.7] Auto-size collapsed the URL entry below placeholder width. Dialog now explicitly sized to ≥ 520 px.

  • CI red since 2026-04-16. [v0.8.7] internal/locale.TestAllKeysPresent was failing because commit 2f77bf7 added 4 new English context-menu keys without Russian counterparts. Parity restored.

Changed — Template defaults

  • Russian & Cyrillic TLDs expanded in ru-domains. [v0.8.7] Was .ru / .xn--p1ai / .su. Added .рус / .москва / moscow / tatar / .дети / .сайт / .орг / .ком.

  • URLTest vars in bin/wizard_template.json rewired. [v0.8.8] urltest_url keeps type: "text" with plain-string URL options (combo with editable presets). urltest_interval and urltest_tolerance now explicitly type: "enum" with object-form {title, value} (strict dropdowns showing "5m (default)" / "100 ms (twitchy)" labels).

Technical / Internal

  • StateService extensions. [v0.8.7] AutoPingAfterConnect, TemplateDirty, LastUpdateError / LastUpdateErrorAt / LastUpdateSucceededAt.
  • ProxySource.Disabled bool json:"disabled,omitempty". [v0.8.7] Omit-default preserves legacy configs.
  • OutboundGenerationResult counters populated. [v0.8.8] TotalSources / SucceededSources / FailedSources filled by GenerateOutboundsFromParserConfig. UpdateConfigFromSubscriptions returns (*OutboundGenerationResult, error).
  • TemplateVar custom UnmarshalJSON. [v0.8.7] Three JSON forms for options. [v0.8.8] Object-form auto-degrades to type: "enum" regardless of declared type.
  • New package core/debugapi/. [v0.8.7] Isolated HTTP surface with narrow ControllerFacade. Adapter debugAPIFacade in core/debugapi_wiring.go.
  • internal/platform/power_linux.go. [v0.8.7] New file. [v0.8.8] power_darwin.go added. power_stub.go build tag tightened.
  • CI: per-version release-notes file required. [v0.8.8] Release job now reads docs/release_notes/<slug>.md. If missing, workflow fails before creating the release. Prereleases get an automatic > ⚠️ Pre-release build banner.
  • New runbook docs/RELEASE_PROCESS.md. [v0.8.8] Canonical procedure for stable and prerelease cuts. Linked from AGENTS.md.
  • FallbackVersion bumped 1.13.6 → 1.13.11 in core/core_version.go. [v0.8.8]
  • SPEC groundwork for v0.9.x. [v0.8.8] Two planning artifacts without code changes:
    • SPEC 045 — State / Config Decoupling. Split Wizard Save (writes state.json only) from Build Config (writes config.json from state + outbounds cache), modelled after the LxBox mobile client.
    • SPEC 046 — Pinned Core and Template. Pin a specific sing-box version and wizard_template.json commit per launcher version.
  • core/config/varsubst.go. [v0.8.8.1] Self-contained — no new dependencies, no UI imports. VarSubstituter type, SubstituteParserConfigPlaceholders, BuildVarSubstituterFromDisk, hard-coded fallback table for the three URLTest placeholders. Hooked into both wizard preview/save and parser auto-update paths.
  • Path invariants consolidated. [v0.8.8.3] internal/constants/constants.go gains WizardTemplateFileName, WizardStateFileName, WizardStatesDirName. internal/platform/platform_common.go gains GetWizardTemplatePath(execDir), GetWizardStatesDir(execDir), GetWizardStatePath(execDir). Code that needs to locate these files MUST go through them — no more hand-rolling filepath.Join(execDir, "bin", "wizard_states", "state.json") per call site.
  • Real-fixture canary test. [v0.8.8.3] core/config/testdata/state-real.json captured from an actual install; TestBuildVarSubstituterFromDisk_RealFixture asserts overrides apply via the real on-disk schema. If the JSON tag breaks again, this test fails loudly.
  • SPEC 048 — PARSER_CONFIG_VAR_SUBSTITUTION (retrospective). [v0.8.8.3] Documents the v0.8.8.1 hotfix architecture, the three bugs in the override loader, the path-invariant refactor, and process lessons.

Migration notes

  • bin/settings.json gains subscription_auto_update_disabled, auto_ping_after_connect_disabled, debug_api_enabled, debug_api_token, debug_api_port. [v0.8.7] Missing fields = zero (enabled / empty / 9269), so existing installs behave as before until you toggle.
  • wizard_template.jsonauto-proxy-out options now reference @urltest_url / @urltest_interval / @urltest_tolerance. [v0.8.7] Custom templates: either merge the three new vars definitions, or keep your literal values (both forms work after v0.8.8.1).
  • Custom wizard_template.json files using type: "text" + object-form options: [{title, value}] are silently normalized to type: "enum" at load. [v0.8.8] Want a free-text combo with presets — switch options to plain strings.
  • Language selector moved from Help to the new Settings tab. [v0.8.7]
  • Existing broken state.json files (v0.8.7 / v0.8.8 fresh installs) heal automatically on first wizard save under v0.8.8.1+. No manual intervention required.

Known issues / deferred for redesign

These items are not in 0.8.8.3 and are tracked for v0.9+:

  • State / Config decoupling (SPEC 045) — dirty marker on Update is still semantically smeared (fires on any wizard save, not just source-list edits).
  • Auto-update event-driven model — the polling loop in core/auto_update.go is still the old "wake every minute, check timestamp" pattern. Documented redesign: typed triggers through a single dispatcher.
  • Right-click context menu on the Update buttonSecondaryTapWrap doesn't route secondary taps into widget.Button; needs a custom RightClickableButton.
  • Last-auto-update failure pill on Core Dashboard — wired but not visible in practice; layout / flag-path diagnosis pending.
  • Ping-all button cancel — current design fully disables the button during a run; click-to-cancel redesign tracked.
  • Pinned core + template (SPEC 046) — currently fetches latest sing-box and HEAD of wizard_template.json. Pinning eliminates floating drift.

RU

Основное

  • Поддержка NaïveProxy (naive+https:// / naive+quic://) в парсере подписок и share-URI энкодере. [v0.8.8] Парсятся user/pass, extra-headers, выбор транспорта (HTTP/2 vs QUIC) по де-факто спеке DuckSoft; собирается sing-box outbound "type": "naive" с TLS-блоком только server_name. Параметр padding= логируется и игнорируется. ПКМ → «Copy link» корректно round-trip-ит обратно в валидный URI. Требует sing-box ≥ 1.13.0 со сборкой with_naive_proxy. См. SPEC 044.

  • Debug API (только localhost). [v0.8.7] Опциональный HTTP-сервер на 127.0.0.1:9269. По умолчанию выключен. Read-эндпоинты /ping, /version, /state, /proxies; action-эндпоинты /action/{start,stop,update-subs,ping-all} (только POST). Bearer-токен (32 байта crypto/rand, constant-time compare). Чекбокс + «Копировать токен» на вкладке Диагностика. Listener строго 127.0.0.1. Основной use-case — backing-service для MCP-обёрток, чтобы AI-агенты (Claude / Cursor / …) могли читать и дёргать лаунчер. См. SPEC 038.

  • Новая вкладка ⚙️ «Настройки» между Servers и Diagnostics. [v0.8.7] Собирает launcher-wide preferences: селектор языка + «Скачать переводы» (перенесены из Help), автообновление подписок, автопинг после подключения. Попутно починен data-loss баг старого language-handler-а — раньше SaveSettings({Lang: code}) затирал все остальные поля. См. SPEC 039.

  • Переключатель подписки в Wizard → Sources. [v0.8.7] Чекбокс в каждой строке. Отключённые источники полностью пропускаются парсером (no fetch, no parse), но остаются в файле. ProxySource.Disabled с omitempty — legacy-конфиги совместимы. См. SPEC 037.

  • Автопинг после подключения VPN (по умолчанию ВКЛ). [v0.8.7] Через 5 секунд после перехода sing-box в running вкладка Servers авто-пингует все прокси. Отменяется при остановке sing-box внутри окна. Сохраняется в auto_ping_after_connect_disabled.

  • Глобальный выключатель автообновления подписок (по умолчанию ВКЛ). [v0.8.7] OFF пропускает плановые обновления; ручной Update всегда работает. Включение через UI сбрасывает счётчик последовательных ошибок.

  • Параметры URLTest как шаблонные vars. [v0.8.7] auto-proxy-out.url / interval / tolerance вынесены в @urltest_url / @urltest_interval / @urltest_tolerance; редактируются в Wizard → Settings. Object-форма options (с подписями, отличными от значений) добавлена. См. SPEC 040. (См. секцию «Исправлено» — там описаны связанные хотфиксы.)

  • Горячие клавиши. [v0.8.7] Cmd/Ctrl+R reconnect, Cmd/Ctrl+U update подписок, Cmd/Ctrl+P ping-all. Модификатор маппится на платформу автоматически. [v0.8.8] Tooltip-подсказки на кнопках Update / Restart показывают шорткат при наведении. См. SPEC 042.

  • Wake-from-sleep re-sync — закрывает SPEC 011 на всех платформах. После резюма лаунчер сбрасывает HTTP-транспорт Clash API, перечитывает список прокси и re-пингует ноды (если включён автопинг).

    • [v0.8.7] Windows + Linux. Linux — нативно через systemd-logind PrepareForSleep по system DBus (новых зависимостей нет); на системах без logind listener молча no-op-ит.
    • [v0.8.8] macOS. Новый internal/platform/power_darwin.go регистрируется в IOKit через IORegisterForSystemPower; CFRunLoop крутится на goroutine с runtime.LockOSThread. Sleep-транзишены авто-подтверждаются IOAllowPowerChange, чтобы система не залипала.
  • Атомарные записи config.json и settings.json. [v0.8.7] Сначала .tmp / .swap, затем атомарный os.Rename — падение, kill -9 или обесточивание посреди записи не могут обнулить живой конфиг. Визард сохраняет свой .bak для ручного восстановления. См. SPEC 041.

Устойчивость и наблюдаемость

  • Лимит 100 МБ на загрузку sing-box core. [v0.8.7] Pre-flight Content-Length + кумулятивный счётчик. Легитимные архивы < 20 МБ.
  • Расшифровка HTTP-статусов в ошибках subscription-fetch. [v0.8.7] 401 → "token may have expired", 403 → "provider blocked", 404 / 410 / 429 / 5xx — каждый с подсказкой.
  • Подсказка «(подписки: X ч назад)» рядом с config.json на Core Dashboard. [v0.8.7] В рамках сессии.
  • Маркер * на кнопке Update, когда визард сохранил изменения, а парсер не отработал. [v0.8.7] См. SPEC 043. Текущая реализация минимальная — фиксится в SPEC 045.
  • Счётчик источников в тосте Update. [v0.8.8] Если хотя бы один источник упал или вернул ноль нод — Config updated: 2/3 source(s) succeeded (1 failed) вместо общего «successfully». «Молчаливый ноль» считается failure.

Безопасность

  • Редакция токена Clash API в debug-логах. [v0.8.7] Раньше LoadClashAPIConfig писал полный bearer на каждом старте; теперь token=ab***89. Токен по-прежнему виден в Settings UI через Copy. Debug-логи можно безопасно шерить.

Исправлено

  • Плейсхолдеры @urltest_* больше не утекают в config.json. [v0.8.8.1] SPEC 040 в v0.8.7 ввёл шаблонные переменные @urltest_url / @urltest_interval / @urltest_tolerance в auto-proxy-out, но путь генерации outbound-ов в парсере копировал их дословно — sing-box падал с outbounds[1].interval: time: invalid duration "@urltest_interval". Свежие установки v0.8.7 / v0.8.8 вообще не запускались. Фикс: core/config/SubstituteParserConfigPlaceholders вызывается на входе GenerateOutboundsFromParserConfig, обходит все Options под parser_config.outbounds[] и parser_config.proxies[].outbounds[], заменяет строки @varname через 3-уровневый резолвер (state-override → template default → hardcoded fallback). Существующие сломанные state.json лечатся автоматически — никаких ручных действий.

  • Override @varname из Settings tab теперь действительно применяется. [v0.8.8.3] v0.8.8.1's BuildVarSubstituterFromDisk имел три независимых бага в override-ветке (loadStateSettingsVars), и кастомизация из UI молча игнорировалась — urltest_interval = 1m из Settings tab не доезжал до сгенерированного конфига. Остальные два уровня резолюции (template default_value, hardcoded fallback) работали, поэтому sing-box получал валидные значения; ~99% юзеров (которые не трогают URLTest defaults) не пострадали. Но любой, кто кастомизировал, тихо получал template default. Три бага:

    1. Неправильный путь к файлу. v0.8.8.1 искал bin/state.json; реальный путь — bin/wizard_states/state.json.
    2. Неправильный формат JSON. Список декодировался как map[string]string; на диске — массив [{name, value}, ...].
    3. Неправильный JSON-ключ. Блок искался под "settings_vars" / "SettingsVars"; wizard пишет под "vars" (см. WizardStateFile.Vars с тегом json:"vars").

    Полная ретроспектива — SPEC 048.

  • Шаблон визарда — object-форма options больше не портит подставляемые значения. [v0.8.8] Раньше type: "text" + object-form options рендерился как combo-виджет со свободным вводом. Выбор «5m (default)» для urltest_interval приводил к "interval": "5m (default)" вместо "5m", и sing-box ругался. Фикс: на этапе JSON-unmarshal любая object-форма в options принудительно даёт Type = "enum". Строгий дропдаун невозможно ввести вручную. Legacy plain-string options (["a","b"]) не затронуты.

  • STUN settings dialog обрезался на Windows (issue #54). [v0.8.7] Auto-size сжимал URL-entry под placeholder-ширину. Диалог теперь явно ≥ 520 px.

  • CI был красный с 2026-04-16. [v0.8.7] internal/locale.TestAllKeysPresent падал — английские ключи «Copy jump server link» без русских пар. Паритет восстановлен.

Шаблон по умолчанию

  • Список русских и кириллических TLD расширен в ru-domains. [v0.8.7] Было .ru / .xn--p1ai / .su. Добавлены .рус / .москва / moscow / tatar / .дети / .сайт / .орг / .ком.

  • URLTest-vars в bin/wizard_template.json переразведены. [v0.8.8] urltest_url остался type: "text" с plain-string URL-options (combo с editable пресетами). urltest_interval и urltest_tolerance теперь явно type: "enum" с object-form {title, value} (строгий дропдаун с подписями типа «5m (default)» / «100 ms (twitchy)»).

Техническое / Внутреннее

  • Расширения StateService. [v0.8.7] AutoPingAfterConnect, TemplateDirty, LastUpdateError / LastUpdateErrorAt / LastUpdateSucceededAt.
  • ProxySource.Disabled bool json:"disabled,omitempty". [v0.8.7] Omit-default — legacy-совместимость.
  • Счётчики OutboundGenerationResult. [v0.8.8] TotalSources / SucceededSources / FailedSources пишутся в GenerateOutboundsFromParserConfig. UpdateConfigFromSubscriptions возвращает (*OutboundGenerationResult, error).
  • Кастомный UnmarshalJSON на TemplateVar. [v0.8.7] Поддерживает три JSON-формы options. [v0.8.8] Object-форма автоматически даёт type: "enum" независимо от заявленного типа.
  • Новый пакет core/debugapi/. [v0.8.7] Изолированная HTTP-поверхность с узким ControllerFacade. Адаптер debugAPIFacade в core/debugapi_wiring.go.
  • internal/platform/power_linux.go. [v0.8.7] Новый файл. [v0.8.8] power_darwin.go добавлен. Build tag power_stub.go сужен.
  • CI: per-version release-notes файл обязателен. [v0.8.8] Release-job читает docs/release_notes/<slug>.md. Если файла нет — workflow падает до создания релиза. Пререлизы получают баннер > ⚠️ Pre-release build.
  • Новый runbook docs/RELEASE_PROCESS.md. [v0.8.8] Канонная процедура для stable и prerelease. Ссылки в AGENTS.md.
  • FallbackVersion 1.13.6 → 1.13.11 в core/core_version.go. [v0.8.8]
  • Спеки-задел на v0.9.x. [v0.8.8] Без правок кода:
    • SPEC 045 — State / Config Decoupling. Развести Wizard Save (только state.json) и Build Config (config.json из state + кэш outbounds), по образцу мобильного клиента LxBox.
    • SPEC 046 — Pinned Core and Template. Жёсткое закрепление версии sing-box и коммита wizard_template.json за версией лаунчера.
  • core/config/varsubst.go. [v0.8.8.1] Self-contained — без новых зависимостей и UI-импортов. Тип VarSubstituter, SubstituteParserConfigPlaceholders, BuildVarSubstituterFromDisk, hardcoded fallback для трёх URLTest-плейсхолдеров. Внедрено в оба пути (wizard preview/save + parser auto-update).
  • Path-инварианты сведены. [v0.8.8.3] internal/constants/constants.go получил WizardTemplateFileName, WizardStateFileName, WizardStatesDirName. internal/platform/platform_common.go получил GetWizardTemplatePath(execDir), GetWizardStatesDir(execDir), GetWizardStatePath(execDir). Код, которому нужны эти файлы, ОБЯЗАН ходить через них — никаких больше самосборок filepath.Join(execDir, "bin", "wizard_states", "state.json") на каждом callsite.
  • Canary-тест с реальной фикстурой. [v0.8.8.3] core/config/testdata/state-real.json собран с реальной установки; TestBuildVarSubstituterFromDisk_RealFixture проверяет применение override через реальную on-disk схему. Если JSON-тег снова сломают — тест упадёт громко.
  • SPEC 048 — PARSER_CONFIG_VAR_SUBSTITUTION (ретроспектива). [v0.8.8.3] Документирует архитектуру v0.8.8.1 hotfix-а, три бага в override-loader, path-invariant рефакторинг и process-уроки.

Миграция

  • В bin/settings.json добавлены subscription_auto_update_disabled, auto_ping_after_connect_disabled, debug_api_enabled, debug_api_token, debug_api_port. [v0.8.7] Отсутствие = zero (enabled / пусто / 9269), существующие установки ведут себя как раньше.
  • wizard_template.json — параметры auto-proxy-out через @urltest_url / @urltest_interval / @urltest_tolerance. [v0.8.7] Кастомные шаблоны: смерджить три новых vars или оставить литералы (обе формы работают начиная с v0.8.8.1).
  • Кастомные wizard_template.json с type: "text" + object-form options тихо нормализуются в type: "enum" при загрузке. [v0.8.8] Если хочется combo со свободным вводом — переключить options в plain-string форму.
  • Селектор языка переехал из Help в новую вкладку Settings. [v0.8.7]
  • Существующие сломанные state.json (свежие установки v0.8.7 / v0.8.8) лечатся автоматически на первом wizard save под v0.8.8.1+. Никаких ручных действий не требуется.

Known issues / отложено на редизайн

Не входит в 0.8.8.3, отслеживается для v0.9+:

  • State / Config decoupling (SPEC 045) — dirty-маркер * всё ещё семантически размазан (срабатывает на любое сохранение, не только на правки источников).
  • Event-driven автообновление подписок — polling loop в core/auto_update.go старого образца. Запланированный редизайн: типизированные триггеры через единый dispatcher.
  • Правый клик по кнопке UpdateSecondaryTapWrap не маршрутизирует secondary-тапы в widget.Button; нужен кастомный RightClickableButton.
  • Плитка «Last auto-update failed» на Core Dashboard — реализована, но в практике не показывается; диагностика отложена.
  • Кнопка Ping-all → Cancel — сейчас полностью disable во время теста; редизайн на click-to-cancel запланирован.
  • Pinned core + template (SPEC 046) — лаунчер тащит latest sing-box и HEAD ветки wizard_template.json. Жёсткое закрепление избавит от drift.

Don't miss a new singbox-launcher release

NewReleases is sending notifications on new releases.