Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c56de9c
feat(pflash): Qwen3.5-0.8B drafter scorer with segment probe and scor…
Graffioh Sep 19, 2026
2877e58
feat(pflash): strict budget selection, explicit scorer query and comp…
Graffioh Sep 19, 2026
3814457
test(pflash): selection and IPC coverage; README
Graffioh Sep 19, 2026
9e2ed04
refactor(pflash): move Qwen3.5 drafter to src/pflash, drop Qwen3-0.6B…
Graffioh Sep 20, 2026
ed2fd89
docs(pflash): clarify pflash vs pflash_drafter boundary
Graffioh Sep 20, 2026
1ee9cc1
feat(pflash): add a rank-based top_k selection mode
Graffioh Sep 22, 2026
2455efb
feat(pflash): rank segments with a document mass prior
Graffioh Sep 22, 2026
739a8c3
feat(pflash): force the headers of the best documents
Graffioh Sep 22, 2026
6ac41fc
Merge upstream/main: resolve dflash->luce rename against pflash reorg
Graffioh Sep 22, 2026
3e65d3c
pflash: derive the scorer query from the rendered chat tail
Graffioh Sep 22, 2026
5418882
revert(pflash): drop the document prior and forced document heads
Graffioh Sep 22, 2026
903b714
fix(pflash): take the chat scorer query from the latest user turn
Graffioh Sep 22, 2026
8e7fc2c
feat(pflash): score the turns after the query in agent loops
Graffioh Sep 22, 2026
7e57eab
feat(pflash): spend the keep ratio on the droppable tokens
Graffioh Sep 22, 2026
36da944
fix(pflash): never compress the system prompt
Graffioh Sep 22, 2026
613c71f
feat(pflash): multi-turn views that append, recall and rebuild
Graffioh Sep 22, 2026
55475e6
feat(pflash): per-conversation drafter scoring sessions
Graffioh Sep 22, 2026
55d7f9c
feat(pflash): multi-turn skeleton and history-query scoring
Graffioh Sep 22, 2026
2ce924a
feat(pflash): report compression and view details in usage timings
Graffioh Sep 22, 2026
71bee68
feat(pflash): compress only large follow-ups; recall switch; served t…
Graffioh Sep 23, 2026
d90c27e
feat(pflash): recall by attention lift; optional paragraph join
Graffioh Sep 23, 2026
a8de3b1
Merge remote-tracking branch 'upstream/main' into codex/pflash-segmen…
Graffioh Sep 23, 2026
554953c
feat(pflash): join kept pieces with paragraph breaks by default
Graffioh Sep 23, 2026
b1c8fe5
feat(pflash): score chats from the prompt's last token
Graffioh Sep 23, 2026
63ccadd
feat(pflash): recall by one lift gate, rebuild past a third of fresh
Graffioh Sep 23, 2026
5af2ed9
fix(pflash): rescore from scratch once on non-finite head scores
Graffioh Sep 23, 2026
4d011e6
feat(pflash): score the latest user turn's tail beside the prompt end
Graffioh Sep 24, 2026
d743a4e
feat(pflash): recall what a fresh selection keeps, as whole passages
Graffioh Sep 25, 2026
555ee2a
Merge remote-tracking branch 'upstream/main' into codex/pflash-segmen…
Graffioh Sep 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions optimizations/kvflash/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ FA span traffic is bandwidth-realistic:
## Full LSA loop (drafter as Memory Indexer) — measured

