diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1669a01bb..58edf4de2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,18 @@ permissions: contents: read jobs: + # The environment-variable registry (c/coli_env.h) against the sources. No + # build, no model, no GPU -- seconds, so it reports before anything else. + env-registry: + name: Env registry in sync + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - run: make -C c check-env + engine: name: Engine (Linux, CPU) runs-on: ubuntu-latest diff --git a/c/Makefile b/c/Makefile index fe37e6bbd..b2c4baa76 100644 --- a/c/Makefile +++ b/c/Makefile @@ -765,7 +765,7 @@ $(file >.build-config,$(BUILD_CONFIG)) endif .build-config: ; -colibri$(EXE): colibri.c oracle.h pin_pool.h cli_args.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h omp_tune.h kv_fp8.h kv_tq.h abl.h backend_cuda.h backend_metal.h backend_vulkan.h decode_batch.h edge_adapters.h edge_runtime.h edge_tok_internal.h schema_gbnf.h segment_adapter_internal.h segment_adapters.h segment_runtime.h tier.h $(CUDA_OBJ) $(METAL_OBJ) $(VK_OBJ) $(VK_SPV) .build-config +colibri$(EXE): colibri.c coli_env.h oracle.h pin_pool.h cli_args.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h omp_tune.h kv_fp8.h kv_tq.h abl.h backend_cuda.h backend_metal.h backend_vulkan.h decode_batch.h edge_adapters.h edge_runtime.h edge_tok_internal.h schema_gbnf.h segment_adapter_internal.h segment_adapters.h segment_runtime.h tier.h $(CUDA_OBJ) $(METAL_OBJ) $(VK_OBJ) $(VK_SPV) .build-config $(CC) $(CFLAGS) colibri.c $(CUDA_OBJ) $(METAL_OBJ) $(VK_OBJ) -o colibri$(EXE) $(LDFLAGS) # Vulkan backend object (plain C + vulkan headers) and its SPIR-V shaders. @@ -1091,7 +1091,7 @@ tests/bench_cuda_resident_batch$(EXE): tests/bench_cuda_resident_batch.cu backen # the GPU sits idle. Same guard #783 put on kimi_k3, which since gaining an # MXFP4 expert path no longer needs it. tests/test_makefile_cuda_scope.py # asserts this shape. -olmoe$(EXE): olmoe.c cli_args.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h kv_prefix.h pin_pool.h route_trace.h serve_codec.h edge_adapters.h edge_runtime.h edge_tok_internal.h fused_simd.h segment_adapter_internal.h segment_adapters.h segment_runtime.h sse41_kernels.h +olmoe$(EXE): olmoe.c coli_env.h cli_args.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h kv_prefix.h pin_pool.h route_trace.h serve_codec.h edge_adapters.h edge_runtime.h edge_tok_internal.h fused_simd.h segment_adapter_internal.h segment_adapters.h segment_runtime.h sse41_kernels.h $(CC) $(NOCUDA_CFLAGS) olmoe.c -o olmoe$(EXE) $(NOCUDA_LDFLAGS) # Qwen3.6-35B-A3B engine (hybrid Gated Attention + Gated DeltaNet + streaming @@ -1125,13 +1125,13 @@ qwen36: qwen36$(EXE) endif # Rebuild when CUDA_DLL changes; otherwise an existing CPU-only executable can # be reported as up to date despite selecting the Windows CUDA DLL tier. -qwen36$(EXE): qwen36.c decode_batch.h serve_poll.h cli_args.h qwen36_tier.h expert_ffn.h idot.h st.h json.h compat.h omp_tune.h kv_prefix.h pin_pool.h edge_adapter_internal.h edge_adapters.h edge_runtime.h segment_adapter_internal.h segment_adapters.h segment_runtime.h gsgemv.h qgemv.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) .build-config +qwen36$(EXE): qwen36.c coli_env.h decode_batch.h serve_poll.h cli_args.h qwen36_tier.h expert_ffn.h idot.h st.h json.h compat.h omp_tune.h kv_prefix.h pin_pool.h edge_adapter_internal.h edge_adapters.h edge_runtime.h segment_adapter_internal.h segment_adapters.h segment_runtime.h gsgemv.h qgemv.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) .build-config $(CC) $(QWEN36_CFLAGS) qwen36.c $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o qwen36$(EXE) $(QWEN36_LDFLAGS) # DeepSeek V4.1 Flash: one file, like every other portable engine. The fp4 experts # stream from the official checkpoint and quant.h's mxfp4 kernel reads them as they # are, so there is no conversion target here to go with it. -deepseek_v41$(EXE): deepseek_v41.c cli_args.h st.h json.h tok.h tok_unicode.h compat.h omp_tune.h kv_prefix.h pin_pool.h quant.h idot.h \ +deepseek_v41$(EXE): deepseek_v41.c coli_env.h cli_args.h st.h json.h tok.h tok_unicode.h compat.h omp_tune.h kv_prefix.h pin_pool.h quant.h idot.h \ sparse_attn.h hyper_connections.h serve_codec.h serve_poll.h .build-config $(CC) $(CFLAGS) deepseek_v41.c -o deepseek_v41$(EXE) $(LDFLAGS) @@ -1139,7 +1139,7 @@ deepseek_v41$(EXE): deepseek_v41.c cli_args.h st.h json.h tok.h tok_unicode.h co # loader and SERVE=1 protocol. With CUDA=1 it links the same expert tier as # qwen36 (fp8 streaming mode: hot experts get VRAM copies, the RAM LRU stays); # without it the tier header's inline stubs keep the build toolkit-free. -qwen38$(EXE): qwen38.c pin_pool.h cli_args.h qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h omp_tune.h quant.h idot.h route_trace.h tok.h tok_unicode.h tok_unicode_o200k.h serve_codec.h edge_adapter_internal.h edge_adapters.h edge_runtime.h qwen38_vision.h segment_adapter_internal.h segment_adapters.h segment_runtime.h qwen36_tier.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +qwen38$(EXE): qwen38.c coli_env.h pin_pool.h cli_args.h qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h omp_tune.h quant.h idot.h route_trace.h tok.h tok_unicode.h tok_unicode_o200k.h serve_codec.h edge_adapter_internal.h edge_adapters.h edge_runtime.h qwen38_vision.h segment_adapter_internal.h segment_adapters.h segment_runtime.h qwen36_tier.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) qwen38.c $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o qwen38$(EXE) $(QWEN36_LDFLAGS) .PHONY: qwen38-tiny-generate qwen38-tiny-check @@ -1194,46 +1194,46 @@ qwen38-tier-engine-check: qwen38-tiny-fp8-generate tests/test_qwen38_tier_engine # Same tier sources as the engine: the test includes qwen36.c, so with CUDA=1 # it needs qwen36_tier.c and the backend object too (without CUDA, the header's # inline stubs cover it and both are empty). -tests/test_qwen36_ctx$(EXE): tests/test_qwen36_ctx.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_ctx$(EXE): tests/test_qwen36_ctx.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(LDFLAGS) # CACHE_ROUTE: route_select() against a residency table, no model needed. -tests/test_qwen36_cache_route$(EXE): tests/test_qwen36_cache_route.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_cache_route$(EXE): tests/test_qwen36_cache_route.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(LDFLAGS) -tests/test_qwen36_dense_batch$(EXE): tests/test_qwen36_dense_batch.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_dense_batch$(EXE): tests/test_qwen36_dense_batch.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) -tests/test_qwen36_json_escape$(EXE): tests/test_qwen36_json_escape.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_json_escape$(EXE): tests/test_qwen36_json_escape.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) # Both tokenizer.json merge spellings ("a b" strings and ["a","b"] pairs) # must index the same merge table; the pair form is what Qwen3.6 ships. -tests/test_qwen36_tok_merges$(EXE): tests/test_qwen36_tok_merges.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_tok_merges$(EXE): tests/test_qwen36_tok_merges.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) # A byte-counted serving payload may end mid-character; the pre-tokenizer must # not read past it. qwen38 already gates this (tests/test_qwen38_tokenizer.c). -tests/test_qwen36_tok_truncated$(EXE): tests/test_qwen36_tok_truncated.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_tok_truncated$(EXE): tests/test_qwen36_tok_truncated.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) # push_id / bpe_piece must refuse loudly, not crash, on a failed realloc during growth. -tests/test_qwen36_encode_oom$(EXE): tests/test_qwen36_encode_oom.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_encode_oom$(EXE): tests/test_qwen36_encode_oom.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) # the dense trunk's integer path: quantizer contract, int4 planar packing, dispatch. -tests/test_qwen36_dense_idot$(EXE): tests/test_qwen36_dense_idot.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_dense_idot$(EXE): tests/test_qwen36_dense_idot.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) # #1653: added tokens are split out before the regex pre-tokenizer, HF-style. -tests/test_qwen36_tokenizer$(EXE): tests/test_qwen36_tokenizer.c qwen36.c expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_tokenizer$(EXE): tests/test_qwen36_tokenizer.c qwen36.c coli_env.h expert_ffn.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) # Reproducible local timing evidence; intentionally not a noisy CI perf gate. -tests/bench_qwen36_dense_batch$(EXE): tests/bench_qwen36_dense_batch.c qwen36.c qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/bench_qwen36_dense_batch$(EXE): tests/bench_qwen36_dense_batch.c qwen36.c coli_env.h qwen36_tier.h st.h json.h compat.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) -inkling$(EXE): inkling.c cli_args.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h pin_pool.h serve_codec.h backend_cuda_ink.h backend_metal.h edge_adapters.h edge_runtime.h edge_tok_internal.h segment_adapter_internal.h segment_adapters.h segment_runtime.h $(INK_CUDA_OBJ) $(METAL_OBJ) +inkling$(EXE): inkling.c coli_env.h cli_args.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h pin_pool.h serve_codec.h backend_cuda_ink.h backend_metal.h edge_adapters.h edge_runtime.h edge_tok_internal.h segment_adapter_internal.h segment_adapters.h segment_runtime.h $(INK_CUDA_OBJ) $(METAL_OBJ) $(CC) $(CFLAGS) inkling.c $(INK_CUDA_OBJ) $(METAL_OBJ) -o inkling$(EXE) $(LDFLAGS) # ENGINES WITHOUT A CUDA BACKEND (#783). @@ -1250,10 +1250,10 @@ NOCUDA_LDFLAGS = $(filter-out -lcudart -lstdc++ -lcuda -L$(CUDA_HOME)/lib64 \ # GLM-5.3-Flash: routed experts stream from the int4-gs64 container. # METAL=1 accelerates resident matrices and routed MoE; CPU remains fallback. -glm53$(EXE): glm53.c decode_batch.h pin_pool.h cli_args.h st.h json.h stop_ids.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h serve_poll.h route_trace.h quant.h idot.h hyper_connections.h delta_attention.h sparse_index.h vision_tower.h backend_metal.h backend_vulkan.h edge_adapter_internal.h edge_adapters.h edge_runtime.h segment_adapter_internal.h segment_adapters.h segment_runtime.h $(METAL_OBJ) $(VK_OBJ) $(VK_SPV) +glm53$(EXE): glm53.c coli_env.h decode_batch.h pin_pool.h cli_args.h st.h json.h stop_ids.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h serve_poll.h route_trace.h quant.h idot.h hyper_connections.h delta_attention.h sparse_index.h vision_tower.h backend_metal.h backend_vulkan.h edge_adapter_internal.h edge_adapters.h edge_runtime.h segment_adapter_internal.h segment_adapters.h segment_runtime.h $(METAL_OBJ) $(VK_OBJ) $(VK_SPV) $(CC) $(CFLAGS) glm53.c $(METAL_OBJ) $(VK_OBJ) -o glm53$(EXE) $(LDFLAGS) -kimi_k3$(EXE): kimi_k3.c cli_args.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h kv_prefix.h pin_pool.h serve_codec.h backend_cuda.h backend_metal.h backend_vulkan.h edge_adapters.h edge_runtime.h edge_tok_internal.h hybrid_split.h segment_adapter_internal.h segment_adapters.h segment_runtime.h $(CUDA_OBJ) $(VK_OBJ) $(VK_SPV) $(METAL_OBJ) +kimi_k3$(EXE): kimi_k3.c coli_env.h cli_args.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h kv_prefix.h pin_pool.h serve_codec.h backend_cuda.h backend_metal.h backend_vulkan.h edge_adapters.h edge_runtime.h edge_tok_internal.h hybrid_split.h segment_adapter_internal.h segment_adapters.h segment_runtime.h $(CUDA_OBJ) $(VK_OBJ) $(VK_SPV) $(METAL_OBJ) $(CC) $(CFLAGS) kimi_k3.c $(CUDA_OBJ) $(VK_OBJ) $(METAL_OBJ) -o kimi_k3$(EXE) $(LDFLAGS) # Use a baseline that matches the compiler target. macOS already targets a @@ -1281,7 +1281,7 @@ iobench$(EXE): iobench.c compat.h tests/test_serve_sentinel$(EXE): tests/test_serve_sentinel.c compat.h serve_codec.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_cluster_protocol$(EXE): tests/test_cluster_protocol.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_cluster_protocol$(EXE): tests/test_cluster_protocol.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_ue8m0$(EXE): tests/test_ue8m0.c st.h json.h compat.h @@ -1296,10 +1296,10 @@ tests/test_tok_o200k$(EXE): tests/test_tok_o200k.c tok.h tok_unicode.h tok_unico tests/test_tok_gpt2$(EXE): tests/test_tok_gpt2.c tok.h tok_unicode.h tok_unicode_o200k.h json.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_k3_ram_budget$(EXE): tests/test_k3_ram_budget.c kimi_k3.c st.h tok.h quant.h idot.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h +tests/test_k3_ram_budget$(EXE): tests/test_k3_ram_budget.c kimi_k3.c coli_env.h st.h tok.h quant.h idot.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_k3_mmap$(EXE): tests/test_k3_mmap.c kimi_k3.c st.h tok.h quant.h idot.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h +tests/test_k3_mmap$(EXE): tests/test_k3_mmap.c kimi_k3.c coli_env.h st.h tok.h quant.h idot.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(CC) $(NOCUDA_CFLAGS) $< $(VK_OBJ) -o $@ $(NOCUDA_LDFLAGS) tests/test_tok_kimi_tiny$(EXE): tests/test_tok_kimi_tiny.c tok.h tok_unicode.h tok_unicode_o200k.h json.h @@ -1310,19 +1310,19 @@ tests/test_st_pread$(EXE): tests/test_st_pread.c st.h json.h compat.h tests/test_st_slice$(EXE): tests/test_st_slice.c st.h json.h compat.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_qwen38_tokenizer$(EXE): tests/test_qwen38_tokenizer.c qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h edge_runtime.c edge_runtime.h edge_adapters.h edge_adapter_internal.h st.h json.h compat.h quant.h idot.h route_trace.h tok_unicode.h tok_unicode_o200k.h +tests/test_qwen38_tokenizer$(EXE): tests/test_qwen38_tokenizer.c coli_env.h qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h edge_runtime.c edge_runtime.h edge_adapters.h edge_adapter_internal.h st.h json.h compat.h quant.h idot.h route_trace.h tok_unicode.h tok_unicode_o200k.h $(CC) $(NOCUDA_CFLAGS) $< edge_runtime.c -o $@ $(NOCUDA_LDFLAGS) -tests/test_qwen38_config$(EXE): tests/test_qwen38_config.c qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h tok_unicode.h tok_unicode_o200k.h +tests/test_qwen38_config$(EXE): tests/test_qwen38_config.c coli_env.h qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h tok_unicode.h tok_unicode_o200k.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_dsv41_serve_budget$(EXE): tests/test_dsv41_serve_budget.c deepseek_v41.c cli_args.h st.h json.h tok.h tok_unicode.h compat.h omp_tune.h kv_prefix.h pin_pool.h quant.h idot.h sparse_attn.h hyper_connections.h serve_codec.h serve_poll.h +tests/test_dsv41_serve_budget$(EXE): tests/test_dsv41_serve_budget.c deepseek_v41.c coli_env.h cli_args.h st.h json.h tok.h tok_unicode.h compat.h omp_tune.h kv_prefix.h pin_pool.h quant.h idot.h sparse_attn.h hyper_connections.h serve_codec.h serve_poll.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_qwen38_idot$(EXE): tests/test_qwen38_idot.c qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h tok_unicode.h tok_unicode_o200k.h +tests/test_qwen38_idot$(EXE): tests/test_qwen38_idot.c qwen38.c coli_env.h qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h tok_unicode.h tok_unicode_o200k.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_qwen38_serve_framing$(EXE): tests/test_qwen38_serve_framing.c qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h +tests/test_qwen38_serve_framing$(EXE): tests/test_qwen38_serve_framing.c coli_env.h qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) tests/test_qwen38_vision$(EXE): tests/test_qwen38_vision.c qwen38_vision.h st.h json.h compat.h @@ -1344,13 +1344,13 @@ qwen38-vision-serve-check: qwen38$(EXE) $(PYTHON) tools/make_edge_tiny_tokenizer.py --vocab-size 64 ./qwen38_mm_tiny $(PYTHON) tests/test_qwen38_vision_serve.py --binary ./qwen38$(EXE) --fixture ./qwen38_mm_tiny -tests/test_qwen38_prefix$(EXE): tests/test_qwen38_prefix.c qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h +tests/test_qwen38_prefix$(EXE): tests/test_qwen38_prefix.c coli_env.h qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_qwen38_metrics$(EXE): tests/test_qwen38_metrics.c qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h +tests/test_qwen38_metrics$(EXE): tests/test_qwen38_metrics.c coli_env.h qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_qwen38_native_weights$(EXE): tests/test_qwen38_native_weights.c qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h segment_runtime.c segment_runtime.h segment_adapters.h segment_adapter_internal.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h +tests/test_qwen38_native_weights$(EXE): tests/test_qwen38_native_weights.c coli_env.h qwen38.c qwen38_core.h kv_prefix.h qwen38_nfc.h qwen38_nfc_tables.h segment_runtime.c segment_runtime.h segment_adapters.h segment_adapter_internal.h st.h json.h compat.h quant.h idot.h route_trace.h serve_codec.h tok_unicode.h tok_unicode_o200k.h $(CC) $(NOCUDA_CFLAGS) $< segment_runtime.c -o $@ $(NOCUDA_LDFLAGS) tests/test_st_map$(EXE): tests/test_st_map.c st.h json.h compat.h @@ -1396,12 +1396,12 @@ tests/test_grammar$(EXE): tests/test_grammar.c grammar.h # equivalence under the shipping flags is covered by the differential dump # (old vs new rope_interleave are byte-identical); this test guards the # source-level formula equivalence and must not depend on contraction luck. -tests/test_rope_invfreq$(EXE): tests/test_rope_invfreq.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_rope_invfreq$(EXE): tests/test_rope_invfreq.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) -ffp-contract=off $< -o $@ $(LDFLAGS) # schema->GBNF compile cache (#7): grammar_reset must equal a fresh setup, and # the GrDraft.src ownership must not leak/double-free. Includes colibri.c. -tests/test_grammar_cache$(EXE): tests/test_grammar_cache.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_grammar_cache$(EXE): tests/test_grammar_cache.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # Standalone: drives a faithful miniature of moe()'s routing+accumulate and links @@ -1417,7 +1417,7 @@ tests/test_degrade_zero$(EXE): tests/test_degrade_zero.c tests/test_schema_gbnf$(EXE): tests/test_schema_gbnf.c schema_gbnf.h grammar.h json.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_spec_decode_state$(EXE): tests/test_spec_decode_state.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_spec_decode_state$(EXE): tests/test_spec_decode_state.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_decode_batch$(EXE): tests/test_decode_batch.c decode_batch.h @@ -1435,71 +1435,71 @@ tests/test_segment_runtime$(EXE): tests/test_segment_runtime.c segment_runtime.c tests/test_segment_conformance$(EXE): tests/test_segment_conformance.c tests/segment_conformance_fixtures.c tests/segment_conformance_fixtures.h segment_runtime.c segment_runtime.h $(CC) $(CFLAGS) tests/test_segment_conformance.c tests/segment_conformance_fixtures.c segment_runtime.c -o $@ $(LDFLAGS) -tests/test_inkling_serve_framing$(EXE): tests/test_inkling_serve_framing.c inkling.c st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) +tests/test_inkling_serve_framing$(EXE): tests/test_inkling_serve_framing.c inkling.c coli_env.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) $(CC) $(CFLAGS) $< $(INK_CUDA_OBJ) $(METAL_OBJ) -o $@ $(LDFLAGS) -tests/test_inkling_shared_batch$(EXE): tests/test_inkling_shared_batch.c inkling.c st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) +tests/test_inkling_shared_batch$(EXE): tests/test_inkling_shared_batch.c inkling.c coli_env.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) $(CC) $(CFLAGS) $< $(INK_CUDA_OBJ) $(METAL_OBJ) -o $@ $(LDFLAGS) # Reproducible local A/B for the shared-expert prefill path. This is timing # evidence, not a CI gate: build and run it explicitly on the target CPU. -tests/bench_inkling_shared_batch$(EXE): tests/bench_inkling_shared_batch.c inkling.c st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) +tests/bench_inkling_shared_batch$(EXE): tests/bench_inkling_shared_batch.c inkling.c coli_env.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) $(CC) $(CFLAGS) $< $(INK_CUDA_OBJ) $(METAL_OBJ) -o $@ $(LDFLAGS) -tests/test_inkling_cache_index$(EXE): tests/test_inkling_cache_index.c inkling.c st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) +tests/test_inkling_cache_index$(EXE): tests/test_inkling_cache_index.c inkling.c coli_env.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h omp_tune.h route_trace.h kv_prefix.h serve_codec.h $(INK_CUDA_OBJ) $(METAL_OBJ) $(CC) $(CFLAGS) $< $(INK_CUDA_OBJ) $(METAL_OBJ) -o $@ $(LDFLAGS) -tests/test_kimi_serve_framing$(EXE): tests/test_kimi_serve_framing.c kimi_k3.c kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h +tests/test_kimi_serve_framing$(EXE): tests/test_kimi_serve_framing.c kimi_k3.c coli_env.h kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h $(CC) $(NOCUDA_CFLAGS) $< $(VK_OBJ) -o $@ $(NOCUDA_LDFLAGS) -tests/test_kimi_cache_index$(EXE): tests/test_kimi_cache_index.c kimi_k3.c kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h +tests/test_kimi_cache_index$(EXE): tests/test_kimi_cache_index.c kimi_k3.c coli_env.h kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h $(CC) $(NOCUDA_CFLAGS) $< $(VK_OBJ) -o $@ $(NOCUDA_LDFLAGS) -tests/test_k3_chat_tools$(EXE): tests/test_k3_chat_tools.c kimi_k3.c kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h +tests/test_k3_chat_tools$(EXE): tests/test_k3_chat_tools.c kimi_k3.c coli_env.h kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h $(CC) $(NOCUDA_CFLAGS) $< $(VK_OBJ) -o $@ $(NOCUDA_LDFLAGS) # olmoe's matmul_q, not colibri's: compares the IDOT path against FP32 # ACTIVATIONS rather than an integer reference. NOCUDA_* for the same reason # the olmoe target uses it -- olmoe.c contains no COLI_CUDA code. -tests/test_olmoe_matmul_q$(EXE): tests/test_olmoe_matmul_q.c olmoe.c st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h +tests/test_olmoe_matmul_q$(EXE): tests/test_olmoe_matmul_q.c olmoe.c coli_env.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_olmoe_serve_framing$(EXE): tests/test_olmoe_serve_framing.c olmoe.c st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h +tests/test_olmoe_serve_framing$(EXE): tests/test_olmoe_serve_framing.c olmoe.c coli_env.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_olmoe_cache_index$(EXE): tests/test_olmoe_cache_index.c olmoe.c st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h +tests/test_olmoe_cache_index$(EXE): tests/test_olmoe_cache_index.c olmoe.c coli_env.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) -tests/test_qwen36_cache_index$(EXE): tests/test_qwen36_cache_index.c qwen36.c expert_ffn.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h qwen36_tier.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) +tests/test_qwen36_cache_index$(EXE): tests/test_qwen36_cache_index.c qwen36.c coli_env.h expert_ffn.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h qwen36_tier.h $(QWEN36_TIER_SRC) $(CUDA_OBJ) $(CC) $(QWEN36_CFLAGS) $< $(QWEN36_TIER_SRC) $(CUDA_OBJ) -o $@ $(QWEN36_LDFLAGS) -tests/test_idot$(EXE): tests/test_idot.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_idot$(EXE): tests/test_idot.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_i4_grouped$(EXE): tests/test_i4_grouped.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_i4_grouped$(EXE): tests/test_i4_grouped.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_stops$(EXE): tests/test_stops.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_stops$(EXE): tests/test_stops.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_cfg_topk$(EXE): tests/test_cfg_topk.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_cfg_topk$(EXE): tests/test_cfg_topk.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_topp$(EXE): tests/test_topp.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_topp$(EXE): tests/test_topp.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # bench_topp is a microbenchmark (old qsort vs new heap partial-select, #335), NOT a test # gate -- intentionally absent from TEST_BINS. Build on demand: make tests/bench_topp -tests/bench_topp$(EXE): tests/bench_topp.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/bench_topp$(EXE): tests/bench_topp.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_sample_nan$(EXE): tests/test_sample_nan.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_sample_nan$(EXE): tests/test_sample_nan.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_temp_env$(EXE): tests/test_temp_env.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_temp_env$(EXE): tests/test_temp_env.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_kv_alloc$(EXE): tests/test_kv_alloc.c colibri.c oracle.h st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h kv_fp8.h kv_tq.h +tests/test_kv_alloc$(EXE): tests/test_kv_alloc.c colibri.c coli_env.h oracle.h st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h kv_fp8.h kv_tq.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_kv_fp8$(EXE): tests/test_kv_fp8.c kv_fp8.h decode_batch.h @@ -1508,7 +1508,7 @@ tests/test_kv_fp8$(EXE): tests/test_kv_fp8.c kv_fp8.h decode_batch.h tests/test_kv_tq$(EXE): tests/test_kv_tq.c kv_tq.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_kv_disk$(EXE): tests/test_kv_disk.c colibri.c oracle.h st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h kv_fp8.h kv_tq.h +tests/test_kv_disk$(EXE): tests/test_kv_disk.c colibri.c coli_env.h oracle.h st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h kv_fp8.h kv_tq.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # fmt=6 kernel oracle: needs the generated grid table, and its fixture comes from @@ -1543,10 +1543,10 @@ fuzz-rans: tests/fuzz_rans.c rans.h tests/fuzz_rans.c -o tests/fuzz_rans -lm ./tests/fuzz_rans -tests/test_int3$(EXE): tests/test_int3.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_int3$(EXE): tests/test_int3.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_int3_load$(EXE): tests/test_int3_load.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_int3_load$(EXE): tests/test_int3_load.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_fp8_passthrough$(EXE): tests/test_fp8_passthrough.c quant.h idot.h @@ -1558,16 +1558,16 @@ tests/test_fp8_passthrough$(EXE): tests/test_fp8_passthrough.c quant.h idot.h tests/test_cuda_fmt_guard$(EXE): tests/test_cuda_fmt_guard.c backend_cuda.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_fp8_load$(EXE): tests/test_fp8_load.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_fp8_load$(EXE): tests/test_fp8_load.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_qt_addrow$(EXE): tests/test_qt_addrow.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_qt_addrow$(EXE): tests/test_qt_addrow.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_logit_nan$(EXE): tests/test_logit_nan.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h +tests/test_logit_nan$(EXE): tests/test_logit_nan.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_router_nan$(EXE): tests/test_router_nan.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h +tests/test_router_nan$(EXE): tests/test_router_nan.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_i4_acc512$(EXE): tests/test_i4_acc512.c @@ -1579,7 +1579,7 @@ tests/test_compat_direct$(EXE): tests/test_compat_direct.c compat.h tests/test_expert_store_ops$(EXE): tests/test_expert_store_ops.c expert_store.h tensor.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_native_quant$(EXE): tests/test_native_quant.c deepseek_v4.c native_quant.h tensor.h quant.h idot.h +tests/test_native_quant$(EXE): tests/test_native_quant.c deepseek_v4.c coli_env.h native_quant.h tensor.h quant.h idot.h $(CC) $(CFLAGS) -DCOLI_V4_UNIT_NATIVE_QUANT deepseek_v4.c $< -o $@ $(LDFLAGS) tests/test_edge_runtime$(EXE): tests/test_edge_runtime.c edge_runtime.c edge_runtime.h @@ -1617,45 +1617,45 @@ SEGMENT_RUNTIME_LIB = $(SEGMENT_BUILD_DIR)/libcolibri_segment_edge.a $(SEGMENT_BUILD_DIR): mkdir -p $@ -$(SEGMENT_BUILD_DIR)/glm.o: colibri.c oracle.h segment_runtime.h edge_runtime.h \ +$(SEGMENT_BUILD_DIR)/glm.o: colibri.c coli_env.h oracle.h segment_runtime.h edge_runtime.h \ segment_adapters.h edge_adapters.h segment_adapter_internal.h \ edge_adapter_internal.h edge_tok_internal.h st.h | $(SEGMENT_BUILD_DIR) $(CC) $(SEGMENT_CPU_CFLAGS) -DCOLIBRI_NO_MAIN -c colibri.c -o $@ -$(SEGMENT_BUILD_DIR)/glm53.o: glm53.c segment_runtime.h edge_runtime.h \ +$(SEGMENT_BUILD_DIR)/glm53.o: glm53.c coli_env.h segment_runtime.h edge_runtime.h \ segment_adapters.h edge_adapters.h segment_adapter_internal.h \ edge_adapter_internal.h st.h quant.h tok.h hyper_connections.h \ delta_attention.h sparse_index.h vision_tower.h | $(SEGMENT_BUILD_DIR) $(CC) $(SEGMENT_CPU_CFLAGS) -DGLM53_NO_MAIN -c glm53.c -o $@ -$(SEGMENT_BUILD_DIR)/inkling.o: inkling.c segment_runtime.h edge_runtime.h \ +$(SEGMENT_BUILD_DIR)/inkling.o: inkling.c coli_env.h segment_runtime.h edge_runtime.h \ segment_adapters.h edge_adapters.h segment_adapter_internal.h \ edge_adapter_internal.h edge_tok_internal.h st.h | $(SEGMENT_BUILD_DIR) $(CC) $(SEGMENT_CPU_CFLAGS) -DINKLING_NO_MAIN -c inkling.c -o $@ -$(SEGMENT_BUILD_DIR)/kimi.o: kimi_k3.c segment_runtime.h edge_runtime.h \ +$(SEGMENT_BUILD_DIR)/kimi.o: kimi_k3.c coli_env.h segment_runtime.h edge_runtime.h \ segment_adapters.h edge_adapters.h segment_adapter_internal.h \ edge_adapter_internal.h edge_tok_internal.h st.h | $(SEGMENT_BUILD_DIR) $(CC) $(SEGMENT_CPU_CFLAGS) -DKIMI_K3_NO_MAIN -c kimi_k3.c -o $@ -$(SEGMENT_BUILD_DIR)/olmoe.o: olmoe.c segment_runtime.h edge_runtime.h \ +$(SEGMENT_BUILD_DIR)/olmoe.o: olmoe.c coli_env.h segment_runtime.h edge_runtime.h \ segment_adapters.h edge_adapters.h segment_adapter_internal.h \ edge_adapter_internal.h edge_tok_internal.h st.h | $(SEGMENT_BUILD_DIR) $(CC) $(SEGMENT_CPU_CFLAGS) -DOLMOE_NO_MAIN -c olmoe.c -o $@ -$(SEGMENT_BUILD_DIR)/qwen36.o: qwen36.c segment_runtime.h edge_runtime.h \ +$(SEGMENT_BUILD_DIR)/qwen36.o: qwen36.c coli_env.h segment_runtime.h edge_runtime.h \ segment_adapters.h edge_adapters.h segment_adapter_internal.h \ edge_adapter_internal.h st.h | $(SEGMENT_BUILD_DIR) $(CC) $(SEGMENT_CPU_CFLAGS) -DQWEN36_NO_MAIN -c qwen36.c -o $@ -$(SEGMENT_BUILD_DIR)/qwen38.o: qwen38.c qwen38_core.h kv_prefix.h segment_runtime.h \ +$(SEGMENT_BUILD_DIR)/qwen38.o: qwen38.c coli_env.h qwen38_core.h kv_prefix.h segment_runtime.h \ segment_adapters.h segment_adapter_internal.h edge_runtime.h \ edge_adapters.h edge_adapter_internal.h st.h json.h compat.h quant.h \ qwen38_nfc.h qwen38_nfc_tables.h route_trace.h tok_unicode.h \ tok_unicode_o200k.h | $(SEGMENT_BUILD_DIR) $(CC) $(SEGMENT_CPU_CFLAGS) -DQWEN38_NO_MAIN -c qwen38.c -o $@ -$(SEGMENT_V4_OBJS): $(SEGMENT_BUILD_DIR)/%.o: deepseek_v4.c deepseek_v4.h \ +$(SEGMENT_V4_OBJS): $(SEGMENT_BUILD_DIR)/%.o: deepseek_v4.c coli_env.h deepseek_v4.h \ deepseek_v4_internal.h segment_runtime.h segment_adapters.h \ edge_runtime.h edge_adapters.h segment_adapter_internal.h \ edge_adapter_internal.h edge_tok_internal.h st.h | $(SEGMENT_BUILD_DIR) @@ -1782,7 +1782,7 @@ V4_TEST_LINK_OBJS += COLI_V4_UNIT_GPU.o backend_loader_dsv4.o V4_TEST_EXTRA_TARGETS = COLI_V4_UNIT_GPU.o backend_loader_dsv4.o endif -tests/test_deepseek_v4$(EXE): tests/test_deepseek_v4.c deepseek_v4.c deepseek_v4.h compat.h \ +tests/test_deepseek_v4$(EXE): tests/test_deepseek_v4.c deepseek_v4.c coli_env.h deepseek_v4.h compat.h \ Makefile.deepseek-v4.units Makefile.deepseek-v4 $(MAKE) -f Makefile.deepseek-v4 ARCH=$(ARCH) deepseek-v4-test-objs \ COLI_V4_UNIT_ST.o COLI_V4_UNIT_CONFIG.o COLI_V4_UNIT_MATH.o COLI_V4_UNIT_SPARSE_ATTENTION.o \ @@ -1807,16 +1807,16 @@ V4_OWNERSHIP_OBJS = \ $(V4_OWN_DIR): mkdir -p $(V4_OWN_DIR) -$(V4_OWN_DIR)/COLI_V4_UNIT_RUNTIME.o: deepseek_v4.c deepseek_v4.h deepseek_v4_internal.h | $(V4_OWN_DIR) +$(V4_OWN_DIR)/COLI_V4_UNIT_RUNTIME.o: deepseek_v4.c coli_env.h deepseek_v4.h deepseek_v4_internal.h | $(V4_OWN_DIR) $(CC) $(V4_OWN_CFLAGS) -DCOLI_V4_UNIT_RUNTIME -c deepseek_v4.c -o $@ -$(V4_OWN_DIR)/COLI_V4_UNIT_CONFIG.o: deepseek_v4.c deepseek_v4.h deepseek_v4_internal.h | $(V4_OWN_DIR) +$(V4_OWN_DIR)/COLI_V4_UNIT_CONFIG.o: deepseek_v4.c coli_env.h deepseek_v4.h deepseek_v4_internal.h | $(V4_OWN_DIR) $(CC) $(V4_OWN_CFLAGS) -DCOLI_V4_UNIT_CONFIG -c deepseek_v4.c -o $@ -$(V4_OWN_DIR)/COLI_V4_UNIT_ST.o: deepseek_v4.c deepseek_v4.h deepseek_v4_internal.h st.h | $(V4_OWN_DIR) +$(V4_OWN_DIR)/COLI_V4_UNIT_ST.o: deepseek_v4.c coli_env.h deepseek_v4.h deepseek_v4_internal.h st.h | $(V4_OWN_DIR) $(CC) $(V4_OWN_CFLAGS) -DCOLI_V4_UNIT_ST -c deepseek_v4.c -o $@ -$(V4_OWN_DIR)/COLI_V4_UNIT_NATIVE_QUANT.o: deepseek_v4.c deepseek_v4.h deepseek_v4_internal.h quant.h idot.h | $(V4_OWN_DIR) +$(V4_OWN_DIR)/COLI_V4_UNIT_NATIVE_QUANT.o: deepseek_v4.c coli_env.h deepseek_v4.h deepseek_v4_internal.h quant.h idot.h | $(V4_OWN_DIR) $(CC) $(V4_OWN_CFLAGS) -DCOLI_V4_UNIT_NATIVE_QUANT -c deepseek_v4.c -o $@ # The engine (RUNTIME unit) opens its expert store through the pluggable @@ -1828,7 +1828,7 @@ $(V4_OWN_DIR)/expert_store_registry.o: expert_store_registry.c expert_store_regi tests/test_v4_ownership$(EXE): tests/test_v4_ownership.c $(V4_OWNERSHIP_OBJS) $(CC) $(V4_OWN_CFLAGS) $< $(V4_OWNERSHIP_OBJS) -o $@ -pthread $(LDFLAGS) -tests/test_v4_serve_framing$(EXE): tests/test_v4_serve_framing.c deepseek_v4.c \ +tests/test_v4_serve_framing$(EXE): tests/test_v4_serve_framing.c deepseek_v4.c coli_env.h \ deepseek_v4.h deepseek_v4_internal.h serve_codec.h Makefile.deepseek-v4 Makefile.deepseek-v4.units $(MAKE) -f Makefile.deepseek-v4 ARCH=$(ARCH) $@ @@ -1924,28 +1924,28 @@ tests/test_qwen36_tier_dense$(EXE): tests/test_qwen36_tier_dense.c tests/qwen36_ $(CC) $(CFLAGS) -DCOLI_CUDA $< -o $@ $(LDFLAGS) # DeltaNet input projection batching, state parity and block failure fallback. -tests/test_qwen36_dnproj_batch$(EXE): tests/test_qwen36_dnproj_batch.c tests/qwen36_fake_cuda.h qwen36.c qwen36_tier.c qwen36_tier.h backend_cuda.h compat.h quant.h +tests/test_qwen36_dnproj_batch$(EXE): tests/test_qwen36_dnproj_batch.c tests/qwen36_fake_cuda.h qwen36.c coli_env.h qwen36_tier.c qwen36_tier.h backend_cuda.h compat.h quant.h $(CC) $(CFLAGS) -DCOLI_CUDA $< -o $@ $(LDFLAGS) # the automatic trunk placement can be withdrawn after the startup probe (fake backend). tests/test_qwen36_tier_withdraw$(EXE): tests/test_qwen36_tier_withdraw.c tests/qwen36_fake_cuda.h qwen36_tier.c qwen36_tier.h backend_cuda.h $(CC) $(CFLAGS) -DCOLI_CUDA $< -o $@ $(LDFLAGS) -tests/test_qwen36_tier_int8_engine$(EXE): tests/test_qwen36_tier_int8_engine.c tests/qwen36_fake_cuda.h qwen36.c expert_ffn.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h +tests/test_qwen36_tier_int8_engine$(EXE): tests/test_qwen36_tier_int8_engine.c tests/qwen36_fake_cuda.h qwen36.c coli_env.h expert_ffn.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h $(CC) $(CFLAGS) -DCOLI_CUDA $< -o $@ $(LDFLAGS) # dnout / attnproj / shexp offered, placed and served from VRAM (fake backend). -tests/test_qwen36_trunk_dense$(EXE): tests/test_qwen36_trunk_dense.c tests/qwen36_fake_cuda.h qwen36.c expert_ffn.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h +tests/test_qwen36_trunk_dense$(EXE): tests/test_qwen36_trunk_dense.c tests/qwen36_fake_cuda.h qwen36.c coli_env.h expert_ffn.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h $(CC) $(CFLAGS) -DCOLI_CUDA $< -o $@ $(LDFLAGS) # #1391: il decode path deve offrire gli esperti int8 al tier, non solo il warmstart -tests/test_qwen36_tier_int8_decode$(EXE): tests/test_qwen36_tier_int8_decode.c tests/qwen36_fake_cuda.h qwen36.c expert_ffn.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h +tests/test_qwen36_tier_int8_decode$(EXE): tests/test_qwen36_tier_int8_decode.c tests/qwen36_fake_cuda.h qwen36.c coli_env.h expert_ffn.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h $(CC) $(CFLAGS) -DCOLI_CUDA $< -o $@ $(LDFLAGS) # The qwen38 engine through its own main() on the fake backend: tier start # from the FP8 fixture, reduced CPU list, qt_note on recycled slots, oracle # tokens unchanged. Needs the fixture (qwen38-tiny-fp8-generate). -tests/test_qwen38_tier_engine$(EXE): tests/test_qwen38_tier_engine.c tests/qwen36_fake_cuda.h qwen38.c qwen38_core.h kv_prefix.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h quant.h idot.h route_trace.h +tests/test_qwen38_tier_engine$(EXE): tests/test_qwen38_tier_engine.c tests/qwen36_fake_cuda.h qwen38.c coli_env.h qwen38_core.h kv_prefix.h qwen36_tier.c qwen36_tier.h backend_cuda.h cli_args.h st.h json.h compat.h quant.h idot.h route_trace.h $(CC) $(CFLAGS) -DCOLI_CUDA $< -o $@ $(LDFLAGS) tests/test_serve_poll$(EXE): tests/test_serve_poll.c serve_poll.h @@ -1964,15 +1964,15 @@ tests/test_mem_available$(EXE): tests/test_mem_available.c compat.h tests/test_798_guards$(EXE): tests/test_798_guards.c st.h json.h compat.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_dsa_select$(EXE): tests/test_dsa_select.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_dsa_select$(EXE): tests/test_dsa_select.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_corpus_draft$(EXE): tests/test_corpus_draft.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_corpus_draft$(EXE): tests/test_corpus_draft.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_cap_precedence$(EXE): tests/test_cap_precedence.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_cap_precedence$(EXE): tests/test_cap_precedence.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_mirror_stripe_split$(EXE): tests/test_mirror_stripe_split.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_mirror_stripe_split$(EXE): tests/test_mirror_stripe_split.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_v4_hybrid_policy$(EXE): tests/test_v4_hybrid_policy.c deepseek_v4_hybrid.h hybrid_split.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) @@ -1983,29 +1983,29 @@ tests/test_k3_fill_budget$(EXE): tests/test_k3_fill_budget.c hybrid_split.h tests/test_v4_bank_pair$(EXE): tests/test_v4_bank_pair.c deepseek_v4_bank_pair.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_ram_clamp$(EXE): tests/test_ram_clamp.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_ram_clamp$(EXE): tests/test_ram_clamp.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_cap_mixed_width$(EXE): tests/test_cap_mixed_width.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_cap_mixed_width$(EXE): tests/test_cap_mixed_width.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_eslot_inflight$(EXE): tests/test_eslot_inflight.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_eslot_inflight$(EXE): tests/test_eslot_inflight.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_glm_cache_index$(EXE): tests/test_glm_cache_index.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_glm_cache_index$(EXE): tests/test_glm_cache_index.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_ssd_probe$(EXE): tests/test_ssd_probe.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_ssd_probe$(EXE): tests/test_ssd_probe.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # bench_dsa_select is a microbenchmark (old qsort vs new quickselect partial-select, #356), # NOT a test gate -- intentionally absent from TEST_BINS. Build on demand: make tests/bench_dsa_select -tests/bench_dsa_select$(EXE): tests/bench_dsa_select.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/bench_dsa_select$(EXE): tests/bench_dsa_select.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # bench_router_select is a microbenchmark (duplicate-prefix scan vs marked-score scan), # not a test gate. Build on demand: make tests/bench_router_select. -tests/bench_router_select$(EXE): tests/bench_router_select.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/bench_router_select$(EXE): tests/bench_router_select.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # bench_indexer_allocations: microbenchmark (DeepSeek V4 indexer malloc vs persistent arena scratch), NOT a test gate. @@ -2015,43 +2015,46 @@ tests/bench_indexer_allocations$(EXE): tests/bench_indexer_allocations.c # bench_idot: microbenchmark (single-acc vs independent-acc AVX-VNNI idot), NOT a test gate. # Build on demand on an AVX-VNNI CPU: make tests/bench_idot ARCH=native -tests/bench_idot$(EXE): tests/bench_idot.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/bench_idot$(EXE): tests/bench_idot.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # bench_i4p_gidot: microbenchmark (per-row vs multi-row/AMX K1b grouped planar IDOT), NOT a test gate. # Build on demand: make tests/bench_i4p_gidot ARCH=native -tests/bench_i4p_gidot$(EXE): tests/bench_i4p_gidot.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/bench_i4p_gidot$(EXE): tests/bench_i4p_gidot.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # bench_gemv_stream: microbenchmark (decode-regime GEMV bandwidth vs the read ceiling; # frozen-baseline + deinterleaved-x candidate A/B), NOT a test gate. # Build on demand: make tests/bench_gemv_stream ARCH=native -tests/bench_gemv_stream$(EXE): tests/bench_gemv_stream.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/bench_gemv_stream$(EXE): tests/bench_gemv_stream.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # bench_mla_simd: microbenchmark (scalar vs AVX2/NEON MLA-absorb reductions, #442), # NOT a test gate. Build on demand: make tests/bench_mla_simd -tests/bench_mla_simd$(EXE): tests/bench_mla_simd.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/bench_mla_simd$(EXE): tests/bench_mla_simd.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_uring$(EXE): tests/test_uring.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h +tests/test_uring$(EXE): tests/test_uring.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h route_trace.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_pipe_block$(EXE): tests/test_pipe_block.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h +tests/test_pipe_block$(EXE): tests/test_pipe_block.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_pilot_ring$(EXE): tests/test_pilot_ring.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_pilot_ring$(EXE): tests/test_pilot_ring.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_moe_gs_guard$(EXE): tests/test_moe_gs_guard.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_moe_gs_guard$(EXE): tests/test_moe_gs_guard.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_omp_tune$(EXE): tests/test_omp_tune.c omp_tune.h compat.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +tests/test_env_registry$(EXE): tests/test_env_registry.c coli_env.h + $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) + tests/test_compat_env$(EXE): tests/test_compat_env.c compat.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_kvb_notice$(EXE): tests/test_kvb_notice.c colibri.c oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h +tests/test_kvb_notice$(EXE): tests/test_kvb_notice.c colibri.c coli_env.h oracle.h st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h quant.h idot.h sample.h kv_persist.h telemetry.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) # Standalone: proves the group-scaled int8 GEMV keeps every row's float @@ -2081,13 +2084,13 @@ tests/test_qgemv_sse41$(EXE): tests/test_qgemv.c qgemv.h sse41_kernels.h # olmoe's dot_i8_16 (ARM NEON/AVX2/SSE4.1 variants): must be bit-exact against # a scalar int8 reference -- pure integer arithmetic, no tolerance needed. # NOCUDA_* for the same reason the other olmoe.c-including test rules use it. -tests/test_olmoe_dot_i8_16$(EXE): tests/test_olmoe_dot_i8_16.c olmoe.c sse41_kernels.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h +tests/test_olmoe_dot_i8_16$(EXE): tests/test_olmoe_dot_i8_16.c olmoe.c coli_env.h sse41_kernels.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h $(CC) $(NOCUDA_CFLAGS) $< -o $@ $(NOCUDA_LDFLAGS) # Same gate, forced onto the SSE4.1 tier: overrides the host's default -march # so the SSE4.1 body in olmoe.c's dot_i8_16 is actually exercised even on a # devbox that would otherwise always pick the AVX2 tier. -tests/test_olmoe_dot_i8_16_sse41$(EXE): tests/test_olmoe_dot_i8_16.c olmoe.c sse41_kernels.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h +tests/test_olmoe_dot_i8_16_sse41$(EXE): tests/test_olmoe_dot_i8_16.c olmoe.c coli_env.h sse41_kernels.h st.h json.h compat.h sample.h tok.h tok_unicode.h tok_unicode_o200k.h omp_tune.h route_trace.h serve_codec.h $(CC) $(NOCUDA_CFLAGS) -msse4.1 -mno-avx2 -mno-fma $< -o $@ $(NOCUDA_LDFLAGS) test-c: $(TEST_BINS) @@ -2165,8 +2168,17 @@ test-asan: @$(ASAN_ENV) $(MAKE) test-c EXTRA_CFLAGS="$(ASAN_CFLAGS)" EXTRA_LDFLAGS="$(ASAN_LDFLAGS)" @echo "test-asan: suite clean under ASan + UBSan" +# --- environment-variable registry -------------------------------------- +# c/coli_env.h is the single list of every variable the engines read. This +# target asserts it still matches the sources: a getenv() with no row, a row +# nothing reads, an unsorted table (coli_env_find binary-searches it) or a +# duplicate name all fail here. Needs no build, no model and no GPU. +check-env: + @$(PYTHON) tools/check_env_registry.py + # Local validation: one portable CPU build and dependency-free tests. check: + $(MAKE) check-env $(MAKE) clean $(MAKE) portable $(MAKE) test @@ -2220,13 +2232,14 @@ bench: iobench$(EXE) .PHONY: bench-omp-grain .PHONY: test-asan .PHONY: dsv4-cuda-test cuda-dsv4-dll cuda-dsv4-dg-dll dsv4-cuda-loader-test +.PHONY: check-env tests/test_kv_prefix$(EXE): tests/test_kv_prefix.c kv_prefix.h $(CC) $(CFLAGS) tests/test_kv_prefix.c -o tests/test_kv_prefix$(EXE) $(LDFLAGS) -tests/test_kimi_request_state$(EXE): tests/test_kimi_request_state.c kimi_k3.c kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h +tests/test_kimi_request_state$(EXE): tests/test_kimi_request_state.c kimi_k3.c coli_env.h kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h $(CC) $(NOCUDA_CFLAGS) tests/test_kimi_request_state.c $(VK_OBJ) -o tests/test_kimi_request_state$(EXE) $(NOCUDA_LDFLAGS) # Kimi CUDA dispatch/fallback with a fake backend; no CUDA toolkit required. -tests/test_kimi_cuda_expert$(EXE): tests/test_kimi_cuda_expert.c kimi_k3.c backend_cuda.h kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h +tests/test_kimi_cuda_expert$(EXE): tests/test_kimi_cuda_expert.c kimi_k3.c coli_env.h backend_cuda.h kv_prefix.h serve_codec.h st.h json.h tok.h tok_unicode.h tok_unicode_o200k.h compat.h quant.h idot.h omp_tune.h route_trace.h $(CC) $(NOCUDA_CFLAGS) -DCOLI_CUDA $< $(VK_OBJ) -o $@ $(NOCUDA_LDFLAGS) diff --git a/c/Makefile.deepseek-v4 b/c/Makefile.deepseek-v4 index a7858363f..0772d0e2f 100644 --- a/c/Makefile.deepseek-v4 +++ b/c/Makefile.deepseek-v4 @@ -245,27 +245,27 @@ $(V4_BINARY): $(V4_OBJS) $(REGISTRY_OBJ): expert_store_registry.c expert_store_registry.h expert_store.h $(CC) $(CFLAGS) -c expert_store_registry.c -o $@ -$(TARGET_OBJS) $(TEST_UNIT_OBJS): %.o: deepseek_v4.c deepseek_v4.h \ +$(TARGET_OBJS) $(TEST_UNIT_OBJS): %.o: deepseek_v4.c coli_env.h deepseek_v4.h \ deepseek_v4_internal.h deepseek_v4_dspark.inc st.h json.h compat.h tensor.h quant.h \ route_trace.h \ native_quant.h native_quant_batch.h native_quant_dual.h \ native_quant_fp4_rows16.h expert_store_registry.h $(CC) $(CFLAGS) -D$* -c deepseek_v4.c -o $@ -$(V4_HOT_TEST_OBJ): deepseek_v4.c deepseek_v4.h deepseek_v4_internal.h \ +$(V4_HOT_TEST_OBJ): deepseek_v4.c coli_env.h deepseek_v4.h deepseek_v4_internal.h \ st.h json.h compat.h tensor.h quant.h route_trace.h \ native_quant.h native_quant_fp4_rows16.h expert_store_registry.h $(CC) $(CFLAGS) -DCOLI_V4_TEST_HOOKS \ -DCOLI_V4_UNIT_EXPERT_STORE_HOT_ROWS16 -c deepseek_v4.c -o $@ -$(V4_BATCH_TEST_OBJ): deepseek_v4.c deepseek_v4.h deepseek_v4_internal.h \ +$(V4_BATCH_TEST_OBJ): deepseek_v4.c coli_env.h deepseek_v4.h deepseek_v4_internal.h \ tensor.h quant.h native_quant.h native_quant_batch.h $(CC) $(CFLAGS) -DCOLI_V4_TEST_HOOKS \ -DCOLI_V4_UNIT_NATIVE_QUANT_BATCH -c deepseek_v4.c -o $@ COLI_V4_UNIT_GENERATE_STATS.o: serve_codec.h -$(V4_SERVE_TEST): tests/test_v4_serve_framing.c deepseek_v4.c deepseek_v4.h \ +$(V4_SERVE_TEST): tests/test_v4_serve_framing.c deepseek_v4.c coli_env.h deepseek_v4.h \ deepseek_v4_internal.h serve_codec.h $(V4_SERVE_TEST_OBJS) $(CC) $(CFLAGS) $< $(V4_SERVE_TEST_OBJS) -o $@ $(LDFLAGS) diff --git a/c/coli_env.h b/c/coli_env.h new file mode 100644 index 000000000..f75b3347d --- /dev/null +++ b/c/coli_env.h @@ -0,0 +1,619 @@ +#ifndef COLI_ENV_H +#define COLI_ENV_H +/* coli_env.h — the single place that knows which environment variables exist. + * + * WHY THIS EXISTS + * --------------- + * The engines read hundreds of environment variables from getenv() call sites + * scattered across the sources, and until this header there was no list of + * them anywhere in the code. (`make check-env` prints the current count; it is + * the one number here that cannot go stale, because it is computed.) + * Two consequences, both of which cost real debugging time: + * + * COLI_PREFIL_CHUNK=512 ./colibri ... <- typo: silently ignored + * K3_BITS=8 ./colibri ... <- wrong engine: silently ignored + * + * Neither prints anything. The run proceeds with the default, produces + * perfectly plausible output, and the number you write down is wrong. That is + * the failure mode this header removes: coli_env_check() is called once at + * startup, compares the process environment against the table below, and says + * so. + * + * This is the approach vLLM converged on (vllm/envs.py): one declaration point, + * one prefix convention, validation at the boundary. It is worth stating that + * the exact count is not the problem; the absence of a registry was. + * + * WHAT IT DELIBERATELY DOES NOT DO + * -------------------------------- + * It does not replace the getenv() calls. Rewriting 187 read sites is a + * mechanical but large change with a real chance of altering a default by + * accident; it belongs in its own commit, engine by engine, and this table is + * the precondition for doing it safely. Here the table is checked against the + * source by `make check-env` (and CI), so it cannot drift in the meantime. + * + * KEEPING IT HONEST + * ----------------- + * Read a new variable anywhere and `make check-env` fails until it is in the + * table. Remove one and it fails until the row is gone. There is no way to + * update the code and forget the registry. + */ + +#include +#include +#include + +/* The environment block. POSIX declares `environ` but not in any header you are + * allowed to rely on; Windows spells it _environ; on macOS a program linked + * against the shared libc must go through _NSGetEnviron(). */ +#if defined(_WIN32) +#define COLI_ENVIRON _environ +#elif defined(__APPLE__) +#include +#define COLI_ENVIRON (*_NSGetEnviron()) +#else +extern char **environ; +#define COLI_ENVIRON environ +#endif + +/* Value shape. Only used for reporting today -- coli_env_dump prints it so a + * "why did my float get truncated" question answers itself. */ +typedef enum { CE_BOOL, CE_INT, CE_FLOAT, CE_STR, CE_PATH } ColiEnvType; + +/* Which binaries read the variable. The engines do NOT share a knob set: K3_* + * is kimi_k3 only, INK_* is inkling only, and a few live in headers everyone + * includes (route_trace.h, rans.h, omp_tune.h) and so are CE_ALL. */ +#define CE_COLIBRI 0x1 +#define CE_KIMI 0x2 +#define CE_INKLING 0x4 +#define CE_OLMOE 0x8 +#define CE_DSV4 0x10 +#define CE_QWEN 0x20 +#define CE_GLM53 0x40 +#define CE_QWEN38 0x80 +#define CE_DSV41 0x100 +/* CE_ALL is retained for declarations shared by the original four engines. + * New rows use explicit engine masks derived from their actual call sites. */ +#define CE_ALL (CE_COLIBRI | CE_KIMI | CE_INKLING | CE_OLMOE) + +#define CE_DEPRECATED 0x1 /* still read; `replacement` names what to use */ + +typedef struct { + const char *name; + unsigned char type; + unsigned short engines; + unsigned char flags; + const char *replacement; /* non-NULL only for CE_DEPRECATED */ +} ColiEnvVar; + +/* Sorted by name; check-env asserts the ordering so a merge cannot silently + * introduce a duplicate. */ +static const ColiEnvVar coli_env_table[] = { + {"ABLATE_OUT", CE_PATH , CE_COLIBRI , 0 , NULL}, + {"ABLATE_SCORE", CE_STR , CE_COLIBRI , 0 , NULL}, + {"ABSORB", CE_INT , CE_COLIBRI , 0 , NULL}, + {"AMX", CE_BOOL, CE_COLIBRI | CE_DSV4 | CE_DSV41 | CE_GLM53 | CE_KIMI | CE_QWEN | CE_QWEN38, 0, NULL}, + {"AMX_S_MIN", CE_INT, CE_COLIBRI | CE_DSV4 | CE_DSV41 | CE_GLM53 | CE_KIMI | CE_QWEN | CE_QWEN38, 0, NULL}, + {"AUTOPIN", CE_INT , CE_COLIBRI | CE_KIMI , 0 , NULL}, + {"CACHE_ROUTE", CE_INT , CE_COLIBRI | CE_QWEN, 0 , NULL}, + {"CAP", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CAP_RAISE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CHAT", CE_STR , CE_OLMOE , 0 , NULL}, + {"CHAT_TEMPLATE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CLUSTER_WORKERS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"CLUSTER_WORKER_PORT", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLIBRI_RESIDENT", CE_STR , CE_QWEN , 0 , NULL}, + {"COLI_ANS_DIRECT", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_ANS_PACK", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_ANS_PROFILE", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_ANS_SIDECAR", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_CORPUS_K", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CORPUS_MINACC", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA", CE_INT , CE_COLIBRI | CE_QWEN | CE_QWEN38, 0 , NULL}, + {"COLI_CUDA_ASYNC", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_ATTN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_ATTN_BATCH", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_CUDA_ATTN_PREFIX", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_ATTN_SHARD", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_DUAL_PROJ", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_F8_WARP", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_MOE_BATCH", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_CUDA_MOE_BATCH_MIN", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_CUDA_MOE_DOUBLE", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_CUDA_MTP", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_PIPE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_PIPE_SHARD", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_PIPE_S_MIN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_PROFILE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_RESID", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_ROUTER", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_SHARED_W4A16", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_SHARED_W4A16_MIN_ROWS", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_TC_INT4", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_TC_MIN_ROWS", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_TC_W4A16", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_TC_W4A16_MIN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_CUDA_W4_PACKED", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_DENSE_BITS", CE_INT, CE_QWEN, 0, NULL}, + {"COLI_DENSE_I8", CE_STR , CE_QWEN , 0 , NULL}, + {"COLI_DENSE_IDOT", CE_BOOL, CE_QWEN, 0, NULL}, + {"COLI_DENSE_INT4", CE_STR, CE_QWEN, 0, NULL}, + {"COLI_DISKCLASS_WINDOW", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_DISK_WEIGHTS", CE_STR , CE_COLIBRI | CE_DSV4 | CE_DSV41 | CE_GLM53, 0 , NULL}, + {"COLI_DRAFT_CORPUS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_DSA_GATHER", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_DSV4_DLL", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_ENV_DUMP", CE_BOOL , CE_COLIBRI | CE_KIMI | CE_INKLING | CE_OLMOE | CE_DSV4 | CE_QWEN | CE_GLM53 | CE_QWEN38 | CE_DSV41, 0 , NULL}, + {"COLI_ENV_STRICT", CE_BOOL , CE_COLIBRI | CE_KIMI | CE_INKLING | CE_OLMOE | CE_DSV4 | CE_QWEN | CE_GLM53 | CE_QWEN38 | CE_DSV41, 0 , NULL}, + {"COLI_EXPERT_STORE", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_GEMM_CHUNK", CE_STR , CE_ALL , 0 , NULL}, + {"COLI_GPU", CE_STR , CE_COLIBRI | CE_QWEN | CE_QWEN38, 0 , NULL}, + {"COLI_GPUS", CE_STR , CE_COLIBRI | CE_QWEN | CE_QWEN38, 0 , NULL}, + {"COLI_GPU_FAIL_AFTER", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_GROUP_ASYNC", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_K3_CKPT", CE_STR , CE_KIMI , 0 , NULL}, + {"COLI_K3_CKPT_DIR", CE_STR , CE_KIMI , 0 , NULL}, + {"COLI_KEEP_F32", CE_STR , CE_QWEN , 0 , NULL}, + {"COLI_KEEP_INT8", CE_STR , CE_QWEN , 0 , NULL}, + {"COLI_KV_PREFIX", CE_BOOL, CE_DSV41 | CE_OLMOE | CE_QWEN, 0, NULL}, + {"COLI_KV_SHARE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_LMHEAD_GPU", CE_INT, CE_QWEN | CE_QWEN38, 0, NULL}, + {"COLI_LOGIT_DUMP", CE_STR , CE_ALL | CE_COLIBRI | CE_OLMOE, 0 , NULL}, + {"COLI_LOGIT_GAP", CE_BOOL , CE_ALL | CE_COLIBRI | CE_OLMOE, 0 , NULL}, + {"COLI_MAP_EXPERTS", CE_BOOL, CE_COLIBRI | CE_DSV4 | CE_DSV41 | CE_GLM53 | CE_INKLING | CE_KIMI | CE_OLMOE | CE_QWEN | CE_QWEN38, 0, NULL}, + {"COLI_METAL", CE_INT , CE_COLIBRI | CE_INKLING | CE_GLM53, 0 , NULL}, + {"COLI_METAL_GEMM_MIN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_METAL_MOE_EXACT", CE_BOOL , CE_COLIBRI , 0 , NULL}, + {"COLI_METAL_PREFILL", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_METAL_RESSET", CE_INT , CE_ALL , 0 , NULL}, + {"COLI_METAL_SPIN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_METAL_UNTRACKED", CE_INT , CE_ALL , 0 , NULL}, + {"COLI_MIR_STRIPE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_MMAP", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_MODEL", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_MODEL_DIRS", CE_PATH , CE_COLIBRI | CE_DSV4 | CE_DSV41, 0 , NULL}, + {"COLI_MODEL_MIRROR", CE_STR , CE_COLIBRI | CE_DSV4 | CE_DSV41 | CE_GLM53, 0 , NULL}, + {"COLI_MTP_GUARD_PCT", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_MTP_GUARD_WINDOW", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_NO_FUSED_PAIR", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_NO_OMP_TUNE", CE_STR , CE_COLIBRI | CE_INKLING | CE_DSV4 | CE_DSV41 | CE_GLM53 | CE_KIMI | CE_OLMOE | CE_QWEN | CE_QWEN38, 0 , NULL}, + {"COLI_NUMA", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_OMP_TUNED", CE_STR , CE_COLIBRI | CE_INKLING , 0 , NULL}, + {"COLI_PIN_SLOTS", CE_INT, CE_COLIBRI | CE_DSV41 | CE_GLM53 | CE_INKLING | CE_KIMI | CE_OLMOE | CE_QWEN | CE_QWEN38, 0, NULL}, + {"COLI_PIPE_BLOCK", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_PLACE", CE_STR, CE_QWEN | CE_QWEN38, 0, NULL}, + {"COLI_POLICY", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_PREFILL_CHUNK", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_PREFIX_LOG", CE_BOOL, CE_DSV41 | CE_OLMOE | CE_QWEN, 0, NULL}, + {"COLI_PROMPT", CE_STR , CE_ALL | CE_COLIBRI, 0 , NULL}, + {"COLI_RAM_OVERCOMMIT", CE_INT , CE_COLIBRI | CE_KIMI , 0 , NULL}, + {"COLI_RTOP8", CE_STR , CE_ALL , 0 , NULL}, + {"COLI_SERVE_ALL_STOPS", CE_STR , CE_ALL | CE_COLIBRI | CE_OLMOE, 0 , NULL}, + {"COLI_SLAB_SHRINK", CE_BOOL , CE_COLIBRI , 0 , NULL}, + {"COLI_SSD_FAST_GBS", CE_FLOAT , CE_COLIBRI , 0 , NULL}, + {"COLI_TEMP", CE_FLOAT , CE_COLIBRI | CE_KIMI | CE_OLMOE , 0 , NULL}, + {"COLI_TIMERS", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"COLI_TRUNK_PROBE", CE_BOOL, CE_QWEN, 0, NULL}, + {"COLI_USAGE", CE_STR , CE_KIMI | CE_OLMOE | CE_QWEN38 | CE_GLM53, 0 , NULL}, + {"COLI_USAGE_DECAY", CE_FLOAT , CE_KIMI | CE_QWEN38 | CE_COLIBRI | CE_DSV4 | CE_GLM53 | CE_INKLING | CE_OLMOE, 0 , NULL}, + {"COLI_V4_AUTOPIN", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"COLI_V4_DIRECT", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"COLI_V4_EXPERT_PREFETCH", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"COLI_V4_MARKOV_BLOCK", CE_INT , CE_DSV4 , 0 , NULL}, + {"COLI_V4_MARKOV_KEEP", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"COLI_V4_MARKOV_SPEC", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"COLI_V4_PREFILL_POOL", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_V4_PREWARM", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"COLI_V4_ROWS16", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_V4_SAVE_USAGE", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"COLI_V4_SHARED_BATCH", CE_STR , CE_DSV4 , 0 , NULL}, + {"COLI_VK_ATTN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_DENSE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_DEV2", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_EXPERTS", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_EXPERTS2", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_QPREP", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_RESERVE2_GB", CE_FLOAT , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_RESERVE_GB", CE_FLOAT , CE_COLIBRI , 0 , NULL}, + {"COLI_VK_SHADERS", CE_STR , CE_COLIBRI | CE_KIMI | CE_GLM53 , 0 , NULL}, + {"COLI_VK_SPIN_US", CE_STR , CE_ALL , 0 , NULL}, + {"COLI_VK_TEST_BALLAST", CE_INT , CE_ALL , 0 , NULL}, + {"COLI_VULKAN", CE_INT , CE_COLIBRI | CE_GLM53 , 0 , NULL}, + {"CONF_LIMIT", CE_FLOAT , CE_OLMOE | CE_QWEN , 0 , NULL}, + {"CONSIST", CE_BOOL, CE_COLIBRI, 0, NULL}, + {"CONSIST_NP", CE_INT, CE_COLIBRI, 0, NULL}, + {"CONSIST_TOL", CE_FLOAT, CE_COLIBRI, 0, NULL}, + {"COUPLE", CE_STR , CE_COLIBRI , 0 , NULL}, + {"COUPLE_D", CE_INT , CE_COLIBRI , 0 , NULL}, + {"COUPLE_K", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CTX", CE_INT , CE_COLIBRI | CE_OLMOE | CE_DSV4 | CE_DSV41, 0 , NULL}, + {"CTX_MAX", CE_STR , CE_INKLING , 0 , NULL}, + {"CUDA_DENSE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CUDA_EXPERT_GB", CE_FLOAT , CE_COLIBRI | CE_QWEN | CE_QWEN38, 0 , NULL}, + {"CUDA_EXPERT_LOAD_BALANCE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CUDA_RAW_EXPERTS", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CUDA_RELEASE_HOST", CE_INT , CE_COLIBRI , 0 , NULL}, + {"CUDA_RESERVE_GB", CE_FLOAT , CE_COLIBRI , 0 , NULL}, + {"DEBUG_LOGITS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"DEGRADE_TAU", CE_FLOAT, CE_COLIBRI, 0, NULL}, + {"DEGRADE_ZERO", CE_BOOL, CE_COLIBRI, 0, NULL}, + {"DIRECT", CE_INT , CE_COLIBRI , 0 , NULL}, + {"DISK_SPLIT", CE_INT , CE_COLIBRI , 0 , NULL}, + {"DN_DBG", CE_STR , CE_QWEN , 0 , NULL}, + {"DRAFT", CE_INT , CE_COLIBRI , 0 , NULL}, + {"DROP", CE_STR , CE_COLIBRI , 0 , NULL}, + {"DSA", CE_INT , CE_COLIBRI , 0 , NULL}, + {"DSA_FORCE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"DSA_TOPK", CE_INT , CE_COLIBRI , 0 , NULL}, + {"DSV4_ATTN_PROF", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_ATTN_ASYNC", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_ATTN_DG_AB", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_BATCHED", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_DEEPGEMM", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_DENSE_DG", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_DENSE_DUMP", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_DEVICE", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_DG_AB", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_DG_DUMP", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_DG_PROFILE", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_EXPERT_MIRRORS", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_FP4_ROWS", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_MOE_CONTIGUOUS", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_MOE_GROUPED", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_MOE_MASKED", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_MOE_PROF", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_MOE_TP2", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_PIN_HOST", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_QKV_FUSED", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_REPLICATED_TP2", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_TC", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_TP2_TRACE", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_CUDA_VRAM_RESERVE_MB", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_DECODE_PROF", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_HYBRID", CE_STR , CE_DSV4 , 0 , NULL}, + {"DSV4_IDX_VERIFY", CE_STR , CE_DSV4 , 0 , NULL}, + {"DUMP", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"DUMP_LAYERS", CE_STR , CE_QWEN , 0 , NULL}, + {"ENC_DEBUG", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"EXPERT_BUDGET", CE_INT , CE_COLIBRI , 0 , NULL}, + {"EXPERT_BUDGET_EXPERIMENTAL", CE_STR , CE_COLIBRI , 0 , NULL}, + {"EXPERT_DROP", CE_INT , CE_OLMOE , 0 , NULL}, + {"EXPERT_WORKER", CE_STR , CE_COLIBRI , 0 , NULL}, + {"FUSED3", CE_STR , CE_OLMOE , 0 , NULL}, + {"GLM53_BITS", CE_INT , CE_GLM53 , 0 , NULL}, + {"GLM53_DUMP_INDEX", CE_BOOL , CE_GLM53 , 0 , NULL}, + {"GLM53_EXPERT_GB", CE_FLOAT , CE_GLM53 , 0 , NULL}, + {"GLM53_MAXT", CE_INT , CE_GLM53 , 0 , NULL}, + {"GLM53_PREFILL_CHUNK", CE_INT , CE_GLM53 , 0 , NULL}, + {"GLM53_VERBOSE", CE_BOOL , CE_GLM53 , 0 , NULL}, + {"GLM_SEGMENT_DBITS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"GLM_SEGMENT_EBITS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"GPU_DEV", CE_INT , CE_INKLING , 0 , NULL}, + {"GRAMMAR", CE_STR , CE_COLIBRI , 0 , NULL}, + {"GRAMMAR_DRAFT", CE_INT , CE_COLIBRI , 0 , NULL}, + {"HEAT_FILE", CE_STR , CE_QWEN | CE_QWEN38, 0 , NULL}, + {"HOT", CE_INT , CE_OLMOE | CE_QWEN , 0 , NULL}, + {"I3_AVX512", CE_INT , CE_COLIBRI , 0 , NULL}, + {"I3_AVX512_TEST", CE_STR , CE_COLIBRI , 0 , NULL}, + {"I4S", CE_INT , CE_COLIBRI , 0 , NULL}, + {"I4_ACC512", CE_INT , CE_COLIBRI , 0 , NULL}, + {"I4_ACC512_TEST", CE_STR , CE_COLIBRI , 0 , NULL}, + {"IDOT", CE_INT , CE_COLIBRI | CE_INKLING | CE_OLMOE | CE_QWEN , 0 , NULL}, + {"IDOT_GS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"INK_DENSE_Q4", CE_STR , CE_INKLING , 0 , NULL}, + {"INK_METAL_MIN_S", CE_INT , CE_INKLING , 0 , NULL}, + {"INK_METAL_SHARED", CE_BOOL , CE_INKLING , 0 , NULL}, + {"INK_PREFIX_LOG", CE_STR , CE_INKLING , 0 , NULL}, + {"INK_SEGMENT_BITS", CE_STR , CE_INKLING , 0 , NULL}, + {"INK_SHARED_BATCH", CE_STR , CE_INKLING , 0 , NULL}, + {"K3_BITS", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_CHAT_IDS", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_CHUNK", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_CUDA", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_DEBUG_OUT", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_DIRECT", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_DIRS", CE_PATH , CE_KIMI , 0 , NULL}, + {"K3_EXPERT_GB", CE_FLOAT , CE_KIMI , 0 , NULL}, + {"K3_HEAD_BITS", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_IDOT", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_LAYERS", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_LOAD_THREADS", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_LOGITS", CE_PATH , CE_KIMI , 0 , NULL}, + {"K3_MAXT", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_METAL", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_MLA_BITS", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_MMAP", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_PIPE", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_PREFIX_LOG", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_STAT_EVERY", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_THINK", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_TOPP", CE_FLOAT , CE_KIMI , 0 , NULL}, + {"K3_TRACE", CE_PATH , CE_KIMI , 0 , NULL}, + {"K3_VALIDATE_LAYER", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_VALIDATE_OUT", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_VALIDATE_TOKEN", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_VAL_LOGITS", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_VK", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_VK_FILL_FRAC", CE_STR , CE_KIMI , 0 , NULL}, + {"K3_VK_GB", CE_FLOAT , CE_KIMI , 0 , NULL}, + {"K3_VK_UP", CE_INT , CE_KIMI , 0 , NULL}, + {"K3_X0", CE_PATH , CE_KIMI , 0 , NULL}, + {"KIMI_DSA_INDEXER", CE_BOOL, CE_KIMI, 0, NULL}, + {"KV8", CE_STR , CE_COLIBRI , 0 , NULL}, + {"KV8_GS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"KVB_FLASH", CE_STR , CE_COLIBRI , 0 , NULL}, + {"KVB_FLASH_MB", CE_STR , CE_COLIBRI , 0 , NULL}, + {"KVB_TILE_MB", CE_STR , CE_COLIBRI , 0 , NULL}, + {"KVSAVE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"KV_SLOTS", CE_INT , CE_COLIBRI | CE_GLM53 , 0 , NULL}, + {"KV_TQ", CE_STR , CE_COLIBRI , 0 , NULL}, + {"KV_TQ_POLAR", CE_STR , CE_COLIBRI , 0 , NULL}, + {"LOOKA", CE_INT , CE_COLIBRI , 0 , NULL}, + {"MAX_NEW", CE_INT , CE_OLMOE , 0 , NULL}, + {"MLOCK", CE_INT , CE_COLIBRI , 0 , NULL}, + {"MODEL", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"MTP", CE_INT , CE_COLIBRI , 0 , NULL}, + {"MTP_DEBUG", CE_INT , CE_COLIBRI , 0 , NULL}, + {"MTP_PRENORM", CE_STR , CE_COLIBRI , 0 , NULL}, + {"MTP_SWAP", CE_STR , CE_COLIBRI , 0 , NULL}, + {"NGEN", CE_INT , CE_COLIBRI | CE_DSV4 , 0 , NULL}, + {"NOGPU", CE_STR , CE_INKLING , 0 , NULL}, + {"NOPACK", CE_STR , CE_COLIBRI , 0 , NULL}, + {"NOSTREAM", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"NUCLEUS", CE_FLOAT , CE_COLIBRI | CE_OLMOE , 0 , NULL}, + {"N_NEW", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"OMP_NUM_THREADS", CE_STR , CE_DSV4 | CE_COLIBRI | CE_DSV41 | CE_GLM53 | CE_INKLING | CE_KIMI | CE_OLMOE | CE_QWEN | CE_QWEN38, 0 , NULL}, + {"OPENAI", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"ORACLE_TF_MAX_MISMATCHES", CE_INT , CE_COLIBRI, 0 , NULL}, + {"PILOT", CE_INT , CE_COLIBRI | CE_OLMOE | CE_QWEN , 0 , NULL}, + {"PILOT_EVICT_GUARD", CE_INT , CE_COLIBRI | CE_OLMOE , 0 , NULL}, + {"PILOT_K", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PILOT_REAL", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PILOT_TWO", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PILOT_WORKERS", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PIN", CE_STR , CE_COLIBRI | CE_INKLING , 0 , NULL}, + {"PIN_FILL", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PIN_GB", CE_STR , CE_COLIBRI , 0 , NULL}, + {"PIN_N", CE_INT , CE_INKLING , 0 , NULL}, + {"PIPE", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PIPE_WORKERS", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PLANAR", CE_STR , CE_COLIBRI , 0 , NULL}, + {"PPL", CE_INT , CE_OLMOE | CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"PREFETCH", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PROF", CE_INT , CE_COLIBRI , 0 , NULL}, + {"PROMPT", CE_STR , CE_ALL | CE_COLIBRI, 0 , NULL}, + {"Q36_EOS", CE_STR , CE_QWEN , 0 , NULL}, + {"Q36_MAXT", CE_STR , CE_QWEN , 0 , NULL}, + {"Q38_EOS", CE_INT , CE_QWEN38 , 0 , NULL}, + {"Q38_EXPERT_PARALLEL_READS", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"Q38_EXPERT_PREFETCH", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"Q38_FP8_KERNEL", CE_STR, CE_QWEN38, 0, NULL}, + {"Q38_MAXT", CE_INT , CE_QWEN38 , 0 , NULL}, + {"Q38_NATIVE_BF16", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"Q38_NATIVE_FP8", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"Q38_PLE_PREFETCH", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"Q38_PREFILL_BATCH", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"Q38_PREFIX_LOG", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"Q38_TRUNK_CPU_INT8", CE_BOOL, CE_QWEN38, 0, NULL}, + {"Q38_TRUNK_GPU", CE_BOOL, CE_QWEN38, 0, NULL}, + {"Q38_TRUNK_MIN_KB", CE_INT, CE_QWEN38, 0, NULL}, + {"Q38_TRUNK_SELFTEST", CE_BOOL, CE_QWEN38, 0, NULL}, + {"Q38_TRUNK_SKIP", CE_STR, CE_QWEN38, 0, NULL}, + {"Q38_VISION", CE_BOOL , CE_QWEN38 , 0 , NULL}, + {"QT_NO_WARMSTART", CE_STR , CE_QWEN , 0 , NULL}, + {"QT_UPLOAD_SYNC", CE_BOOL, CE_QWEN | CE_QWEN38, 0, NULL}, + {"QWEN_DENSE_BATCH", CE_STR , CE_QWEN , 0 , NULL}, + {"QWEN_EXPERT_ACT", CE_STR, CE_QWEN, 0, NULL}, + {"QWEN_EXPERT_KERNEL", CE_BOOL, CE_QWEN, 0, NULL}, + {"QWEN_SHARED_BATCH", CE_STR , CE_QWEN , 0 , NULL}, + {"RAM_GB", CE_FLOAT , CE_COLIBRI | CE_KIMI | CE_DSV4 | CE_OLMOE, 0 , NULL}, + {"RANS_AVX512", CE_STR , CE_ALL , 0 , NULL}, + {"RANS_NEON", CE_STR , CE_ALL , 0 , NULL}, + {"RANS_PATH", CE_PATH , CE_ALL , 0 , NULL}, + {"REF", CE_STR , CE_COLIBRI , 0 , NULL}, + {"REF_FORCE", CE_STR , CE_COLIBRI , 0 , NULL}, + {"REPIN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"REPIN_VERBOSE", CE_STR , CE_COLIBRI , 0 , NULL}, + {"REPLAY", CE_STR , CE_COLIBRI , 0 , NULL}, + {"REP_PEN", CE_FLOAT , CE_INKLING , 0 , NULL}, + {"ROUTE_AGREE", CE_INT , CE_COLIBRI | CE_QWEN, 0 , NULL}, + {"ROUTE_ALPHA", CE_FLOAT , CE_COLIBRI | CE_QWEN, 0 , NULL}, + {"ROUTE_J", CE_INT , CE_COLIBRI | CE_QWEN, 0 , NULL}, + {"ROUTE_M", CE_INT , CE_COLIBRI | CE_QWEN, 0 , NULL}, + {"ROUTE_P", CE_FLOAT , CE_COLIBRI | CE_QWEN, 0 , NULL}, + {"ROUTE_TRACE", CE_STR , CE_ALL | CE_QWEN38 | CE_COLIBRI | CE_DSV4 | CE_GLM53 | CE_INKLING | CE_KIMI | CE_OLMOE, 0 , NULL}, + {"RSS_GUARD_GB", CE_FLOAT , CE_COLIBRI , 0 , NULL}, + {"SCHEMA", CE_STR , CE_COLIBRI , 0 , NULL}, + {"SCORE", CE_STR , CE_COLIBRI , 0 , NULL}, + {"SCORE_PREFIX", CE_INT , CE_COLIBRI , 0 , NULL}, + {"SEED", CE_INT , CE_COLIBRI | CE_INKLING | CE_DSV41, 0 , NULL}, + {"SERVE", CE_INT , CE_COLIBRI | CE_KIMI | CE_INKLING | CE_OLMOE | CE_DSV4 | CE_QWEN | CE_GLM53 | CE_QWEN38 | CE_DSV41, 0 , NULL}, + {"SERVE_BATCH", CE_INT , CE_COLIBRI | CE_GLM53 | CE_OLMOE, 0 , NULL}, + {"SMOOTH", CE_FLOAT , CE_OLMOE | CE_QWEN , 0 , NULL}, + {"SNAP", CE_STR , CE_COLIBRI | CE_KIMI | CE_INKLING | CE_OLMOE | CE_DSV4 | CE_QWEN | CE_GLM53 | CE_QWEN38 | CE_DSV41, 0 , NULL}, + {"SNAP_MIRROR", CE_STR , CE_COLIBRI | CE_DSV4 | CE_DSV41 | CE_GLM53, 0 , NULL}, + {"SPEC", CE_INT , CE_COLIBRI , 0 , NULL}, + {"SPEC_PIN", CE_INT , CE_COLIBRI , 0 , NULL}, + {"STATS", CE_STR , CE_COLIBRI , 0 , NULL}, + {"TEMP", CE_FLOAT , CE_COLIBRI | CE_OLMOE , CE_DEPRECATED , "COLI_TEMP"}, + {"TF", CE_STR , CE_COLIBRI , 0 , NULL}, + {"THINK", CE_INT , CE_COLIBRI | CE_INKLING , 0 , NULL}, + {"TOK", CE_STR , CE_QWEN | CE_QWEN38 , 0 , NULL}, + {"TOKENS", CE_INT , CE_COLIBRI , 0 , NULL}, + {"TOPK", CE_INT , CE_COLIBRI , 0 , NULL}, + {"TOPP", CE_FLOAT , CE_COLIBRI | CE_INKLING , 0 , NULL}, + {"TRUNK_RESIDENT_LAYERS", CE_INT, CE_COLIBRI, 0, NULL}, + {"URING", CE_INT , CE_COLIBRI , 0 , NULL}, + {"USAGE_SAVE", CE_STR , CE_ALL | CE_QWEN38 | CE_COLIBRI | CE_DSV4 | CE_GLM53 | CE_INKLING | CE_KIMI | CE_OLMOE, 0 , NULL}, + {"V41_DIRECT", CE_BOOL, CE_DSV41, 0, NULL}, + {"V41_DSPARK", CE_BOOL, CE_DSV41, 0, NULL}, + {"V41_DSPARK_MAX", CE_INT, CE_DSV41, 0, NULL}, + {"V41_DSPARK_MINACC", CE_INT, CE_DSV41, 0, NULL}, + {"V41_ENGRAM_ROWS", CE_INT, CE_DSV41, 0, NULL}, + {"V41_INDEX_OWNER", CE_BOOL, CE_DSV41, 0, NULL}, + {"V41_READ_DEPTH", CE_INT, CE_DSV41, 0, NULL}, + {"V41_SPEC_FORCE", CE_BOOL, CE_DSV41, 0, NULL}, + {"V41_STATS", CE_BOOL, CE_DSV41, 0, NULL}, + {"V41_TRACE", CE_BOOL, CE_DSV41, 0, NULL}, + {"V4_DRAFT", CE_INT , CE_DSV4 , 0 , NULL}, + {"V4_EXPERT_UNION", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"V4_IDX_BATCH", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_IDX_IDENTITY", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_LOADER_LANES", CE_INT , CE_DSV4 , 0 , NULL}, + {"V4_MOE_BANK_FULL", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_MOE_REFILL_GROUP", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_MTP", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"V4_MTP_DRAFT", CE_INT , CE_DSV4 , 0 , NULL}, + {"V4_MTP_GB", CE_FLOAT , CE_DSV4 , 0 , NULL}, + {"V4_MTP_GPU_MIRRORS", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_MTP_MIN", CE_INT , CE_DSV4 , 0 , NULL}, + {"V4_MTP_PARTIAL_KEEP", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"V4_NGRAM", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"V4_NGRAM_PARTIAL_KEEP", CE_BOOL , CE_DSV4 , 0 , NULL}, + {"V4_PREFILL_CHUNK", CE_INT , CE_DSV4 , 0 , NULL}, + {"V4_PREFILL_SEGMENT", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_PREFIX_CKPT", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_PREFIX_CKPT_DISK", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_PREFIX_CKPT_MIN", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_PREFIX_CKPT_SLOTS", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_PREFIX_LOG", CE_STR , CE_DSV4 , 0 , NULL}, + {"V4_REPLAY_TRACE", CE_PATH, CE_DSV4, 0, NULL}, + {"VK_PROF", CE_STR , CE_ALL , 0 , NULL}, + {"WARMUP", CE_INT , CE_OLMOE | CE_QWEN , 0 , NULL}, + {"WIDE", CE_INT , CE_OLMOE | CE_QWEN , 0 , NULL}, + {"XEXP", CE_INT , CE_COLIBRI , 0 , NULL}, +}; +#define COLI_ENV_N ((int)(sizeof(coli_env_table) / sizeof(coli_env_table[0]))) + +static const char *coli_env_type_name(unsigned char t) { + switch (t) { + case CE_BOOL: return "bool"; + case CE_INT: return "int"; + case CE_FLOAT: return "float"; + case CE_PATH: return "path"; + default: return "string"; + } +} + +static const ColiEnvVar *coli_env_find(const char *name) { + int lo = 0, hi = COLI_ENV_N - 1; + while (lo <= hi) { + int mid = (lo + hi) / 2, c = strcmp(coli_env_table[mid].name, name); + if (c < 0) lo = mid + 1; + else if (c > 0) hi = mid - 1; + else return &coli_env_table[mid]; + } + return NULL; +} + +/* Levenshtein, capped: only used to say "did you mean" on a name the user + * already got wrong, so the O(n*m) on two short strings is irrelevant. */ +static int coli_env_edit(const char *a, const char *b) { + int la = (int)strlen(a), lb = (int)strlen(b); + if (la > 63 || lb > 63) return 99; + int prev[64], cur[64]; + for (int j = 0; j <= lb; j++) prev[j] = j; + for (int i = 1; i <= la; i++) { + cur[0] = i; + for (int j = 1; j <= lb; j++) { + int del = prev[j] + 1, ins = cur[j - 1] + 1, sub = prev[j - 1] + (a[i - 1] != b[j - 1]); + int m = del < ins ? del : ins; + cur[j] = m < sub ? m : sub; + } + memcpy(prev, cur, sizeof(int) * (size_t)(lb + 1)); + } + return prev[lb]; +} + +/* The nearest known name, or NULL when nothing is close enough to suggest. */ +static const char *coli_env_suggest(const char *name) { + const char *best = NULL; + int bd = 4; /* 3 edits is already a stretch for a 10-char name */ + for (int i = 0; i < COLI_ENV_N; i++) { + int d = coli_env_edit(name, coli_env_table[i].name); + if (d < bd) { bd = d; best = coli_env_table[i].name; } + } + return best; +} + +/* Names we own. An unknown FOO=1 in the environment is not our business, but an + * unknown COLI_FOO=1 almost certainly is. */ +static int coli_env_is_ours(const char *n) { + static const char *const prefixes[] = { + "COLI_", "COLIBRI_", "K3_", "KIMI_", "INK_", "GLM53_", + "Q38_", "Q36_", "QWEN_", "DSV4_", "V4_", "V41_" + }; + for (unsigned i = 0; i < sizeof(prefixes) / sizeof(prefixes[0]); ++i) + if (!strncmp(n, prefixes[i], strlen(prefixes[i]))) return 1; + return 0; +} + +/* Compare the process environment against the table. `self` is the calling + * engine's CE_* bit, `name` its binary name for the messages. + * + * Warns, does not exit: an unrecognised variable has never stopped a run before + * and turning that into a hard failure would break scripts that set a knob for + * whichever engine they might launch. COLI_ENV_STRICT=1 makes it fatal for CI + * and for anyone who wants the guarantee. + * + * Returns the number of problems found. */ +static int coli_env_check(unsigned short self, const char *name) { + int bad = 0, strict = getenv("COLI_ENV_STRICT") && atoi(getenv("COLI_ENV_STRICT")); + char **envp = COLI_ENVIRON; + for (char **e = envp; e && *e; e++) { + const char *eq = strchr(*e, '='); + if (!eq || eq == *e) continue; + size_t n = (size_t)(eq - *e); + if (n >= 64) continue; + char key[64]; + memcpy(key, *e, n); + key[n] = 0; + const ColiEnvVar *v = coli_env_find(key); + if (!v) { + if (!coli_env_is_ours(key)) continue; /* not ours, not our problem */ + const char *s = coli_env_suggest(key); + fprintf(stderr, "[env] unknown variable %s", key); + if (s) fprintf(stderr, " -- did you mean %s?", s); + fprintf(stderr, "\n"); + bad++; + continue; + } + if (!(v->engines & self)) { + fprintf(stderr, "[env] %s is not read by %s (it belongs to %s%s%s%s%s%s%s%s%s) -- it will have no effect\n", + key, name, + (v->engines & CE_COLIBRI) ? "colibri " : "", (v->engines & CE_KIMI) ? "kimi_k3 " : "", + (v->engines & CE_INKLING) ? "inkling " : "", (v->engines & CE_OLMOE) ? "olmoe " : "", + (v->engines & CE_DSV4) ? "deepseek-v4 " : "", (v->engines & CE_QWEN) ? "qwen36 " : "", + (v->engines & CE_GLM53) ? "glm53 " : "", (v->engines & CE_QWEN38) ? "qwen38 " : "", + (v->engines & CE_DSV41) ? "deepseek-v41" : ""); + bad++; + continue; + } + if (v->flags & CE_DEPRECATED) + fprintf(stderr, "[env] %s is deprecated -- use %s\n", key, v->replacement ? v->replacement : "(nothing)"); + } + if (bad && strict) { + fprintf(stderr, "[env] COLI_ENV_STRICT=1 and %d problem(s) above\n", bad); + exit(2); + } + return bad; +} + +/* Every variable this engine reads, its type, and whether it is set right now. + * Answers "is my export actually reaching the engine" without a debugger. */ +static void coli_env_dump(unsigned short self, const char *name) { + const char *enabled = getenv("COLI_ENV_DUMP"); + if (!enabled || !atoi(enabled)) return; + int n = 0; + for (int i = 0; i < COLI_ENV_N; i++) { + const ColiEnvVar *v = &coli_env_table[i]; + if (!(v->engines & self)) continue; + const char *val = getenv(v->name); + fprintf(stderr, " %-32s %-6s %s%s\n", v->name, coli_env_type_name(v->type), + val ? "= " : "(unset)", val ? val : ""); + n++; + } + fprintf(stderr, "[env] %d variables for %s\n", n, name); +} + +#endif /* COLI_ENV_H */ diff --git a/c/colibri.c b/c/colibri.c index a96ccba4e..1137b77af 100644 --- a/c/colibri.c +++ b/c/colibri.c @@ -99,6 +99,7 @@ static inline void omp_set_num_threads(int n){ (void)n; } #include "edge_adapters.h" #include "edge_tok_internal.h" #endif +#include "coli_env.h" #ifdef COLI_CUDA #include "backend_cuda.h" #endif @@ -11136,6 +11137,11 @@ int main(int argc, char **argv){ perror("[OMP] execv self-reexec failed, running untuned"); #endif } + /* Registry check: an unknown or wrong-engine variable is silently ignored + * otherwise, and the run then reports a plausible number for the WRONG + * configuration. See coli_env.h. */ + coli_env_check(CE_COLIBRI, "colibri"); + coli_env_dump(CE_COLIBRI, "colibri"); /* #718: the hot-team block above tunes wake latency but historically left * GLM at libgomp's logical-CPU default. Memory-bound quantized matmuls can * collapse when SMT siblings share each core, measured 2.3x on a 5950X. diff --git a/c/deepseek_v4.c b/c/deepseek_v4.c index d7bb6c6e8..6ebb92b42 100644 --- a/c/deepseek_v4.c +++ b/c/deepseek_v4.c @@ -12,6 +12,8 @@ * anything larger falls back to malloc exactly like before this change. */ #define COLI_V4_ROUTE_STACK_EXPERTS 512 +#include "coli_env.h" + #ifdef COLI_V4_UNIT_ST /* Shared st.h adapter and V4 tensor materialization helpers. */ #include "deepseek_v4_internal.h" @@ -12040,6 +12042,8 @@ static int has_sentence_end(const char *text, int length) { } int main(int argc, char **argv) { + coli_env_check(CE_DSV4, "deepseek-v4"); + coli_env_dump(CE_DSV4, "deepseek-v4"); if (argc < 3 || argc > 6) { fprintf(stderr, "usage: %s MODEL_DIR INPUT_TOKEN_ID [TOKEN_COUNT]\n" " %s MODEL_DIR --prompt TEXT [MAX_NEW_TOKENS] [--stop-sentence]\n", @@ -14621,6 +14625,8 @@ static int v4_omp_reserve_loader_cpus(void) { #endif int main(int argc, char **argv) { + coli_env_check(CE_DSV4, "deepseek-v4"); + coli_env_dump(CE_DSV4, "deepseek-v4"); #ifdef _OPENMP if (!v4_omp_reserve_loader_cpus()) fprintf(stderr, "[OMP] deepseek-v4: effective team size %d\n", diff --git a/c/deepseek_v41.c b/c/deepseek_v41.c index 93860212a..49cc493b1 100644 --- a/c/deepseek_v41.c +++ b/c/deepseek_v41.c @@ -60,6 +60,7 @@ #include "compat.h" #include "json.h" #include "st.h" +#include "coli_env.h" #include "quant.h" #include "sparse_attn.h" #include "omp_tune.h" @@ -3887,6 +3888,8 @@ static int *load_ids(jval *root, const char *key, int *count) { } int main(int argc, char **argv) { + coli_env_check(CE_DSV41, "deepseek-v41"); + coli_env_dump(CE_DSV41, "deepseek-v41"); /* Size the team to PHYSICAL cores before anything else touches the model. * This engine issues ~720 OpenMP regions per decoded token -- three per * expert application, 240 applications a token -- and every one of them is diff --git a/c/glm53.c b/c/glm53.c index aa1ad8174..68042e3c1 100644 --- a/c/glm53.c +++ b/c/glm53.c @@ -89,6 +89,7 @@ static uint64_t g_metal_moe_rows = 0; static int g_vk_ready = 0; #endif #include "compat.h" +#include "coli_env.h" #include "serve_poll.h" /* CANCEL a meta' turno (#1332) */ #include "route_trace.h" #include "decode_batch.h" /* coli_submit_ext, coli_logprob_tail: canale logprobs */ @@ -3515,6 +3516,8 @@ static void serve_loop(GModel *m, Tok *tokenizer) { #ifndef GLM53_NO_MAIN int main(int argc, char **argv) { + coli_env_check(CE_GLM53, "glm53"); + coli_env_dump(CE_GLM53, "glm53"); /* Physical-core team sizing, the same shared helper colibri/inkling/ * kimi_k3/olmoe/deepseek-v41 call. This engine has no OpenMP sizing of its * own, so on an SMT host it ran one thread per logical CPU; #718 measured diff --git a/c/inkling.c b/c/inkling.c index 0ee1740dd..7569fe083 100644 --- a/c/inkling.c +++ b/c/inkling.c @@ -53,6 +53,7 @@ #include "edge_adapters.h" #include "edge_tok_internal.h" #endif +#include "coli_env.h" #ifdef COLI_CUDA #include "backend_cuda_ink.h" static int g_cuda = 0; @@ -2580,6 +2581,11 @@ int main(int argc, char **argv) { } #endif /* !COLI_CUDA && !__APPLE__ */ coli_omp_tune_threads("inkling"); + /* Registry check: an unknown or wrong-engine variable is silently ignored + * otherwise, and the run then reports a plausible number for the WRONG + * configuration. See coli_env.h. */ + coli_env_check(CE_INKLING, "inkling"); + coli_env_dump(CE_INKLING, "inkling"); const char *snap = getenv("SNAP"); if (!snap) { coli_print_launcher_help("Inkling"); return 1; } g_topp = getenv("TOPP") ? (float)atof(getenv("TOPP")) : 0.f; diff --git a/c/kimi_k3.c b/c/kimi_k3.c index a05f6336d..aee4a6f20 100644 --- a/c/kimi_k3.c +++ b/c/kimi_k3.c @@ -112,6 +112,7 @@ #include "backend_cuda.h" #endif #include "omp_tune.h" +#include "coli_env.h" #include "route_trace.h" #include "kv_prefix.h" #include "pin_pool.h" /* coli_pin_slots_wanted: quanti scatti tenere */ @@ -3272,6 +3273,11 @@ static void serve_loop(Model *m, Tok *T){ #ifndef KIMI_K3_NO_MAIN int main(int argc, char **argv){ coli_omp_tune_threads("kimi_k3"); /* squadra sui core fisici, niente spin-wait: vedi omp_tune.h */ + /* Registry check: an unknown or wrong-engine variable is silently ignored + * otherwise, and the run then reports a plausible number for the WRONG + * configuration. See coli_env.h. */ + coli_env_check(CE_KIMI, "kimi_k3"); + coli_env_dump(CE_KIMI, "kimi_k3"); int serving=getenv("SERVE")&&getenv("SERVE")[0]=='1'; /* Usage was printed only when there were NO arguments, so `--help` fell * through as the model directory and the engine went looking for diff --git a/c/olmoe.c b/c/olmoe.c index 944566c57..e6638e349 100644 --- a/c/olmoe.c +++ b/c/olmoe.c @@ -42,6 +42,7 @@ #include /* omp_set_num_threads/omp_get_max_threads per omp_tune.h */ #endif #include "omp_tune.h" +#include "coli_env.h" #include "route_trace.h" /* shared routing telemetry (#700) */ #include "kv_prefix.h" #include "pin_pool.h" /* piu scatti annidati */ /* riuso del prefisso tra turni (shared) */ @@ -1836,6 +1837,11 @@ static int *read_int_array(jval *o, const char *key, int *n_out) { #ifndef OLMOE_NO_MAIN int main(int argc, char **argv) { coli_omp_tune_threads("olmoe"); /* squadra sui core fisici, niente spin-wait: vedi omp_tune.h */ + /* Registry check: an unknown or wrong-engine variable is silently ignored + * otherwise, and the run then reports a plausible number for the WRONG + * configuration. See coli_env.h. */ + coli_env_check(CE_OLMOE, "olmoe"); + coli_env_dump(CE_OLMOE, "olmoe"); const char *snap = getenv("SNAP"); if (!snap) { coli_print_launcher_help("OLMoE"); return 1; } g_pilot = getenv("PILOT") ? atoi(getenv("PILOT")) : 0; diff --git a/c/qwen36.c b/c/qwen36.c index 670ac1d05..0a3860c24 100644 --- a/c/qwen36.c +++ b/c/qwen36.c @@ -65,6 +65,7 @@ static int qwen36_max_ctx(void) { #include "pin_pool.h" /* riuso del prefisso tra turni (shared) */ #include "decode_batch.h" /* ColiSubmit + coli_submit_ext: le chiavi key=value di SUBMIT */ #include "json.h" /* tokenizer.json parsing (reuse minimal parser) */ +#include "coli_env.h" #include "qwen36_tier.h" /* optional CUDA VRAM expert tier */ #include "expert_ffn.h" /* routed experts: planar int4 kernel + layer runner */ #include "idot.h" /* integer dot kernels for the dense trunk (COLI_DENSE_IDOT, COLI_DENSE_BITS) */ @@ -3711,6 +3712,8 @@ static void tier_warmstart(Model *m, int expert_is_int4) { } int main(int argc, char **argv) { + coli_env_check(CE_QWEN, "qwen36"); + coli_env_dump(CE_QWEN, "qwen36"); /* Physical-core team sizing, as colibri/inkling/kimi_k3/olmoe/deepseek-v41 * do. Without it this engine takes one thread per logical CPU, which on an * SMT host doubles the team for no arithmetic and pays a barrier per tiny diff --git a/c/qwen38.c b/c/qwen38.c index 494f0b389..d2cd4eab7 100644 --- a/c/qwen38.c +++ b/c/qwen38.c @@ -67,6 +67,7 @@ static int qwen38_max_ctx(void) { #include "tok_unicode.h" #include "tok_unicode_o200k.h" #include "qwen38_nfc.h" +#include "coli_env.h" /* quant.h owns Colibri's authoritative E4M3 table. This engine retains the * Qwen sibling's established dense kernels, so rename quant.h's two generic * helpers while including it; every format-specific symbol keeps its shared @@ -1834,6 +1835,8 @@ static int q38_reference_mode(const char *path,int serve_mode){ #ifndef QWEN38_TEST_SERVE int main(int argc, char **argv) { + coli_env_check(CE_QWEN38, "qwen38"); + coli_env_dump(CE_QWEN38, "qwen38"); /* Physical-core team sizing, as colibri/inkling/kimi_k3/olmoe/deepseek-v41 * do. Without it this engine takes one thread per logical CPU, which on an * SMT host doubles the team for no arithmetic and pays a barrier per tiny diff --git a/c/tests/test_env_registry.c b/c/tests/test_env_registry.c new file mode 100644 index 000000000..968f079d4 --- /dev/null +++ b/c/tests/test_env_registry.c @@ -0,0 +1,32 @@ +#include +#include "../coli_env.h" + +int main(void) { + const unsigned short engines[] = {CE_COLIBRI, CE_KIMI, CE_INKLING, CE_OLMOE, + CE_DSV4, CE_QWEN, CE_GLM53, CE_QWEN38, CE_DSV41}; + for (unsigned i = 0; i < sizeof(engines) / sizeof(engines[0]); ++i) { + assert(coli_env_find("COLI_ENV_STRICT")->engines & engines[i]); + assert(coli_env_find("COLI_ENV_DUMP")->engines & engines[i]); + } + assert(coli_env_find("V41_DSPARK")->engines == CE_DSV41); + assert(coli_env_find("V41_READ_DEPTH")->engines == CE_DSV41); + assert(coli_env_find("Q38_TRUNK_GPU")->engines == CE_QWEN38); + assert(coli_env_find("COLI_PLACE")->engines == (CE_QWEN | CE_QWEN38)); + assert(coli_env_find("CACHE_ROUTE")->engines & CE_QWEN); + assert(coli_env_find("SNAP")->engines & CE_DSV41); + assert(coli_env_is_ours("V41_DSPAR")); + assert(!strcmp(coli_env_suggest("V41_DSPAR"), "V41_DSPARK")); + assert(!coli_env_find("V41_DSPAR")); + const char *const typos[] = {"COLI_PREFIL_CHUNK", "COLIBRI_ENGINE_SUFFI", + "K3_BIT", "KIMI_DSA_INDEXE", "INK_BIT", "GLM53_BIT", "Q38_TRUNK_GP", + "Q36_CTX_MA", "QWEN_EXPERT_KERNL", "DSV4_UNKNOWN", "V4_REPLAY_TRAC", "V41_DSPAR"}; + for (unsigned i = 0; i < sizeof(typos) / sizeof(typos[0]); ++i) + assert(coli_env_is_ours(typos[i])); + const char *const unrelated[] = {"EDITOR", "MY_VAR", "CUDA_VISIBLE_DEVICES", + "OMP_WAIT_POLICY", "QT_QPA_PLATFORM", "VK_ICD_FILENAMES", "QWEN", "V41", "Q38X_FOO"}; + for (unsigned i = 0; i < sizeof(unrelated) / sizeof(unrelated[0]); ++i) + assert(!coli_env_is_ours(unrelated[i])); + assert(!strcmp(coli_env_suggest("QWEN_EXPERT_KERNL"), "QWEN_EXPERT_KERNEL")); + puts("test_env_registry: ok"); + return 0; +} diff --git a/c/tests/test_env_registry_scanner.py b/c/tests/test_env_registry_scanner.py new file mode 100644 index 000000000..9ce4f10b7 --- /dev/null +++ b/c/tests/test_env_registry_scanner.py @@ -0,0 +1,50 @@ +"""Name coverage must follow calls, not formatting or source comments.""" +import contextlib +import io +from pathlib import Path +import tempfile +import unittest +from unittest.mock import patch +from tools import check_env_registry as registry + + +class RegistryScannerTest(unittest.TestCase): + def setUp(self): + self.directory = tempfile.TemporaryDirectory() + self.addCleanup(self.directory.cleanup) + self.root = Path(self.directory.name) + self.patch = patch.object(registry, "C_DIR", str(self.root)) + self.patch.start() + self.addCleanup(self.patch.stop) + + def test_calls_across_lines_and_whitespace(self): + (self.root / "engine.c").write_text( + 'getenv (\n "COLI_A");\nq38_env_bool(\n "Q38_B");\n' + 'compat_getenv_utf8("COLI_C");\n') + self.assertEqual(registry.scan_sources(), { + "COLI_A": ["engine.c:1"], "Q38_B": ["engine.c:3"], + "COLI_C": ["engine.c:5"]}) + + def test_comments_and_strings_are_not_calls(self): + (self.root / "engine.c").write_text( + '// getenv("COLI_COMMENT")\n' + '/* q38_env_bool("Q38_COMMENT") */\n' + 'const char *s = "getenv(\\"COLI_STRING\\")";\n' + 'my_getenv("COLI_OTHER_FUNCTION");\n' + 'getenv("COLI_REAL");\n') + self.assertEqual(registry.scan_sources(), {"COLI_REAL": ["engine.c:5"]}) + + def test_commented_read_cannot_keep_stale_registry_entry_alive(self): + (self.root / "engine.c").write_text('// getenv("COLI_OLD")\n') + (self.root / "coli_env.h").write_text( + 'static const ColiEnvVar coli_env_table[] = {\n' + ' {"COLI_OLD", CE_BOOL, CE_QWEN, 0, NULL},\n};\n') + error = io.StringIO() + with contextlib.redirect_stderr(error): + self.assertEqual(registry.main(), 1) + self.assertIn("no code reads it: COLI_OLD", error.getvalue()) + + def test_fixture_directories_are_excluded(self): + (self.root / "tests").mkdir() + (self.root / "tests" / "fixture.c").write_text('getenv("FIXTURE_ONLY");') + self.assertEqual(registry.scan_sources(), {}) diff --git a/c/tools/check_env_registry.py b/c/tools/check_env_registry.py new file mode 100644 index 000000000..6f64d32a8 --- /dev/null +++ b/c/tools/check_env_registry.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""Keep coli_env.h in sync with the getenv() calls in the engines. + +Run it with `make -C c check-env`. It fails when: + + - the code reads a variable the registry does not list (the check in + coli_env_check() would then report a real variable as "unknown", which is + worse than not checking at all); + - the registry lists a variable no code reads (a stale row that will suggest + a name that does nothing); + - the table is not sorted by name, which silently breaks the binary search in + coli_env_find(), or contains a duplicate name. + +c/tests/ is excluded: fixtures read their own variables (EXPERT_RAW, TMPDIR) +which are not part of the engines' surface. +""" + +import os +import re +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +C_DIR = os.path.dirname(HERE) + +GETENV = re.compile(r'\b(?:q38_env_bool|(?:compat_)?getenv(?:_utf8)?)\s*\(\s*"([A-Z0-9_]+)"') +# Consume literals and comments before looking for calls. This is a lexical +# scan of literal names, not a C preprocessor or dynamic-name evaluator. +SOURCE_TOKEN = re.compile( + r'"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|//[^\n]*|/\*.*?\*/|' + + GETENV.pattern, re.DOTALL) +ROW = re.compile(r'^\s*\{"([A-Z0-9_]+)"\s*,') + + +def scan_sources(): + """Every variable the engines actually read, and where.""" + found = {} + for root, dirs, files in os.walk(C_DIR): + dirs[:] = [d for d in dirs if d not in ("tests", "__pycache__", "shaders")] + for f in files: + if not f.endswith((".c", ".h", ".cu", ".mm")): + continue + # coli_env.h is scanned like any other source: its own getenv() calls + # (COLI_ENV_STRICT) are real reads. The table rows are `{"NAME",` and + # do not match GETENV, so listing a variable is not mistaken for + # reading it. + path = os.path.join(root, f) + with open(path, errors="replace") as fh: + source = fh.read() + for m in SOURCE_TOKEN.finditer(source): + if m.group(1) is not None: + n = source.count("\n", 0, m.start()) + 1 + found.setdefault(m.group(1), []).append( + "%s:%d" % (os.path.relpath(path, C_DIR), n)) + return found + + +def scan_registry(): + """The table's rows, in file order.""" + rows = [] + with open(os.path.join(C_DIR, "coli_env.h"), errors="replace") as fh: + inside = False + for line in fh: + if "coli_env_table[] = {" in line: + inside = True + continue + if inside: + if line.startswith("};"): + break + m = ROW.match(line) + if m: + rows.append(m.group(1)) + return rows + + +def main(): + code = scan_sources() + rows = scan_registry() + problems = [] + + if not rows: + problems.append("could not parse any rows out of coli_env.h") + + dupes = {n for n in rows if rows.count(n) > 1} + if dupes: + problems.append("duplicate rows: " + ", ".join(sorted(dupes))) + + if rows != sorted(rows): + for a, b in zip(rows, rows[1:]): + if a > b: + problems.append( + "table is not sorted (%r before %r) -- coli_env_find() " + "binary-searches it, so an unsorted table silently fails " + "to find valid names" % (a, b)) + break + + missing = sorted(set(code) - set(rows)) + for v in missing: + problems.append("read by the code but missing from coli_env.h: %s (%s)" + % (v, code[v][0])) + + stale = sorted(set(rows) - set(code)) + for v in stale: + problems.append("in coli_env.h but no code reads it: %s" % v) + + if problems: + sys.stderr.write("coli_env.h is out of sync with the sources:\n") + for p in problems: + sys.stderr.write(" - %s\n" % p) + sys.stderr.write( + "\nAdd, remove or re-sort the row in c/coli_env.h so the registry " + "matches what the engines read.\n") + return 1 + + print("check-env: %d variables, registry matches the sources" % len(rows)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index e6bee8245..85f8a4a6e 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -6,7 +6,7 @@ Reference for the environment variables read by the colibrì engine. ## Which program reads these? -**There are seven engine binaries, and they do not share a knob set.** The main +**There are eight engine binaries, and they do not share a knob set.** The main engine `c/colibri` (built from `c/colibri.c`, formerly `glm.c`) reads most of what follows, but the sister engines read their own: @@ -17,11 +17,13 @@ what follows, but the sister engines read their own: | `inkling` | `c/inkling.c` | `INK_*`, plus `CTX_MAX`, `PIN_N`, `REP_PEN`, `GPU_DEV`, `NOGPU` — see [Inkling engine](#inkling-engine-inkling) | | `qwen36` | `c/qwen36.c` | `QWEN_*`, `Q36_*`, its dense/CUDA-tier controls, and the `CACHE_ROUTE` family (VRAM tier over RAM cache) — see [Qwen3.6 engine](#qwen36-engine-qwen36) | | `qwen38` | `c/qwen38.c` | `Q38_MAXT`, `Q38_EOS`, `Q38_NATIVE_FP8`, `Q38_NATIVE_BF16`, `Q38_PREFILL_BATCH`, `Q38_TRUNK_CPU_INT8`, `Q38_FP8_KERNEL`, `COLI_TIMERS` — see [Qwen3.8 engine](#qwen38-engine-qwen38) | +| `glm53` | `c/glm53.c` | the `GLM53_*` family plus its Vulkan, serving, and KV-slot controls — see [GLM-5.3 engine](#glm-53-flash-engine-glm53) | +| `deepseek-v41` | `c/deepseek_v41.c` | `V41_*`, plus shared streaming, KV-prefix and serving controls | | `olmoe` | `c/olmoe.c` | `HOT`, `WIDE`, `SMOOTH`, `CONF_LIMIT`, `MAX_NEW`, `CHAT`, `EXPERT_DROP`, `WARMUP` — see [OLMoE engine](#olmoe-engine-olmoe) | | `deepseek_v4` | `c/deepseek_v4.c` | `CTX`, the `V4_*` / `DSV4_*` families and the two `COLI_CUDA_*_BATCH` gates — see [DeepSeek V4 engine](#deepseek-v4-engine-deepseek_v4); note that the CUDA section below describes `colibri.c` knobs (`COLI_CUDA`, `CUDA_DENSE`, ...) which the V4 engine does not read — its GPU switch is `DSV4_CUDA` | Setting an `INK_*` variable while running `colibri` does nothing, and vice -versa; nothing warns you about it. A few variables are genuinely shared because +versa; the startup registry warns about that mismatch. A few variables are genuinely shared because they live in headers every engine includes (`COLI_USAGE`, `USAGE_SAVE`, `COLI_USAGE_DECAY` in `route_trace.h`; `RANS_*` in `rans.h`; `COLI_NO_OMP_TUNE` / `OMP_NUM_THREADS` in `omp_tune.h`). @@ -34,6 +36,41 @@ CLI doesn't surface, or to override what the CLI would set. Format: `VAR` — default — effect. +## Checking what the engine actually received + +Every engine validates the environment at startup against the registry in +`c/coli_env.h` and reports what it cannot use: + +```console +$ COLI_PREFIL_CHUNK=512 ./colibri ... +[env] unknown variable COLI_PREFIL_CHUNK -- did you mean COLI_PREFILL_CHUNK? + +$ K3_BITS=8 ./colibri ... +[env] K3_BITS is not read by colibri (it belongs to kimi_k3) -- it will have no effect +``` + +Both of those used to be silent: the run proceeded with the default and +produced a plausible number for a configuration you did not set. That is the +mistake this check exists to catch, and it is why the engine-ownership table +above matters. + +It warns rather than exits, so nothing that works today stops working. Two +knobs: + +| Variable | Default | Effect | +|---|---|---| +| `COLI_ENV_STRICT` | `0` | `=1` turns those warnings into `exit(2)`. For CI and for anyone who wants the guarantee rather than the notice. | +| `COLI_ENV_DUMP` | `0` | `=1` prints every variable this engine reads, its type, and whether it is currently set — the fastest answer to "is my export reaching the engine?" | + +Variables the engine does not own are left alone: an unrelated `EDITOR` or +`MY_VAR` in the environment is never reported. Unknown names are checked only +under `COLI_*`, `COLIBRI_*`, `K3_*`, `KIMI_*`, `INK_*`, `GLM53_*`, `Q38_*`, +`Q36_*`, `QWEN_*`, `DSV4_*`, `V4_*`, and `V41_*`. These prefixes belong to the +project. Shared external prefixes such as `CUDA_*`, `OMP_*`, `QT_*`, and `VK_*` +are not claimed: unregistered names under them are ignored. Registered names +are still checked for engine ownership regardless of prefix. + + --- ## Common — everyday use