Phase 2 of the ② Serve rework (Phase 1 = #635 dead-end fix): a Route-C brought
model can be re-tuned before serve, without hand-editing a compose. Fields
(pre-filled from the resolved slug's defaults, dropdowns to avoid typos):
• served name → SERVED_NAME (Input)
• ctx → MAX_MODEL_LEN (Select — presets + the slug's own default)
• KV cache → KV_CACHE_DTYPE (Select — fp8_e5m2/e4m3/turboquant_4bit_nc/…)
• spec-decode → SPEC on/off (Select)
• VRAM util → GPU_MEMORY_UTILIZATION (Select)
Mechanism (all five ride env — no per-serve compose rewrite):
- data.py: ActionPlan gains `env`; dispatch merges {**os.environ, **plan.env}.
- services.py: serve_generated(compose_path, overrides) → plan.env (+ pins
MODEL_DIR); serve_override_defaults() parses the sibling compose's
${VAR:-default} for pre-fill (stdlib regex, no PyYAML).
- swap_apply.py: emit parameterizes --served-model-name ${SERVED_NAME:-…} and
gates --speculative-config behind ${SPEC:-on} via the SAME entrypoint the
shipped nvfp4 compose uses — so SPEC=off drops the MTP drafter at up-time.
- app.py: LaneServePane fields, revealed + pre-filled only for a Route-C armed
model (hidden otherwise); collect_overrides() → serve_generated. Loose
validation (dropdowns constrain; the reconcile gate + boot are the real check).
Validated: emitted compose `docker compose config` resolves SERVED_NAME=X and
SPEC=off (entrypoint gate) cleanly; 169 byo/serve/override tests pass.
Claude-Session: https://claude.ai/code/session_01EfF565T9eSLaqGzidyJ1Pm
Co-authored-by: noonghunna <10742901+noonghunna@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>