Closes the UX gap raised by @snoby on #37 — previously, launching a
compose that needs the DFlash draft model without first running
WITH_DFLASH_DRAFT=1 setup.sh would fail with vLLM's generic
"Invalid repository ID or local directory" pydantic error.
Adds three new preflight functions in scripts/preflight.sh:
1. preflight_hf_token (soft warn) — wired into setup.sh before the model
download. Catches missing HF_TOKEN early and tells the user exactly
what to do (visit hf.co/settings/tokens, accept T&C, export the token).
Skip via PREFLIGHT_NO_HF_TOKEN=1.
2. preflight_compose_deps (hard error) — wired into switch.sh just before
docker compose up. Parses the target compose YAML for known model-path
patterns (qwen3.6-27b-dflash, qwen3.6-27b-mtp-head, qwen3.6-27b-autoround-int4)
and verifies each exists on host. If missing, emits a clear "Fix:" line
with the exact setup.sh invocation needed (e.g. WITH_DFLASH_DRAFT=1).
Refuses to proceed with exit 1. Skip via PREFLIGHT_NO_COMPOSE_DEPS=1.
3. preflight_kv_format_hint (soft warn) — wired into switch.sh as the last
pre-up check. Detects smallest VRAM via nvidia-smi; if <24 GB and the
target compose uses turboquant_3bit_nc KV, emits the @efschu finding
from #47 (TQ3 → fp8_e5m2 swap rule) with cross-link to docs/HARDWARE.md
+ a tools/kv-calc.py one-liner to predict the user's specific config.
Skip via PREFLIGHT_NO_KV_HINT=1.
Tested on this rig:
- HF_TOKEN unset → warns
- Missing DFlash dir → hard errors with WITH_DFLASH_DRAFT=1 hint
- Missing main model → hard errors with generic setup.sh hint
- 24 GB rig + TQ3 compose → silent (correct, TQ3 is right pick)
- Simulated 20 GB rig + TQ3 compose → fires the fp8_e5m2 hint
All preflights are individually skippable via PREFLIGHT_NO_<NAME>=1
env vars (matches existing PREFLIGHT_NO_FETCH=1 / PREFLIGHT_NO_GENESIS_PIN=1
patterns).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>