`get_server_args().<field>` reads one process's startup record. Nine sites still
did that for a value that has a namespace: the attention backend (5),
`skip_tokenizer_init` (2), the draft-aware `load_format`, and a chunked-prefill
size in `sglang.kernels`. They now read `get_exec().kernel` / `get_serving()` /
`get_model()` / `get_schedule()`, so they see the resolved value including
post-publish overrides.
The multimodal processor's device selection moves to the instance it was
constructed with rather than to a namespace: `base_gpu_id` differs per worker (the
encode-server DP workers each specialise their own copy), so no process-global
value can stand in for it, and engines sharing a tokenizer process each need their
own. Branch order, the NPU preprocess patches, and the case that leaves "device"
unset are unchanged.
What stays on `get_server_args()` is the derived API — `@property` and method
members computed from several fields plus the HF config
(`mamba_cache_chunk_size`, `get_model_config()`, `enable_mamba_extra_buffer*`) —
plus three config-intent reads of live-shadowed sizes, each of which needs an
answer the live topology property cannot give (the DSA indexer's PP gate must
short-circuit before touching the PP group, `allocation`'s DCP gate asks whether
DCP was configured at all, and the CUDA-IPC recycler runs where no group exists).
A new AST ratchet pins both shapes it can see — the direct call and an alias
bound from it in the same function — at 0 and 12 respectively, exempting the
derived APIs and those three sites by name. The alias-form baseline is not zero:
those reads are mostly per-runner fields in model code, and lowering them is the
next slice.
Two fixtures stopped faking config: `test_dllm_fdfo_kv_reuse` rebound
`allocation.get_server_args` to a SimpleNamespace, which silently stops
intercepting the moment a reader migrates; it publishes a real config instead.
Each of these wrote a value after resolution so a later reader would find it on
the instance. None of them needed the instance: one write was redundant, and the
two that carry a value the resolved-config readback reports move to
get_context().override, which the readback overlays.
- The SM100 GDN prefill default was written onto ServerArgs and read back one
line later by initialize_linear_attn_config. It is now the return value of
flashinfer_gdn_prefill_default, threaded into initialize_linear_attn_config
(an explicit --linear-attn-prefill-backend still wins) and recorded with
get_context().override so /server_info reports the backend in effect.
- The XGrammar fallback recorded grammar_backend="none" on the instance. No code
reads the field after the factory reads it once, but get_internal_state
reports the whole resolved config, so the fallback now lands there instead:
the readback tells the truth and the seed keeps the requested backend.
- UnifiedRadixCache.init_hicache re-applied the direct-IO layout fixup that
__post_init__ already applies: init_hicache only runs when hierarchical cache
is on, which is exactly when _handle_hicache normalizes page_first to
page_first_direct (pinned by test_hicache_io_backend_and_mem_layout_
compatibility::direct_with_page_first). Three fixtures reached the fixup by
building ServerArgs(model_path="dummy"), whose resolution is skipped, so they
now declare the layout resolution would have produced.
Writer ratchet 34 -> 31.
The module-skipped tests injected config by faking get_server_args (a
SimpleNamespace stand-in patched onto the module) or by writing fields
onto a ServerArgs instance post-publish — both invisible to the namespace
accessors the production code now reads. Re-enable them by publishing the
config they need (get_context().override_server_args seeding, scoped per
test), asserting bag state where the old assertions checked instance
write-through (declare_load_time_override is bag-only), and extending the
per-runner stubs the code genuinely reads (kv_cache_dtype_str,
max_total_tokens, context_len).
The unified-radix-cache file (which grew a large hicache/insert-walk suite
while skipped) is recovered in the same change:
- test_cache_finished_req_strips_thinking (19 parametrized classes) wrote
strip_thinking_cache onto the ServerArgs instance; the cache reads
get_serving().strip_thinking_cache — use the serving bag's scoped
override.
- test_shallower_crossing_backs_up_above_backuped_middle staged its
broken-backup-continuity setup through insert_host, which now
deliberately drops refills below an un-backed-up node under
write-through (host_insert_dropped). Build the same tree state through
an explicit backup + device eviction.
Every config-namespace-migration deferral is recovered, so the deferral
ratchet (test_migration_deferral_ratchet.py) has done its job and is
retired.