feat(kvflash): pager serialize/deserialize + QK residency library
What
Model-agnostic KV-paging primitives in server/src/common/, already consumed by the qwen35/qwen35moe, gemma4, and laguna backends. This is the reusable foundation extracted from the kvflash snapshot-chain work — lands independently of any backend integration.
Why split it out
The full kvflash snapshot chain (~4000 LOC) couples tightly into qwen35_backend.cpp. The library (pager + QK scoring) does not — it touches only common/ headers + tests. Landing it standalone gives every backend a shared, tested KV-paging + residency layer without the integration-review burden.
Contents
kvflash_pager.h—serialize(max_chunks)/deserializev1 format with ledger section (was_resident + qk_score + dtype) for pooled-prefix snapshot/restore; critical-chunk pinning + deadlock guard;floor_to_chunk;identity_prefix_covers(preserved for existing consumers).kvflash_qk.h— cosine QK residency scoring with seeded-fallback; overflow-safeseeded_n(limit defaults to 0, notn_chunks, preventing OOB reads when a caller omits the length).
Verification
- Builds against main's
llama.cppsubmodule (no fork dependency). test_kvflash_pagerPASS: serde + pinning + partial-serialize + ledger round-trip.test_kvflash_qkPASS: pure-math scoring incl. seeded-sentinel fallback.- Full
dflash_common(main's server code) recompiles —identity_prefix_coverskeeps laguna/gemma4 working. - CPU-only; no GPU required.
Scope
5 files, +713/−18. No server-backend files, no bench/docs noise. Supersedes the library portions of #429/#445/#430/#446 (those integration slices remain tracked separately).
Follow-up PR (qwen35 pooled snapshot-chain integration) will stack on top of this.