# bench/ — benchmark executables. EXPLICIT (not globbed): this dir also holds
# unbuilt experiments (het_gemv.cpp, matmul_bench.mm, mlx_baseline.py) that must
# NOT become build targets. Each real benchmark is opted in by name.
add_executable(chat-bench chat-bench.cpp)
target_link_libraries(chat-bench PRIVATE mlx-magic-lib)

# PLAN12 item-2a acceptance proof: forward_batch(B twins) ≡ forward(), bit-for-bit.
# Needs a model dir at runtime (required arg — no hardcoded path); builds without one.
add_executable(forward-batch-proof forward-batch-proof.cpp)
target_link_libraries(forward-batch-proof PRIVATE mlx-magic-lib)

# PLAN12 10.85 measurement: full greedy decode of B rows serial (forward) vs batched
# (forward_batch). Proves multi-step decode independence AND prints the honest tok/s ratio.
add_executable(batch-decode-bench batch-decode-bench.cpp)
target_link_libraries(batch-decode-bench PRIVATE mlx-magic-lib)

# PLAN12 item-5 KV paging proof: one real full-attn layer's decode is bit-identical whether its
# KV lives in the plain LayerCache or is round-tripped through a BlockPool-owned KVPageArena page.
add_executable(kv-page-proof kv-page-proof.cpp)
target_link_libraries(kv-page-proof PRIVATE mlx-magic-lib)

# PLAN12 item-5 step 5: KV block-paging bit-exact + row-independent through the REAL forward_batch
# full-attn path (paging ON via KVPagingCtx vs OFF). Needs a model dir at runtime.
add_executable(kv-forward-paging-proof kv-forward-paging-proof.cpp)
target_link_libraries(kv-forward-paging-proof PRIVATE mlx-magic-lib)

# PLAN12 item-5 step 7: cross-request prefix REUSE — a second request reuses the first's resident KV
# blocks (content hit, no prefix recompute) and decodes bit-identically. Needs a model dir at runtime.
add_executable(kv-prefix-reuse-proof kv-prefix-reuse-proof.cpp)
target_link_libraries(kv-prefix-reuse-proof PRIVATE mlx-magic-lib)

# PLAN12 item-7 (11.11): GDN boundary-snapshot serial-equivalence — a GatedDeltaNet layer's recurrent
# state snapshotted to safetensors, cleared, restored, and decoded bit-identically. Needs a model dir.
add_executable(gdn-snapshot-proof gdn-snapshot-proof.cpp)
target_link_libraries(gdn-snapshot-proof PRIVATE mlx-magic-lib)

# PLAN12 item-6 ACCEPTANCE: cross-request prefill-skip through the REAL arch batch fn — a second
# request extending a prior prompt skips the shared prefix + returns identical logits. force_load so
# the qwen35 batch registrar (static registrar) links, same as generate-batch-proof. Needs a model dir.
add_executable(kv-reuse-proof kv-reuse-proof.cpp)
target_link_libraries(kv-reuse-proof PRIVATE mlx-magic-lib)
mlxm_force_load(kv-reuse-proof)

# PLAN12 15.01 measurement harness: attribute the ~14-vs-32 tok/s GDN gap to named stages.
# Runs one decode with the stage profile OFF (honest tok/s) then ON (host/gpu per-stage table).
# Needs a model dir at runtime (required arg — no hardcoded path); builds without one. force_load
# so the qwen35 arch registrar links (it is a static registrar, same as generate-batch-proof).
add_executable(gdn-gap-profile gdn-gap-profile.cpp)
target_link_libraries(gdn-gap-profile PRIVATE mlx-magic-lib)
mlxm_force_load(gdn-gap-profile)

# PLAN12 item-2c ISOLATED probe: the fused delta-rule Metal kernel alone (no model/weights).
# Proves whether a BATCHED launch (grid.z=Hv*B, stacked rows) equals per-row solo launches —
# isolates a 2c kernel/launch bug from a host-integration bug. Needs the GPU but no model dir.
add_executable(gdn-batch-probe gdn-batch-probe.cpp)
target_link_libraries(gdn-batch-probe PRIVATE mlx-magic-lib)

# PLAN12 10.85 correctness proof: serial generate() vs batched generate_batch() over the
# FULL sampling stack (RowDecoder) — per-request decoded text must be byte-identical.
# Unlike the other benches this one uses the tokenizer + the arch batch REGISTRY, whose
# entries are static registrars — force_load so they aren't dead-stripped from the .a
# (same mechanism the server relies on; also confirms the qwen35 batch registrar links).
add_executable(generate-batch-proof generate-batch-proof.cpp)
target_link_libraries(generate-batch-proof PRIVATE mlx-magic-lib)
mlxm_force_load(generate-batch-proof)

# PLAN12 14.05E/14.07 — operator tool: write the 14.02 split checkpoint to the exact
# path the streaming server derives (split_dir_for), so the offline split step and the
# server can never disagree about where shards live.
add_executable(weight-stream-split weight-stream-split.cpp)
target_link_libraries(weight-stream-split PRIVATE mlx-magic-lib)

# PLAN12 11.10 acceptance proof: MLA compression ratio (gate 1) + absorbed vs
# unabsorbed equivalence (gate 2), measured on a REAL DeepSeek-V2 checkpoint.
add_executable(mla-equivalence-proof mla-equivalence-proof.cpp)
target_link_libraries(mla-equivalence-proof PRIVATE mlx-magic-lib)

# PLAN12 11.10 diagnostic: our forward's top-k logits for FIXED token ids, so a
# comparison against mlx_lm isolates the forward from prompt rendering.
add_executable(deepseek-logit-probe deepseek-logit-probe.cpp)
target_link_libraries(deepseek-logit-probe PRIVATE mlx-magic-lib)
