- lx-changelog: health board + observatory + global probe + sub cache entry - DECISIONS.md: D18 board vs delete-and-overlay, D19 observatory vs sweep, D20 global probe settings - contract comments: urltest.go CheckOutbounds (fast circuit) + observatory.go loop (background circuit + freshness gate) document the two-circuit split - SPEC 019: dial-error section updated - slots still not moved, but board verdict demotes dead slot on next pick + retry (§5.B); sticky/replace-in-slot/never-shrink invariants preserved
SPECS — sing-box-lx (Spec Kit)
Все задачи — папки NNN-NAME. Внутри: SPEC.md → PLAN.md → TASKS.md → IMPLEMENTATION_REPORT.md.
Имя папки: NNN-NAME
| Часть | Значение | Расшифровка |
|---|---|---|
| NNN | 001, 002, … | Сквозной номер — стабильный якорь, не меняется никогда |
| NAME | UPPER_SNAKE | Название |
Имя папки не несёт тип/статус: они меняются по ходу задачи, а имя должно
оставаться стабильным (на него ссылаются из кода, доков и сабмодуля). Ссылки
давай короткой формой SPECS/NNN-NAME — она переживёт смену статуса.
Тип и статус — в шапке SPEC.md + Roadmap
Источник правды по типу/статусу — таблица-шапка в начале SPEC.md каждой
задачи; Roadmap ниже её агрегирует.
| Поле | Значение |
|------|----------|
| Тип | F (feature) \| B (bug) \| Q (question/исследование) |
| Статус | N (new) \| O (open) \| W (wait) \| C (complete) |
Файлы внутри папки
| Файл | Назначение |
|---|---|
| SPEC.md | Что и зачем — проблема, требования, критерии приёмки |
| PLAN.md | Как строить — архитектура, изменяемые файлы, зона касания upstream |
| TASKS.md | Чеклист по этапам |
| IMPLEMENTATION_REPORT.md | Отчёт после реализации |
| HISTORY.md | Хронология: как делали раньше, почему переделали. Только при смене архитектуры фичи (см. правило структуры ниже) |
Структура SPEC.md — актуальное состояние сверху, НЕ хронология
Правило: SPEC.md описывает ТЕКУЩУЮ (актуальную) архитектуру фичи в первую очередь. Порядок разделов — от актуального состояния к деталям, НЕ по хронологии разработки.
- Верх SPEC.md = как фича устроена СЕЙЧАС (актуальная архитектура), затем детали/контракт/критерии.
- НЕ вести SPEC.md как дневник («сначала сделали так, потом в rc.9 исправили…»). Пометки вида «ИСПРАВЛЕНО в rc.N», «прежнее утверждение неверно», отвергнутые подходы — НЕ в SPEC.md.
- Когда архитектура фичи МЕНЯЕТСЯ (переделали механизм): SPEC.md переписывается под новое состояние, а старое состояние + обоснование смены (как делали, почему это оказалось неверно, почему выбрали новое) выносятся в HISTORY.md этой же папки.
- Читатель SPEC.md должен понять, как всё работает СЕЙЧАС, не продираясь через историю решений. История — по запросу, в HISTORY.md.
Конфигурация фич
Пользовательский конфиг XHTTP и AmneziaWG 2.0 (поля + примеры) — ../docs-lx/lx-config.md.
Корень SPECS
| Файл | Назначение |
|---|---|
| CONSTITUTION.md | Неизменяемые принципы, приоритеты, запреты |
| IMPLEMENTATION_PROMPT.md | DoD, git/ребейз-ритуал, контракт выхода |
Workflow
- Папка
SPECS/NNN-NAME/(следующий номер). В шапке SPEC.md —Тип+Статус: N. - SPEC.md → PLAN.md → TASKS.md.
- Реализация по TASKS с учётом IMPLEMENTATION_PROMPT и CONSTITUTION.
- IMPLEMENTATION_REPORT.md, DoD-чеклист, статус в шапке SPEC.md и Roadmap →
C.
Roadmap (план задач)
| # | Задача | Статус | Суть |
|---|---|---|---|
| 001 | FORK_BOOTSTRAP | C | Remotes, ветка lx, Makefile.lx, версия -lx (ldflags), CI-скелет, lx-test/config — ✅ собрано/проверено |
| 002 | XHTTP_CLIENT_TRANSPORT | C | ✅ live-validated против Xray (3x-ui): packet-up/auto работают (handshake+DNS+HTTPS+download); stream-one — был баг, исправлен в 011 |
| 003 | AWG2_CLIENT_ENDPOINT | C | ✅ Функционален, проверен живым AWG2-сервером (handshake+keepalive+трафик). merged-форк Leadaxe/wireguard-go (sagernet+обфускация) через submodule; S1–S4/H1–H4/I1–I5 |
| 004 | BUILD_CI_RELEASE | C | ✅ Makefile.lx/libbox-теги, дешёвый CI (lint+build-check на push; cross×6+AAR на dispatch), lx-release.yml (релиз v1.13.13-lx.3 опубликован — 6 desktop + 2 AAR), lx-rebase.yml (авто-ребейз → PR/issue, демо зелёное) |
| 005 | AWG2_RANGED_MAGIC_HEADERS | C | ✅ Проверено живым awg2-сервером с ranged-конфигом (handshake+трафик). Диапазонные H1–H4 ("N-M") из awg2-экспортов: option.MagicHeader (number|string) → spec-строка в IpcSet; vendored wireguard-go уже умел |
| 006 | LINUX_MUSL_STATIC_ROUTER_BUILDS | C | ✅ CI-приёмка 4/4 арки статикой (amd64/arm64/armv7/mipsle-softfloat, statically linked, libdl=0, naive сохранён). musl-сборки под роутеры по подобию upstream build.yml (cronet-go + Chromium musl-toolchain, with_musl). Чинит #1 (libdl.so.2 на AsusWRT + armv7). CI-only, без Go-кода |
| 007 | AWG_OVER_WIREGUARD_DETOUR_GUARD | C | ✅ Код+тесты+DoD, Start-guard field-verified (Android lx.9). Bug в 003: AWG-нода с detour на WireGuard-туннель (плоский WG или AWG) вешает ядро на Android (AWG внутри WG). Два дополняющих guard'а: Start-guard (Endpoint.Start, статическая транзитивная detour-цепь — device не поднимается) + selector-guard (SelectOutbound — при переключении селектора на WG гасит AWG-потребителей до переключения, через ConsumersOf). Оба — вариант B (ядро живёт, узел не встаёт, ошибка в лог). Ленивый dialer-guard (lx.8) откачен. detour на VLESS и WG→AWG — разрешены. Чинит #2 |
| 008 | AWG_JUNK_PARAM_VALIDATION | C | ✅ Код+тесты+DoD. Bug в 003 (найден при 007): jmin > jmax паникует rand.Int в amneziawg-go (краш в timer-горутине). validateJunk в awgIpcLines отвергает на уровне конфига (check/старт), без паники. Узко — только краш-кейс; jc-несогласованность осознанно не трогаем (минимальный дифф, совместимость). Чинит #3 |
| 009 | WIRESOCK_MASQUERADE_PROFILES | C | ✅ Код+тесты+DoD; механизм проверен вживую (туннель + трафик на 009), релиз v1.13.13-lx.11. WireSock-стиль id/ip/ib (домен/протокол/браузер) — декларативный сахар над I1 CPS. Профили quic (1-RTT short header) / dns (EDNS OPT response) / stun (Binding Success Response) / sip (200 OK response), структуры портированы из open-source WireSock amneziawg-proxy/src/transform.rs (MIT). Механизм — I1 only (S1–S4 невозможен против WARP, сабмодуль не трогаем). id обязателен только для dns/sip (там идёт на провод), для quic/stun опционален. Строгая LDH-валидация домена (security-граница: инъекция в SIP/DNS). ib — без JA3-fingerprint (честно задокументировано). Все профили приняты реальным newObfChain; sing-box check зелёный; адверсариальный ревью (6 агентов) — 0 находок |
| 010 | WG_ENDPOINT_GRO_SPLIT_BRAIN | C | ✅ Корень подтверждён на железе, фикс верифицирован (download 0.44→20.7 Mbps), вмержен в lx (lx.14). Bug: WG-endpoint без detour на Android режет download (GRO split-brain — UDP_GRO включён, а receive-путь linux-only). Фикс — гейт UDP_GRO за !android в сабмодуле wireguard-go (conn/). UDP/WG-only |
| 011 | XHTTP_STREAM_ONE_DOWNLINK | C | ⚠️ Принято на синтетике; лайв НЕ прогонялся (нет reality+xhttp ноды). Bug в 002 (жалоба): vless+reality+xhttp+mode:auto не работал. Корень (сверено с Xray + issue #5635 + hiddify): stream-one слал <path>/<sessionId>, а Xray-сервер роутит stream-one только при пустом sessionId → downlink не-VLESS → unknown version. Фикс: голый путь без sessionId; mode:auto+reality → stream-one (детект reality по имени типа, без with_utls-зависимости). Юнит-тесты (URL-layout + reality-детект), check, сборки зелёные. Ветка lx-xhttp-streamone, в lx не влито; лайв — открытый TODO в REPORT |
| 012 | TCP_DOWNLINK_STALL_ZOMBIE_CONNS | C | ⚠️ НЕ воспроизводится на lx.14 (статус закрытия — «not reproducible»). Симптом (↑517 ↓0, WhatsApp/Telegram «висят») наблюдался на РАЗНЫХ нодах, включая WG → зонтик над «↓0»-сталлом, не один баг. WG-долю закрыл 010 (UDP/WG-only). Для не-WG (VLESS/reality) отдельного код-фикса нет — симптом сейчас не воспроизводится без подтверждённого объяснения. Артефакты: зонд LX_CONN_TRACE (не прогнан в бою), PROBE.md |
| 013 | PACKAGE_NAME_REGEX_RULE_ITEM | C | ✅ Код+тесты, сборки/vet/gofmt зелёные. Бэкпорт апстрим-фичи 1.14 (941ce58b) на базу 1.13.13 без полной миграции: rule-item package_name_regex (regex-матчинг Android-пакета) для route/DNS/headless. Новый route/rule/rule_item_package_name_regex.go + поля/регистрация/cond в 6 файлах роутинга. Хунк RuleSetVersion5 из коммита НЕ переносился (это rule-set v5, не фича). Полная миграция на 1.14 отложена до v1.14.0 stable (feasibility: ~1,5–2 дня, риск — ребейз AWG-подмодуля; lx-rebase.yml сам исключает alpha) |
| 014–021 | (см. шапки в SPECS/NNN-*/SPEC.md) |
C | Command-протокол RPC (014/015), connections-мьютекс (016), Connection.Detour (017), DNS-query-стрим (018), URLTest пул/sticky (019), multi-WG idle-suspend (020), MASQUE CONNECT-IP outbound (021). Источник статуса — шапка каждого SPEC.md |
| 023 | MUSL_TOOLCHAIN_MIRROR | C | 🛠 Durable-зеркало Chromium musl-тулчейна. snapshot.debian.org периодически 503-ит и блокирует релиз (v1.14.0-lx.2-rc.1 падал дважды на нём; actions/cache промахивается из-за ref-scoping тегов). Producer-workflow (lx-musl-toolchain-mirror.yml) заливает собранный тулчейн 4 арок в release-ассет musl-toolchain-cache; lx-release.yml восстанавливает его на cache-miss ДО фолбэка на snapshot. Источники: actions/cache → lx-mirror → snapshot. Обе workflow lx-owned, upstream-дифф нулевой. Зеркало заполнено, restore проверен |
| 022 | LX_DEEP_AUDIT | C | 🔍 Аудит-исследование + ремедиация. Многоагентный аудит всей LX-дельты по 10 осям + адверсариальная верификация каждой находки. 32→27 подтверждено (0 critical, 1 high, 1 medium, 6 low, 19 nit), 5 опровергнуто. Исправлено 24/27 (ветка lx-spec022-audit-fixes): P0 #1 masque h2 CONNECT висел навечно (ctx игнорировался); P1 #2 idle-suspend воскрешал guard-suspended AWG (hang ядра Android); + все P2/P3. Осознанно пропущены #12/#17/#18 (санкционированные компромиссы / ребейз-цена). Реестр + ремедиация в SPEC.md |
| 024 | RUNTIME_LOOP_GUARD | DEFERRED | 🔁 Guard от runtime-колец в detour/selector. Статическое кольцо ядро отклоняет на старте (circular outbound dependency); собранное в рантайме через SelectOutbound — нет защиты → fatal stack overflow, падение процесса. Проработана событийная модель E1–E5 + topologyMu-линеаризация гонки; адверсарская проверка (7 агентов): deadlock/false-positives HOLDS, но TOCTOU BREAKS — даже полный ядерный guard негерметичен без покрытия endpoint-mgr/Remove/history-side-channels и без устранения pointer↔tag расхождения после рантайм-Create. Решение (2026-07-06): защита на уровне UI (LxBox), ядро не трогаем. Design record: SPEC.md |
Вне этого репозитория: потребление ядра лаунчером (
singbox-launcher) — парсингtype=xhttpв реальный XHTTP-транспорт (сейчас023маппит его вhttpupgrade), AWG-поля в визарде, заменаbin/sing-box. Это отдельные задачи в репозитории лаунчера.