# Night shift 2026-10-15 (day) ## Mёртвый BASE: ночные теги vLLM прунены, kindling не собирается После вчерашнего чат-шаблонного фикса `sm121 serve --build-node` попытался rebuild `spark-glm53:v10` (чексумма каталога сменилась) и упал: `FROM vllm/vllm-openai:nightly-ddd6fbca…` → **not found**. Docker Hub прунул всю старую схему `nightly-` (сейчас только `nightly-dev---`), база прунена и с узлов (dgx1/2), дайджест нигде не записан (сентябрьский лог затёрт, реестр на Mac не включён, web-jobs чисты) → образ-база **невосстановим**. Промежуточный ручной путь (тонкая обёртка `FROM spark-glm53:v10` + новый шаблон + label) построен на dgx1, но **отклонён оператором**: sm121 должен уметь собрать всё с нуля, без ручных обходов. ## Решение: репин BASE на релиз v0.31.0 (постоянный тег) - v0.31.0 (cut 2026-10-02) — первый релиз, содержащий коммит базы ddd6fbca (09-26); multi-arch, arm64 ✓. - Дрейф-аудит `ddd6fbca..v0.31.0` (6 дней mainline, 239 файлов): - все файлы, которые патчат kindling-патчеры (mla/_fa_common, mla/_core, sparse_attn_indexer_kpool, kernel_warmup, shm_broadcast, platforms/cuda, reasoning, glm5next/*) — **без изменений**; - `routed_experts.py`: vllm#58720 вкатился upstream **дословно** (`_index_expert_mapping` идентичен) → `vllm-58720-routed-experts.patch` удалён из Dockerfile (verify-base.py по-прежнему ассертит наличие фикса); - requirements: flashinfer 0.7.0 → 0.7.0.post1 (mикро-бамп), torch/NCCL/ cutlass-dsl без изменений. - `ARG BASE=vllm/vllm-openai:v0.31.0`, `ARG VLLM_REF=db9527a4…` (коммит тега — FlashKDA shim компилится против того же исходника, что в base). - Коммит `546e7b2` (shared repo). ## Сборка через sm121 — успешна `sm121 build --recipe glm53-kindling-2x --build-node dgx1.lan`: **11 m 16 s** (pull base 145 s + flashkda + патчи + verify-base гейт + --load). Гейт verify-base прошёл (Glm5Next, glm45, glm47_failclosed, sm_120, MiaAI SM90 + indexer, spin-wait, FlashKDA 17a037d, mentat). Образ `c4bf0a1a…`, label `74087ade…` (= чексумма каталога), шаблон внутри `6c444d8b…` (фикс). Каталог снова полностью воспроизводим с нуля. ## 2x serve: падение через 9 с и настоящая причина Первый serve упёрся в то, что контейнер умирал через ~9 с (с `--rm` — самоудалялся из store, в логах только TaskDelete). Причина: **бейковые оверлеи `experimental/`** (build.sh генерирует `Dockerfile.bake` — COPY оверлеев поверх image/Dockerfile) написаны против дерева ddd6fbca и включают полные файлы с **старыми импорт-блоками**. На чистом v0.31.0 такой файл даёт ImportError в первый же импорт (`hisparse get_hisparse_gpu_memory_usage`). verify-base проходит — он ранит ДО bake- стадии. 23 оверлея из 38 имели дрейф базового файла. Ребейс на v0.31.0: `new = v0.31.0-файл + (оверлей − ddd6fbca)`; 21 авто, 2 вручную (`rejection_sampler` — рефакторинг `gather_draft_sampled()`; `flashinfer_mla_sparse_sm90` — 3-кортеж `_kv_lens_host` + early-return `_TRITON`). Коммит `5e04b7b`. **Вторая ловушка — guard в `experimental/draft-trunc/draft_trunc.py`**: `VLLM_COMMIT = "ddd6fbca"` + чек `f"+g{VLLM_COMMIT}" in vllm.__version__`. Ночные базы несли scm-суффикс `+g`; релизный v0.31.0 — голый `"0.31.0"` → guard ронял движок на старте ("Refresh the copies..."). Фикс: guard закреплён за версией релиза (semantics fail-loud сохранены), коммит `6e0b952`. Ребильд 30 с, label `29c47313…`. Финал: serve6 (08:29) — контейнер живой, грузит веса (33 шарда, NFS4), Mac-процесс serve умер после стрима лога (ран-лиджер закрыт); модель поднимается автономно, readiness ~08:39 UTC. Пайдантик-трейс с `{{dflash}}` в логах serve2/serve6 источник не установлен (live-команда catched inspect несёт resolved `snapshots/bf582e4e…`, движок грузит веса — не в этом краш); если повторится — смотреть APIServer-процесс, а не команду. ## Итог дня (10-15) - **kindling-2x снова жив на v0.31.0-базе** (sm121-native, воспроизводим с нуля), API http://192.168.88.14:30000, модель `glm53`. Смоук: plain ✓ + structured output с параллельными tool calls ✓ (горячий путь фикс-шаблона). - Лиджер: Mac-серверные процессы (serve2–6) умирали после стрима лога, контейнер живёт автономно → ран-лиджер закрыт, модель служит без open-run. Для чистого состояния: `sm121 serve` заново (цена ~20 мин перезагрузки весов). - Пайдантик-трейс с `{{dflash}}` в логах serve2/serve6: источник не установлен (live-команда несёт resolved `snapshots/bf582e4e…`, движок поднялся и служит) — не фатально, не в команде. - Ключевой урок: при смене BASE в kindling-дире **все** бейковые оверлеи (полные копии vllm-файлов) надо ребейсить + проверять guards на `__version__` (draft-trunc). Чек-лист записан в `docker-images/glm53-kindling/AGENTS.md` ("Changing the vLLM base"). ## Замечания - **karmic-kraken** dirs (шаблон тоже обновлён): его BASE — дайджест-закреплённая CUDA (вечная), rebuild воспроизводим, но полный clone-at-pin (долгий, 45+ мин) — сработает при следующем serve полос, использующих karmic-kraken (`glm53-kindling-4x-karmic`, `mimo26-flash-mopd-4x-vllm`, `mimo26-flash-mopd-4x-sparkring`). - Патчеры со «вступлением» (MiaAI retarget под flashinfer 0.7.0) прошли на 0.7.0.post1 — якоря не съехали. - Ночные vLLM-теги имеют TTL: любая схема на `nightly-*` мёртва через недели. Базы должны быть релизными/дайджестными (karmic — образец). ## Аддон 1.1.11 (сборка + деплой на Pi) - **1.1.11** (reпo `sm121-ha-integration`, коммит `e577b74`): интерактивная recipes-панель (кнопка ⟳ sync → `POST /api/repos/sync`, per-row serve/stop через job-API, `fleet_up` — running-статус из fleet-пробы для машин без ledger (Pi), «—» в колонке запусков без ledger), bench-эргономика (опц. `--label`, opt-in `--depth`, caveat-`*` в perf ячейках), follow-SSE report-viewer'а под префиксом `/recipes`, dock-меню якорится к кнопке `+`. - CI (GitHub Actions, OIDC) собрал `ghcr.io/kilork/sm121-addon:1.1.11` (aarch64+amd64+manifest) и запушил. - **Деплой на Pi**: ws-прокси HA (`supervisor/api`) отдавал `unknown_error` на всех `/app*` — в supervisor 2026.09.x V2-API (`/apps/...`) смонтирован под префиксом `/v2` и **выключен feature-flag'ом** (`v2_enabled`), а рабочий путь — V1 `POST /addons/{slug}/update` (install — только для новых). Токен API — из `/data/cli.json` внутри supervisor-контейнера (`access_token`; токен в env app-контейнера `SUPERVISOR_TOKEN` — app-scoped, на install даёт 403). Supervisor API в HAOS 18.3 — в контейнере `hassio_supervisor` на порту **80** (не 8188), IP 172.30.232.2. - HAOS 18.3 сменил layout: data-раздел на `/data` (не `/mnt/data`), `/mnt/data/supervisor` на хосте отсутствует (/docker-маунты из другого namespace). - Проверено: контейнер `app_02c10862_sm121` на `:1.1.11`, RSS 55 MiB, дашборд `http://ha.lan:3100` (token из `options.json → sm121_web_token`), `POST /api/repos/sync → {"ok":true,"repos":1}`, в SSE `/recipes/events` `glm53-kindling-2x` = **`fleet_up: true`** (на Pi ledger'ов нет, контейнеры видны fleet-пробой на dgx1/dgx2) — целевой кейс работает. ## Аддон 1.1.12 (перенос кнопок управления в раскрывающуюся секцию) - По просьбе оператора: кнопки больше не в state-ячейке каждой строки — controls переехали в **раскрывающуюся секцию** строки (клик по строке), над toml-ссылкой: **▶ serve / ⏹ stop** (tracked jobs), **▤ logs** (только для запущенного — живой хвост: пикер ноды из fleet-пробы + `/api/logs` attach + стрим через `/events`, при сворачивании строки стрим отключается), **⚡ bench** (новый `POST /api/bench` — tracked job, стандарт seed 42/hardmode/perf c1,2, quality-прогон без лейбла авто-лейблится `web-`, репорт падает в recipe-репо и появляется в таблице через live stream). - 1.1.12 (`cc30f20`): CI → `ghcr.io/kilork/sm121-addon:1.1.12`, деплой тем же V1-путём (`POST /addons/02c10862_sm121/update`, токен из `/data/cli.json` supervisor-контейнера). Проверено: контейнер на `:1.1.12`, RSS ~37 MiB, маркеры actbar/logbox/data-act на `/recipes`, `/api/bench` отвечает (401 без токена / 415 без JSON). ## MiMo 4x rebase на SparkRing 2026.10.4 (dgx58-switch) - `power on dgx58-switch` (dgx5–8 + switch + fan). Образ `dev-20261013-dcp2prefill-status038-sircl-tp6` был пред-затянут на dgx6/dgx8 — digest сверен с релизом 2026.10.4 (`e21ba936…acd76f`) ✅. - **dgx5 был заблокирован**: root fs 100% (0 байт свободно) — sshd отказывал в key-auth, docker load невозможен. Чистка docker-мусора (`container prune` 2.6G + `image prune -a` 210.5G + `builder prune` 32G) → 307G свободно, 65%. HF-кэш не тронут. - dgx6→dgx5 node-to-node ssh падал (`publickey`): у dgx6 только `id_ed25519_shared` (не-deфолтное имя) — ssh его не предлагает; нужен `ssh -i ~/.ssh/id_ed25519_shared`. dgx8→dgx7 работал (у dgx8 есть дефолтный id_ed25519, его публичная половина в authorized_keys dgx7). В итоге синк сделал сам лаунчер: save/load + **pull-by-digest re-attach** (manifest-only, слои локальные) — digest встал на dgx5/dgx7. - Первый serve: rank 2 (dgx7) умер через 28 с после старта (не OOM — «Deactivated successfully», `--rm` съел логи). Второй спуск с `--keep --no-wait`: все 4 up, ранг 2 жив — транзиент, повторного триажа не потребовалось (первый спуск стартовал в момент re-attach digest на dgx7 — вероятная гонка). - Рецепт: digest 71d41057… → e21ba936… (recipes `a09e85f`), комментарий обновлён (2026.10.4: status 0.3.8, sircl 0.6.0, DCP2 prefill, TP6 профиль; все 2026.10.2 профили приняты без изменений). - **Bench (v2.8.0, pluto, `--tokenizer /tmp/mimo-tok` — MiMo-токенайзер подтянут с NAS, на pluto его не было): 90/100 (174/194)** ★★★★★. Perf: pp 4,609/4,975, **tg 66.2 c1 / 80.7 c2 @d0** — против якоря 10-02 (dev-20261004): pp 4,314, tg 55.4 → **+19% decode, +7% prefill**. Качество 92 (dev7/184) → 90 (v2.8.0/194) — пулы разные, сравнение только по нормированному /100 с cross-harness bias. - Отчёты: `recipes/mimo26-flash-mopd-4x-sparkring/reports/2026-10-15_195648_rebase-1015.*` (recipes `040e9f2`). Ветка `seed` в recipe-репо случайно создана и удалена; коммиты легли в `main` (fast-forward). - Состояние: MiMo 4x serves на dgx5–8 (API `http://192.168.88.43:30000`, модель `mimo-v2.6-flash` @524K), ledger открыт (serve с `--no-wait`). 2x glm53 на dgx1/2 не тронут. ## Первоклассные движки: gr8 + DGPP (engine-drivers) - Мотивация: сторонние движки (`gr8`, `DGPP`) были «псевдо-vLLM» — попадали в vLLM-ветки и генерировали неверные флаги. Рефакторинг по трейту + два новых движка как первоклассные. Спека: `specs/tech-architecture/engine-drivers.md`. - **Phase 1** (`engine.rs`, удалён `engine_flags.rs`): трейт `EngineDriver` + реестр `driver_for()`; шесть мест (build_engine_args, docker NCCL worker-IP, tmux entrypoint/port/host-IP, doctor-hint) делегируют. Чистый рефактор — vllm/sglang байт-в-байт. - **Phase 2** (`Gr8Driver`): `--model`, `--tp/--peers` (mgmt-IP по рангам, `peers` в `EngineFlagsCtx`), `takes_host_port=false` (API :8100 фикс.). `validate` освобождает движки без `--host/--port` от port-convention. Рецепт `glm53-full-tp4-gr8` (recipes `541c5f6`). Dry-run рендерит точный `gr8 glm53 up … --tp 4 --peers …`. - **Phase 3** (`DeployTarget::Native` + `DgppDriver` + `src/native/`): head-coordinated — rank 0 запускает `dgpp-cluster up`, менеджер самнимает peers. Рецепт `[dgpp]` (http_port, dir, release, свободная таблица `[dgpp.engine]`); генерация cluster-JSON (model/world_size/http + engine verbatim) + sibling `.env` (DGPP_NODES/SSH_USER/ports), заливка на rank 0 heredoc'ом (`~`→`$HOME`), nohup-запуск; стоп — `dgpp-cluster down`. Рецепт `qwen38-27b-nvfp4-dgpp` (recipes `c733c06`). Юнит-тесты JSON/env/expand_home. - `make check` зелёный (375 тестов + UI + lines + recipe-gate). Launcher `fe1d70a`. Live-проверка native-serve — при первом реальном DGPP-деплое.