Test run F implements the paper's complete inference paradigm with the
pflash drafter (Qwen3-0.6B, `/opt/lucebox/models/drafter/`) standing in
pflash drafter (Qwen3.5-0.8B, `/opt/lucebox/models/drafter/`) standing in
for the trained indexer: prompt (2048) larger than the pool (1024) so
prefill itself evicts, then every τ=64 decoded tokens the drafter
rescores the full sequence (tail attention = indexer query, chunk means
Expand Down Expand Up @@ -176,7 +176,7 @@ The pool is wired into the qwen35 backend behind `--kvflash <tokens>`
pool (live LRU eviction mid-request). Coherent story end to end,
36.9 tok/s, clean finish. Second request (per-request pager reset) ok.
2. WITH pflash: `--kvflash 2048 --prefill-compression always
--prefill-threshold 256 --prefill-drafter <Qwen3-0.6B>`. Compression
--prefill-threshold 256 --prefill-drafter <Qwen3.5-0.8B>`. Compression
1468 -> 60 tokens, then `[kvflash] drafter scorer attached (tau=64)`
automatically; 400 coherent tokens answering from the compressed
context. Same binary, zero pflash-specific configuration on the pool.
Expand Down Expand Up @@ -246,7 +246,7 @@ and masks through it. What differs per arch:
3.09, identical text).

Policy: drafter-scored residency is the default on all four archs. The
server probes for the Qwen3-0.6B next to the model (or --prefill-drafter)
server probes for the Qwen3.5-0.8B next to the model (or --prefill-drafter)
and lazy-loads it at the first reselect; `--kvflash-policy lru` opts out.
qwen35/qwen35moe feed the drafter target ids directly; laguna/gemma4 use
KvFlashCrossTokScorer (detokenize -> re-tokenize -> score -> map back by
Expand Down
6 changes: 3 additions & 3 deletions optimizations/kvflash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ does not fit at all.)
# recommended: drafter-scored residency, pool auto-sized from VRAM.
# pass --prefill-drafter so the drafter is guaranteed (no silent LRU fallback).
luce_server model.gguf --max-ctx 32768 --kvflash auto \
--prefill-drafter /opt/lucebox/models/drafter/Qwen3-0.6B-BF16.gguf
--prefill-drafter /opt/lucebox/models/drafter/Qwen3.5-0.8B-BF16.gguf

# drop the path to auto-probe (model dir, drafter/, draft/, /opt/lucebox/models/drafter/);
# falls back to LRU if none is found, so check the banner reads policy=drafter
Expand All @@ -52,7 +52,7 @@ luce_server model.gguf --max-ctx 32768 --kvflash 8192 --kvflash-policy lru
```

Drafter-scored residency is the DEFAULT policy on every model family:
the server probes for `Qwen3-0.6B-BF16.gguf` next to the model (same
the server probes for `Qwen3.5-0.8B-BF16.gguf` next to the model (same
dir, `drafter/`, `draft/`, then `/opt/lucebox/models/drafter/`) and
lazy-loads it on the first reselect; `--prefill-drafter` overrides the
location, prefill compression can stay off either way. Qwen-family
Expand Down Expand Up @@ -147,7 +147,7 @@ Env: `LUCE_KVFLASH_POLICY=qk`. Bench: `test_kvflash --qkbench`.
- `server/src/common/kvflash_qk.h` — target-QK scorer: pure scoring math
(unit-tested in `server/test/test_kvflash_qk.cpp`), seal-time key pooling,
`KvFlashTargetQkScorer`
- `server/src/qwen3/qwen3_kvflash_scorer.{h,cpp}` — pflash-drafter scorer
- `server/src/pflash/kvflash_drafter_scorer.{h,cpp}` — pflash-drafter scorer
(tail attention; bisects on allocation pressure)
- `server/src/qwen35/*` — cache `ctx_alloc`, masked pooled decode, slot-mapped
spec verify, daemon flags
Expand Down
32 changes: 16 additions & 16 deletions optimizations/pflash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Long-context prefill is O(S²): vanilla llama.cpp on a single RTX 3090 takes **~
**What was missing:** no implementation that sits in front of a quantized GGUF target on a 24 GB card without dragging Python+Triton into the runtime path. PFlash is that:

- C++/CUDA daemon-resident drafter + scoring + target generation, all in one process, one ggml allocator.
- Custom Qwen3-0.6B BF16 forward (`qwen3_0p6b_loader.cpp` + `qwen3_0p6b_graph.cpp`) — no libllama.
- Custom Qwen3.5-0.8B BF16 forward (`src/pflash/qwen35_loader.cpp` + the qwen35 target graph) — no libllama.
- 4 CUDA kernels for the FlashPrefill `mean_K → score → select → sparse_fwd` algorithm (`flashprefill_kernels.cu`).
- BSA ([mit-han-lab/Block-Sparse-Attention](https://github.com/mit-han-lab/Block-Sparse-Attention), FA-2 derived, sm_80+) for the long-context drafter forward, wired without `libtorch` via 3 ATen/c10 header stubs (`server/deps/bsa_stubs/`).
- 128K → 2.6K span selection at `keep_ratio=0.05`, NIAH retrieved at every measured context, decode ~74 tok/s downstream.
Expand Down Expand Up @@ -72,21 +72,21 @@ cmake --build server/build --target test_dflash test_flashprefill_kernels -j

# 2. fetch weights (target + spec-decode draft + drafter scorer)
uv run hf download unsloth/Qwen3.6-27B-GGUF Qwen3.6-27B-Q4_K_M.gguf --local-dir server/models/
uv run hf download Qwen/Qwen3-0.6B model.safetensors tokenizer.json --local-dir server/models/drafter/
uv run hf download Qwen/Qwen3.5-0.8B model.safetensors tokenizer.json --local-dir server/models/drafter/
uv run hf download z-lab/Qwen3.6-27B-DFlash model.safetensors --local-dir server/models/draft/

# 2b. convert the drafter (Qwen3-0.6B HF) to a BF16 GGUF for the C++ scorer.
# 2b. convert the drafter (Qwen3.5-0.8B HF) to a BF16 GGUF for the C++ scorer.
# The submodule already vendors llama.cpp at deps/llama.cpp.
uv run python server/deps/llama.cpp/convert_hf_to_gguf.py server/models/drafter \
--outtype bf16 --outfile server/models/Qwen3-0.6B-BF16.gguf
--outtype bf16 --outfile server/models/Qwen3.5-0.8B-BF16.gguf

# 3. generate NIAH cases + run head-to-head bench against the C++ daemon
uv run --directory pflash python tests/niah_gen.py --n 1 --ctx 131072 --out /tmp/niah_128k.jsonl
uv run --directory pflash python tests/bench_niah_cpp.py \
--bin ../server/build/test_dflash \
--target ../server/models/Qwen3.6-27B-Q4_K_M.gguf \
--draft-spec ../server/models/draft/model.safetensors \
--drafter-gguf ../server/models/Qwen3-0.6B-BF16.gguf \
--drafter-gguf ../server/models/Qwen3.5-0.8B-BF16.gguf \
--cases /tmp/niah_128k.jsonl --keep-ratio 0.05 --n-gen 256
```

Expand All @@ -99,8 +99,8 @@ For an OpenAI-compatible server with transparent compression on long prompts, ru
| `--prefill-compression` | `off` / `auto` / `always` | `off` | When to run pflash. `auto` compresses when total prompt ≥ threshold; `always` compresses every request. |
| `--prefill-threshold` | int (tokens) | `32000` | Token threshold for `auto` mode. |
| `--prefill-keep-ratio` | float `(0, 1]` | `0.05` | Fraction of source tokens to keep after compression. `0.02` for 128K, `0.10` for 32K. |
| `--prefill-drafter` | path to `.gguf` | required when not `off` | Drafter weights (Qwen3-0.6B BF16 GGUF). |
| `--prefill-drafter-tokenizer` | HF repo id | `Qwen/Qwen3-0.6B` | HF tokenizer for the drafter vocab. |
| `--prefill-drafter` | path to `.gguf` | required when not `off` | Drafter weights (Qwen3.5-0.8B BF16 GGUF). |
| `--prefill-drafter-tokenizer` | HF repo id | `Qwen/Qwen3.5-0.8B` | HF tokenizer for the drafter vocab. |

When `--prefill-compression != off`, the server auto-sets `LUCE_LM_HEAD_FIX=0` and `LUCE_FA_WINDOW=0` (matching the bench harness — needed so the post-compress draft graph fits on a 24 GB card without OOM).

Expand All @@ -111,7 +111,7 @@ When `--prefill-compression != off`, the server auto-sets `LUCE_LM_HEAD_FIX=0` a
--prefill-compression auto \
--prefill-threshold 4096 \
--prefill-keep-ratio 0.02 \
--prefill-drafter server/models/Qwen3-0.6B-BF16.gguf
--prefill-drafter server/models/Qwen3.5-0.8B-BF16.gguf
```

Below the threshold the server runs the standard target generate (no compression). Above it, the server transparently runs `compress` on the daemon, swaps the prompt for the compressed text, and continues the normal `/v1/chat/completions` flow. Tool-calling requests (`req.tools` non-empty) skip compression so JSON tool definitions stay intact.
Expand Down Expand Up @@ -155,7 +155,7 @@ prompt (≤ 128K tokens)
▼
┌──────────────────────────────────────────────┐
│ drafter (in-process) │
│ custom Qwen3-0.6B BF16 forward in ggml │
│ custom Qwen3.5-0.8B BF16 forward in ggml │
│ FlashPrefill block-sparse via BSA (≥ 32K) │
│ tail-attention scoring → score [S] │
│ chunk(128) + alpha-threshold → top blocks │
Expand All @@ -177,7 +177,7 @@ prompt (≤ 128K tokens)
└──────────────────────────────────────────────┘
```

**Drafter forward.** Custom Qwen3-0.6B graph (`qwen3_0p6b_graph.cpp`) per-layer A/FP/B blocks: dense attention up to ~32K source, FlashPrefill sparse attention at and above. The 4 FP kernels live in `flashprefill_kernels.cu`; BSA dispatch is in `bsa_launcher.cu` + `bsa_fwd_inst.cu`.
**Drafter forward.** The Qwen3.5-0.8B drafter (`src/pflash/qwen35_drafter.cpp` on the qwen35 target graph) runs the model's first fifteen blocks and scores the context with block 15's NoPE Q/K attention-mass head; `PFLASH_QWEN35_LEGACY_SCORER=1` selects the all-layer running-max scorer instead.

**Scoring + selection.** Tail attention `Q[-N:] @ K^T / sqrt(d)` per layer/head, max over (L, H), mean over the tail window. Block-level threshold by `alpha * mean(scores)` selects which K-blocks each Q-block attends to. Configurable via `LUCE_FP_ALPHA`.

Expand Down Expand Up @@ -205,14 +205,14 @@ What we built:

- C++/CUDA port of the FlashPrefill algorithm: 4 kernels (`mean_K / score / select / sparse_fwd`), no Triton dependency.
- BSA ([mit-han-lab/Block-Sparse-Attention](https://github.com/mit-han-lab/Block-Sparse-Attention)) wired without `libtorch` via 3 ATen/c10 header stubs (`server/deps/bsa_stubs/`).
- Custom Qwen3-0.6B BF16 forward so the drafter runs through the same ggml allocator as the 27B target.
- Custom Qwen3.5-0.8B BF16 forward so the drafter runs through the same ggml allocator as the 27B target.
- Daemon stdin protocol (`compress` / `generate` / `park` / `unpark` / `free drafter`) so target + drafter coexist on a 24 GB card.
- NIAH harness against `llama-bench` for end-to-end validation.

## Scope and limits

- **Single 24 GB GPU** target (RTX 3090 reference). On 32+ GB cards, drafter + target can coexist and the park/unpark dance disappears.
- **Qwen3.6-27B Q4_K_M target + Qwen3-0.6B drafter** is the validated pair. Other targets/drafters need keep_ratio + alpha re-calibration.
- **Qwen3.6-27B Q4_K_M target + Qwen3.5-0.8B drafter** is the validated pair. Other targets/drafters need keep_ratio + alpha re-calibration.
- **NIAH single-needle** is the only retrieval task validated end-to-end. Multi-doc QA, long-form code retrieval, etc. still TBD.
- **sm_80+** required for BSA (RTX 3090 sm_86 is the reference). On sm_75 (Turing) the build auto-disables BSA and falls back to the WMMA path; expect a slower drafter forward at long ctx.

Expand Down Expand Up @@ -242,16 +242,16 @@ These are operator-side flags on the launcher; they do not change
PFlash semantics. A short prompt lane should keep the original
defaults.

### Drafter selection: BF16 Qwen3-0.6B for compress
### Drafter selection: BF16 Qwen3.5-0.8B for compress

PFlash compress benefits from a small, fast drafter. The validated
choice is **Qwen3-0.6B** in **BF16 safetensors** with ~5 attention
choice is **Qwen3.5-0.8B** in **BF16 safetensors** with ~5 attention
layers. The DFlash drafter for the same target works correctly
during decode-after-unpark but is heavier than ideal for compress.

Practical guidance:

- Use Qwen3-0.6B BF16 for `compress` (PFlash side).
- Use Qwen3.5-0.8B BF16 for `compress` (PFlash side).
- Reuse the larger DFlash drafter for `decode` after unpark
(DFlash side).

Expand All @@ -262,7 +262,7 @@ simultaneously on a 24 GB GPU.

Reproducible comparison vs Ollama native `/api/chat` on the same
64K unique-prompt summary task, RTX 6000 Ada sm_89,
Qwen3.6-27B-Q4_K_M, FA_WINDOW=0. Drafter setup: Qwen3-0.6B BF16
Qwen3.6-27B-Q4_K_M, FA_WINDOW=0. Drafter setup: Qwen3.5-0.8B BF16
GGUF for the PFlash compress path (see "Drafter selection" above);
the larger DFlash drafter on the luce daemon side ran as FP16
safetensors during decode-after-unpark on this run. Feel free to
Expand Down
2 changes: 1 addition & 1 deletion optimizations/pflash/pflash/dflash_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def park_target(self): self._send("park target\n")
def unpark_target(self): self._send("unpark target\n")

def compress(self, prompt_ids: list[int], keep_ratio: float, drafter_gguf: str,
drafter_arch: str = "qwen3-0.6b") -> list[int]:
drafter_arch: str = "qwen35-0.8b") -> list[int]:
"""C++ drafter score+compress via daemon. Returns compressed token ids.

Daemon command: compress <bin> <keep_x1000> <drafter_gguf> <drafter_arch>
Expand Down
8 changes: 4 additions & 4 deletions optimizations/pflash/tests/bench_niah_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ def main():
ap.add_argument("--target", default="/opt/lucebox/models/Qwen3.6-27B-Q4_K_M.gguf")
ap.add_argument("--draft-spec", default="/home/lucebox/lucebox-hub/server/models/draft/model.safetensors",
help="draft model used for spec decoding (NOT drafter scorer)")
ap.add_argument("--drafter-gguf", default="/home/lucebox/lucebox-hub/server/models/Qwen3-0.6B-BF16.gguf",
help="C++ drafter scorer GGUF (Qwen3-0.6B BF16)")
ap.add_argument("--drafter-arch", default="qwen3-0.6b", choices=["qwen3-0.6b", "qwen35-0.8b"],
ap.add_argument("--drafter-gguf", default="/home/lucebox/lucebox-hub/server/models/Qwen3.5-0.8B-BF16.gguf",
help="C++ drafter scorer GGUF (Qwen3.5-0.8B BF16)")
ap.add_argument("--drafter-arch", default="qwen35-0.8b", choices=["qwen35-0.8b"],
help="C++ drafter architecture selector")
ap.add_argument("--target-tokenizer", default="Qwen/Qwen3.6-27B")
ap.add_argument("--drafter-tokenizer", default="Qwen/Qwen3-0.6B")
ap.add_argument("--drafter-tokenizer", default="Qwen/Qwen3.5-0.8B")
ap.add_argument("--max-ctx", type=int, default=16384,
help="daemon KV cache max ctx; sized for compressed prompt+gen, NOT source")
ap.add_argument("--keep-ratio", type=float, default=0.020)
Expand Down
2 changes: 1 addition & 1 deletion optimizations/pflash/tests/niah_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def main():
# Default matches bench_niah_cpp.py's --drafter-tokenizer, since that is
# the tokenizer the downstream NIAH bench uses to size case["prompt"]
# for the drafter forward. Override for any other harness.
ap.add_argument("--tokenizer", default="Qwen/Qwen3-0.6B")
ap.add_argument("--tokenizer", default="Qwen/Qwen3.5-0.8B")
args = ap.parse_args()
tok = AutoTokenizer.from_pretrained(args.tokenizer)

Expand Down
34 changes: 15 additions & 19 deletions server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ endif()

# ─── ggml (vendored from llama.cpp) ──────────────────────────────────
#
# We use only ggml from the vendored llama.cpp snapshot. The drafter is
# loaded via our own custom Qwen3-0.6B forward
# (src/qwen3/qwen3_loader.cpp + src/qwen3/qwen3_graph.cpp)
# We use only ggml from the vendored llama.cpp snapshot. The PFlash drafter
# is loaded via our own custom Qwen3.5-0.8B forward
# (src/pflash/qwen35_loader.cpp + src/qwen35/qwen35_target_graph.cpp)
# rather than libllama, so libllama is not built.
#
# No BLAS, no Metal, no Vulkan, no examples/tests/tools.
Expand Down Expand Up @@ -476,6 +476,7 @@ set(LUCE_SRC_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/src/bailingmoe3
${CMAKE_CURRENT_SOURCE_DIR}/src/laguna
${CMAKE_CURRENT_SOURCE_DIR}/src/qwen3
${CMAKE_CURRENT_SOURCE_DIR}/src/pflash
${CMAKE_CURRENT_SOURCE_DIR}/src/gemma4
${CMAKE_CURRENT_SOURCE_DIR}/src/deepseek4
${CMAKE_CURRENT_SOURCE_DIR}/src/server
Expand All @@ -492,11 +493,14 @@ add_library(luce_common STATIC
src/draft/draft_gguf_loader.cpp
src/draft/draft_safetensors_loader.cpp
src/draft/draft_graph.cpp
src/qwen3/anchor_scan.cpp
src/qwen3/qwen3_drafter.cpp
src/qwen3/qwen3_kvflash_scorer.cpp
src/pflash/anchor_scan.cpp
src/pflash/pflash_selection.cpp
src/pflash/pflash_drafter.cpp
src/pflash/pflash_compress.cpp
src/pflash/qwen35_drafter.cpp
src/pflash/qwen35_loader.cpp
src/pflash/kvflash_drafter_scorer.cpp
src/qwen3/qwen3_loader.cpp
src/qwen3/qwen3_graph.cpp
src/qwen3/qwen3_backend.cpp
src/qwen3/qwen3_daemon.cpp
src/gemma4/gemma4_loader.cpp
Expand Down Expand Up @@ -695,7 +699,7 @@ endif()
# - CUDA sm_60–sm_69 (Pascal): scalar F16, no tensor cores — flashprefill_scalar.cu
# - HIP Phase 1 (default): ggml q8 fallback, no custom kernels.
# - HIP Phase 2 (LUCE_HIP_SM80_EQUIV=ON): rocWMMA-native kernels.
# The dispatch in qwen3_graph.cpp checks buffer type at runtime:
# The dispatch in flashprefill.h checks buffer type at runtime:
# BF16 buffers → bf16 WMMA kernel; F16 buffers → f16 WMMA kernel; else → ggml FA.
if(LUCE_GPU_BACKEND STREQUAL "hip")
# rms_norm_hip.cu is needed by the HIP chunk-B graph path regardless of SM80_EQUIV.
Expand Down Expand Up @@ -1379,12 +1383,6 @@ if(LUCE_TESTS)
target_link_libraries(test_turbo_wht_warp PRIVATE CUDA::cudart)
list(APPEND _raw_unit_test_targets test_turbo_wht_warp)
endif()
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/test_drafter_tail_capture_guard.cpp")
# RED phase binary: same source WITHOUT the fix flag — documents the bug.
add_executable(test_drafter_tail_capture_guard_red
test/test_unit_main.cpp
test/test_drafter_tail_capture_guard.cpp)
endif()
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/test_draft_vs_reference.cpp")
add_executable(test_draft_vs_reference test/test_draft_vs_reference.cpp)
target_link_libraries(test_draft_vs_reference PRIVATE luce_common)
Expand Down Expand Up @@ -2077,10 +2075,8 @@ if(LUCE_TESTS)
test/test_chain_rollback_policy.cpp
test/test_ddtree_tau.cpp
test/test_anchor_transitive.cpp
test/test_drafter_early_exit_score_range.cpp
test/test_drafter_tail_capture_guard.cpp
test/test_drafter_warm_path_regression.cpp
test/test_qwen3_buffer_plan.cpp
test/test_pflash_drafter_ipc.cpp
test/test_pflash_selection.cpp
test/test_model_test_paths.cpp
test/test_gguf_mmap.cpp
test/test_kv_quant.cpp
Expand All @@ -2104,7 +2100,7 @@ if(LUCE_TESTS)
src/server/scheduler.cpp
src/server/model_card.cpp
src/server/prompt_normalize.cpp
src/qwen3/anchor_scan.cpp)
src/pflash/anchor_scan.cpp)
# Keep the GREEN formula target-local: the separate RED regression
# executable compiles the same source without this definition.
target_compile_definitions(test_server_unit PRIVATE
Expand Down
Loading
Loading