2026-10-15.md 16 KB

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-<fullsha> (сейчас только nightly-dev-<arch>-<cuda>-<shortsha>), база прунена и с узлов (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<sha>; релизный 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-<UTC-stamp>, репорт падает в 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-деплое.