Skip to main content

fuel_dispatch/fkc/
register.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! The REGISTRATION slice: a parsed+lowered provider bundle →
3//! live kernel registrations on the two dispatch registries
4//! (adoption plan §1.2, §1.3, §2.1, §2.2).
5//!
6//! This module makes the FKC importer **end-to-end**: a contract bundle
7//! file becomes concrete entries in a [`KernelBindingTable`] (primitive
8//! `op_kind` contracts) and a [`FusedKernelRegistry`] (`fused_op`
9//! contracts). The pipeline is:
10//!
11//! ```text
12//! import_bundle_str(src)  =  parse_file(src) → lower_file(.., link) → ImportedProvider
13//! import_bundle(path)     =  read file       → import_bundle_str
14//! import_glob(pattern)    =  glob files      → import_bundle_str each → MERGE (front-matter must agree)
15//! provider.register_into(table, fused)       =  the actual registry inserts + finalize gate
16//! ```
17//!
18//! ## Cost decision for this slice
19//!
20//! Two cost paths coexist:
21//!
22//! 1. **Named cost-fn trampoline (§4.4, Task-F).** A primitive contract whose
23//!    `cost.cost_fn` NAMES a registered cost fn has that name resolved through
24//!    the provider's [`LinkRegistry::resolve_cost_fn`](crate::fkc::LinkRegistry)
25//!    at lower time and the resulting [`CostFn`](crate::kernel::CostFn) pinned
26//!    on the binding by [`ImportedProvider::register_into`]. A pinned cost fn
27//!    is NOT the [`unknown_cost`] sentinel, so the
28//!    [`fill_unset_cost_for_backend`](crate::kernel::KernelBindingTable::fill_unset_cost_for_backend)
29//!    pass leaves it — the mechanism that lets a contract carry a real,
30//!    shape-aware cost model (e.g. the CUDA `flash_decoding` static
31//!    infeasibility gate `cost_flash_decoding_cuda`). An unresolved name is a
32//!    typed [`FkcError::UnknownCostFn`], never a silent fallback.
33//! 2. **Judge-bootstrapped default (the common case, [consumer-ahead]).** A
34//!    contract that names NO cost fn registers with the [`unknown_cost`]
35//!    sentinel `CostFn` (primitives) / [`fused_unknown_cost`] (fused ops);
36//!    the fill pass then upgrades the primitive sentinel to the op/backend
37//!    default, and the Judge refines empirically. The parsed
38//!    [`CompiledCostExpr`](crate::fkc::cost_expr::CompiledCostExpr) stays on
39//!    the `Resolved*` record. Fused ops have no named-cost-fn path yet (the
40//!    fused cost-fn signature differs; no consumer today).
41
42use std::collections::HashSet;
43use std::path::Path;
44use std::sync::{Mutex, OnceLock};
45
46use fuel_graph::registry::FusedOpParams;
47use fuel_ir::Shape;
48use fuel_ir::backend::BackendCapabilities;
49use fuel_ir::probe::BackendId;
50
51use crate::fkc::error::FkcError;
52use crate::fkc::lower::{LinkRegistry, Resolved, ResolvedFused, ResolvedPrimitive, lower_file};
53use crate::fkc::parse::parse_file;
54use crate::fused::{BackendImpl, CostEstimate, FusedKernelRegistry};
55use crate::kernel::{KernelBindingTable, unknown_cost};
56
57// ===========================================================================
58// kernel_source interner (§1.3)
59// ===========================================================================
60
61/// Intern a `kernel_source` (or any short, bounded-cardinality provider
62/// tag) string into a `&'static str`, leaking it on first sighting.
63///
64/// `BindingEntry.kernel_source` and `BackendImpl.dtypes` use `&'static`
65/// data, but a contract's `kernel_source` is read from a file at runtime,
66/// so it is not `'static`. Resolution per plan §1.3: a process-wide
67/// `OnceLock<Mutex<HashSet<&'static str>>>` interner that `Box::leak`s the
68/// owned string on first sighting and returns the cached handle on every
69/// repeat.
70///
71/// **Bounded process-lifetime leak.** Each *distinct* string is leaked
72/// exactly once for the life of the process. The set of distinct
73/// `kernel_source` tags is a handful (one per provider source: e.g.
74/// `"portable-cpu"`, `"aocl"`, `"mkl"`), so the total leaked bytes are
75/// trivially bounded and never grow under repeated imports of the same
76/// provider. This is the same posture `precision.rs` takes for precision
77/// `notes`. (Alternative, out of scope here: widen `kernel_source` to
78/// `Cow<'static, str>` in a follow-up.)
79pub(crate) fn intern(s: &str) -> &'static str {
80    static POOL: OnceLock<Mutex<HashSet<&'static str>>> = OnceLock::new();
81    let pool = POOL.get_or_init(|| Mutex::new(HashSet::new()));
82    let mut guard = pool.lock().expect("kernel_source interner poisoned");
83    if let Some(existing) = guard.get(s) {
84        return existing;
85    }
86    let leaked: &'static str = Box::leak(s.to_string().into_boxed_str());
87    guard.insert(leaked);
88    leaked
89}
90
91/// Intern a per-operand dtype list into a `&'static [DType]` slice for a
92/// fused [`BackendImpl`] (whose `dtypes` field is `&'static [DType]`).
93/// Backed by the same bounded process-lifetime leak as [`intern`]: each
94/// distinct dtype tuple is leaked once and cached. Distinct fused ops use
95/// a small, fixed set of dtype tuples, so the leak is bounded.
96fn intern_dtypes(dtypes: &[fuel_ir::DType]) -> &'static [fuel_ir::DType] {
97    use fuel_ir::DType;
98    static POOL: OnceLock<Mutex<HashSet<&'static [DType]>>> = OnceLock::new();
99    let pool = POOL.get_or_init(|| Mutex::new(HashSet::new()));
100    let mut guard = pool.lock().expect("fused dtypes interner poisoned");
101    if let Some(existing) = guard.get(dtypes) {
102        return existing;
103    }
104    let leaked: &'static [DType] = Box::leak(dtypes.to_vec().into_boxed_slice());
105    guard.insert(leaked);
106    leaked
107}
108
109// ===========================================================================
110// Fused-cost sentinel (the fused equivalent of `unknown_cost`)
111// ===========================================================================
112
113/// The fused-op cost-fn sentinel — the fused analog of
114/// [`unknown_cost`]. There is no public fused sentinel in `fused.rs`
115/// (registrations that omit a cost use `CostEstimate::default()` inline),
116/// so the importer supplies its own trivial zero-cost fn matching the
117/// fused cost-fn signature
118/// `fn(&[Shape], &FusedOpParams, &BackendCapabilities) -> CostEstimate`.
119///
120/// [consumer-ahead]: declared cost priors are retained on
121/// `ResolvedFused.cost` but not yet wired into a `CostFn`; the Judge
122/// bootstraps all imported costs for now (a follow-up slice adds the cost
123/// trampoline, plan §2.3 strategy A).
124pub fn fused_unknown_cost(
125    _shapes: &[Shape],
126    _params: &FusedOpParams,
127    _caps: &BackendCapabilities,
128) -> CostEstimate {
129    CostEstimate::default()
130}
131
132// ===========================================================================
133// ImportedProvider (§1.2)
134// ===========================================================================
135
136/// A parsed + validated provider bundle, holding the resolved per-kernel
137/// records ready to register. Construction (`import_*`) already ran the
138/// parse + restricted-YAML pre-pass + lowering (string → typed dispatch
139/// records); [`Self::register_into`] only does the registry inserts +
140/// the duplicate-detection gate.
141#[derive(Debug, Clone)]
142pub struct ImportedProvider {
143    /// `provider.name` (front-matter).
144    pub name: String,
145    /// `provider.backend` (front-matter), the registry key backend.
146    pub backend: BackendId,
147    /// `provider.kernel_source` (front-matter), interned to `&'static`.
148    pub kernel_source: &'static str,
149    /// `provider.revision_base` (front-matter) — the provider build id folded
150    /// into `kernel_revision_hash`.
151    ///
152    /// Retained on the imported provider *specifically* so [`import_glob`] can
153    /// enforce §9.2's "front-matter must agree across files". It was previously
154    /// consumed during lowering and dropped, which made that agreement
155    /// structurally uncheckable: two files of one globbed provider could
156    /// declare different bases, and since `revision_base` feeds
157    /// `kernel_revision_hash` — the key the verification ledger is looked up
158    /// by — the merged provider would silently carry kernels whose revision
159    /// hashes were computed against different roots.
160    pub revision_base: Option<String>,
161    /// `provider.link_registry` (front-matter) — the symbol path of the table
162    /// this file's `entry_point`s are declared to resolve against.
163    ///
164    /// Retained for the same reason as [`Self::revision_base`]: §9.2 requires
165    /// it to AGREE across a glob's files, and a field that is consumed during
166    /// lowering and dropped cannot be compared at merge time. `import_glob`
167    /// binds every file it merges through the single registry its *caller*
168    /// supplied, so disagreement here means at least one file's entry points
169    /// were resolved against a table its author never named.
170    pub link_registry: Option<String>,
171    /// Lowered `op_kind` contracts → the binding table.
172    pub primitives: Vec<ResolvedPrimitive>,
173    /// Lowered `fused_op` contracts → the fused registry.
174    pub fused: Vec<ResolvedFused>,
175    /// Soft import diagnostics (§3.5 warns, precision downgrades, etc.).
176    pub warnings: Vec<crate::fkc::ImportWarning>,
177}
178
179impl ImportedProvider {
180    /// Split a flat `Vec<Resolved>` into the primitive / fused buckets.
181    fn from_resolved(
182        name: String,
183        backend: BackendId,
184        kernel_source: &'static str,
185        revision_base: Option<String>,
186        link_registry: Option<String>,
187        resolved: Vec<Resolved>,
188        warnings: Vec<crate::fkc::ImportWarning>,
189    ) -> Self {
190        let mut primitives = Vec::new();
191        let mut fused = Vec::new();
192        for r in resolved {
193            match r {
194                Resolved::Primitive(p) => primitives.push(p),
195                Resolved::Fused(f) => fused.push(f),
196            }
197        }
198        ImportedProvider {
199            name,
200            backend,
201            kernel_source,
202            revision_base,
203            link_registry,
204            primitives,
205            fused,
206            warnings,
207        }
208    }
209
210    /// Register every primitive contract into `table` and every fused
211    /// contract into `fused`, then run the duplicate-detection gate.
212    ///
213    /// **Describe-only sections (`registrable: false`, §3.10) are already
214    /// excluded** before this point: [`lower_file`] (called by the `import_*`
215    /// constructors) filters them out, so `self.primitives` / `self.fused`
216    /// contain only registrable kernels. A documentation-only section therefore
217    /// never reaches the binding table / fused registry or the duplicate-
218    /// `KernelRef` gate — it is honest docs, not a dispatch decision point.
219    ///
220    /// Per slice (§2.1 / §2.2): each primitive becomes a
221    /// [`KernelBindingTable::register_full_with_source`] insert; each
222    /// fused op becomes a [`FusedKernelRegistry::register`] of a
223    /// [`BackendImpl`]. **Cost is the sentinel for every kernel this
224    /// slice** — `unknown_cost` for primitives, [`fused_unknown_cost`]
225    /// for fused ops (see the module-level cost note); the parsed cost AST
226    /// stays on the `Resolved*` record.
227    ///
228    /// `register_full_with_source` is append-only and returns `()` today;
229    /// the **same** `KernelRef` driven onto one `(op, dtypes, backend)`
230    /// key twice is detected by [`KernelBindingTable::finalize`], which
231    /// this method calls **after all inserts** and maps to
232    /// [`FkcError::DuplicateKernelRef`] (never a panic — the import path is
233    /// `Result` end-to-end).
234    pub fn register_into(
235        &self,
236        table: &mut KernelBindingTable,
237        fused: &mut FusedKernelRegistry,
238    ) -> Result<(), FkcError> {
239        // --- Primitives → KernelBindingTable (§2.1) ---
240        for p in &self.primitives {
241            let kernel_source: &'static str = intern(&p.kernel_source);
242            // §4.4 cost-fn trampoline (Task-F): when the contract PINS a cost
243            // fn (`cost.cost_fn`, resolved through the LinkRegistry at lower
244            // time), stamp THAT `CostFn` — it survives the
245            // `fill_unset_cost_for_backend` pass (which only replaces the
246            // `unknown_cost` sentinel), so a contract can carry a real,
247            // shape-aware cost model (e.g. the CUDA `flash_decoding` static
248            // infeasibility gate). When it does NOT pin one, keep the
249            // `unknown_cost` sentinel so the fill pass upgrades it to the
250            // op/backend default (the Judge-bootstrapped path for every other
251            // imported primitive).
252            let cost_fn = p.cost_fn.unwrap_or(unknown_cost);
253            // FKC gap-closure Task 2.2 (§2.3): compile the contract's
254            // declared cost AST (if any, and if no pinned `cost_fn` already
255            // wins — see `stamp_primitive_cost_expr`) into the interned
256            // `'static` handle threaded onto the binding below.
257            let cost_expr = crate::fkc::cost_compile::stamp_primitive_cost_expr(p);
258            // Structural-miss fallback bit (FKC §4.12): compute genericity
259            // ONCE from the retained five-flag `ResolvedLayout` set and stamp
260            // it onto the binding so the live dispatch pick site reads a
261            // precomputed bool (never re-derives it from the lossy
262            // single-bool `KernelCaps`). Baracuda's miss telemetry keys on it.
263            let is_generic = crate::fkc::is_generic_contract(&p.layouts);
264            // Thread the contract-computed revision hash onto the binding (FKC
265            // §4.11 basis tuple) so the Baracuda dispatch-telemetry `ImplId`
266            // pins the exact kernel build. Hand-written kernels stamp
267            // `UNTRACKED` (`0`); only this FKC-import path carries a real one.
268            table.register_full_with_source_generic(
269                p.op,
270                &p.dtypes,
271                p.backend,
272                p.kernel,
273                p.caps,
274                p.precision,
275                cost_fn,
276                kernel_source,
277                is_generic,
278                p.revision.0,
279                // FKC gap-closure Task 2.2: the compiled cost AST (or `None`
280                // when a pinned `cost_fn` already wins, or the contract
281                // declared no cost expression at all).
282                cost_expr,
283            );
284        }
285
286        // --- Fused ops → FusedKernelRegistry (§2.2) ---
287        for f in &self.fused {
288            // FKC gap-closure Task 2.4 (§2.3): compile the contract's
289            // declared cost AST (if any) into the interned `'static` handle
290            // threaded onto `cost_expr` below. `fused_layer1_cost` prefers
291            // it over both the hand-written `cost` fn (still stamped as the
292            // `fused_unknown_cost` sentinel here) and the decompose-derived
293            // fallback.
294            let dtypes: &'static [fuel_ir::DType] = intern_dtypes(&f.dtypes);
295            fused.register(
296                f.id,
297                f.backend,
298                BackendImpl {
299                    kernel: f.kernel,
300                    dtypes,
301                    cost: fused_unknown_cost,
302                    precision: f.precision,
303                    caps: f.caps,
304                    revision: f.revision,
305                    cost_expr: crate::fkc::cost_compile::stamp_fused_cost_expr(f),
306                },
307            );
308            // Finding 5.4 (FKC side, Task 3.6): preserve the contract's
309            // `return.bundle` per-slot names in the side-table, keyed by the
310            // SAME (id, backend, dtypes) tuple just registered above. Empty
311            // for a single-output section (the common case) — skip the
312            // insert rather than recording a vacuous entry.
313            if !f.bundle_slot_names.is_empty() {
314                fused.record_bundle_slot_names(f.id, f.backend, dtypes, &f.bundle_slot_names);
315            }
316        }
317
318        // --- The duplicate-detection gate, surfaced as a typed error ---
319        // `register_full_with_source` is append-only; `finalize` is the
320        // single pass that detects the same `KernelRef` registered twice
321        // at one key. Map its dispatch `Error` message into a typed
322        // `FkcError::DuplicateKernelRef` (never-panic on the import path).
323        table
324            .finalize()
325            .map_err(|e| FkcError::DuplicateKernelRef(e.to_string()))?;
326
327        Ok(())
328    }
329}
330
331// ===========================================================================
332// Public import entry points (§1.2)
333// ===========================================================================
334
335/// Parse + validate a single bundle markdown file's bytes into an
336/// [`ImportedProvider`]. Pure: no I/O of its own (tests pass `&str`).
337///
338/// `parse_file` → `lower_file(.., link)` → assemble. Every failure is a
339/// typed [`FkcError`]; never panics.
340pub fn import_bundle_str(src: &str, link: &dyn LinkRegistry) -> Result<ImportedProvider, FkcError> {
341    let file = parse_file(src)?;
342    // Run the build-time validators (the V-FKC-* battery, §10) AFTER parse so a
343    // structurally / coherence-bad contract fails import before any lowering or
344    // registration touches the dispatch surface. Validation runs over EVERY
345    // section, including describe-only ones (§3.10) — their descriptive checks
346    // (dtype, layout, cost, precision) still apply; only their dispatch-resolution
347    // checks are skipped. The ONE relaxation: a describe-only section's
348    // CONSUMER-AHEAD gate (`GatherNotYetSupported` / `MxNotYetRegistrable`) is a
349    // correct "describable-but-not-yet-registrable" outcome, so `validate_file`
350    // treats it as non-blocking (the same "deferred" posture the corpus CI lint
351    // takes) — a describe-only documentation section must not block a bundle's
352    // importable sections.
353    crate::fkc::validate::validate_file(&file)?;
354    // `lower_file` then EXCLUDES describe-only sections from the registered set
355    // (§3.10): they never become a Resolved* record and are never registered.
356    let mut warnings: Vec<crate::fkc::ImportWarning> = Vec::new();
357    let mut resolved = lower_file(&file, link, &mut warnings)?;
358    let provider = &file.front_matter.provider;
359    let backend = lower_backend_str(&provider.backend)?;
360    let kernel_source = intern(&provider.kernel_source);
361
362    // V-FKC-9 (Task 4.3): gate every lowered record's declared precision
363    // against the empirical verification ledger BEFORE it reaches
364    // `from_resolved` / the binding table. Any machine-checkable claim
365    // (bit-stability, ULP, etc.) with no matching `pass` ledger entry for
366    // this exact `(kernel_source, backend, dtypes, kernel_revision_hash)`
367    // collapses to `PrecisionGuarantee::UNAUDITED` plus a warning — an
368    // asserted-but-never-measured claim must not survive import as if it
369    // had been verified. Task 4.5b seeded the embedded ledger with real
370    // empirical `pass` entries for the fused CPU ops flipped to
371    // `audited: true` on 2026-07-03, so THOSE records are honored here
372    // (same revision hash, since `default_kernel_registry()`'s
373    // `register_*_fused_from_contract` helpers stamp `BackendImpl.revision`
374    // from this SAME `ResolvedFused.revision`); a primitive `op_kind`
375    // contract like `add_f32` (never in Task 4.5b's fused-op scope) has no
376    // ledger entry and is downgraded.
377    let ledger = crate::fkc::verify::embedded();
378    for r in &mut resolved {
379        match r {
380            Resolved::Primitive(p) => {
381                let q = crate::fkc::verify::LedgerQuery {
382                    kernel_ref: p.kernel_source.as_str(),
383                    backend: p.backend,
384                    dtypes: p.dtypes.as_slice(),
385                    kernel_revision_hash: p.revision.0,
386                };
387                p.precision =
388                    crate::fkc::verify::gate_precision(p.precision, &q, ledger, &mut warnings);
389            }
390            Resolved::Fused(f) => {
391                let q = crate::fkc::verify::LedgerQuery {
392                    kernel_ref: f.kernel_source.as_str(),
393                    backend: f.backend,
394                    dtypes: f.dtypes.as_slice(),
395                    kernel_revision_hash: f.revision.0,
396                };
397                f.precision =
398                    crate::fkc::verify::gate_precision(f.precision, &q, ledger, &mut warnings);
399            }
400        }
401    }
402
403    Ok(ImportedProvider::from_resolved(
404        provider.name.clone(),
405        backend,
406        kernel_source,
407        provider.revision_base.clone(),
408        provider.link_registry.clone(),
409        resolved,
410        warnings,
411    ))
412}
413
414/// Convenience: read a bundle file at `path`, then [`import_bundle_str`].
415pub fn import_bundle(
416    path: impl AsRef<Path>,
417    link: &dyn LinkRegistry,
418) -> Result<ImportedProvider, FkcError> {
419    let path = path.as_ref();
420    let src = std::fs::read_to_string(path).map_err(|e| FkcError::Io {
421        path: path.display().to_string(),
422        reason: e.to_string(),
423    })?;
424    import_bundle_str(&src, link)
425}
426
427/// Glob multiple per-kernel / per-bundle FKC files into one provider
428/// (§9.2). Each matched file is parsed + lowered independently and then
429/// **merged** into a single [`ImportedProvider`]; the front-matter
430/// `provider.name` / `provider.backend` / `provider.kernel_source` must
431/// **agree** across every file or [`FkcError::ProviderMismatch`].
432///
433/// Glob order is sorted for determinism (so duplicate-detection /
434/// revision-hash order is stable across runs).
435///
436/// **No new dependency.** `fuel-dispatch` has no `glob` crate dep, and the
437/// adoption plan (§1.2) prefers no new dep — so this uses a minimal
438/// directory walk + a small filename matcher over the pattern's last
439/// component rather than pulling in `glob`. The supported pattern shape is
440/// `<dir>/<filename-pattern>` where the filename pattern may contain `*`
441/// wildcards (e.g. `fuel-dispatch/kernel-contracts/cpu/*.fkc.md`); `**` is not
442/// supported (a single directory level, matching the per-provider layout).
443pub fn import_glob(pattern: &str, link: &dyn LinkRegistry) -> Result<ImportedProvider, FkcError> {
444    let mut paths = glob_files(pattern)?;
445    paths.sort(); // deterministic order
446
447    if paths.is_empty() {
448        return Err(FkcError::Io {
449            path: pattern.to_string(),
450            reason: "glob pattern matched no files".to_string(),
451        });
452    }
453
454    let mut merged: Option<ImportedProvider> = None;
455    for path in &paths {
456        let file_label = path.display().to_string();
457        let provider = import_bundle(path, link)?;
458        match merged.as_mut() {
459            None => merged = Some(provider),
460            Some(acc) => {
461                // Front-matter must agree across files (§9.2).
462                if provider.name != acc.name {
463                    return Err(FkcError::ProviderMismatch {
464                        field: "provider.name".to_string(),
465                        expected: acc.name.clone(),
466                        found: provider.name.clone(),
467                        file: file_label,
468                    });
469                }
470                if provider.backend != acc.backend {
471                    return Err(FkcError::ProviderMismatch {
472                        field: "provider.backend".to_string(),
473                        expected: format!("{:?}", acc.backend),
474                        found: format!("{:?}", provider.backend),
475                        file: file_label,
476                    });
477                }
478                // kernel_source is interned, so distinct tags compare by
479                // pointer-or-content; compare by content for the message.
480                if provider.kernel_source != acc.kernel_source {
481                    return Err(FkcError::ProviderMismatch {
482                        field: "provider.kernel_source".to_string(),
483                        expected: acc.kernel_source.to_string(),
484                        found: provider.kernel_source.to_string(),
485                        file: file_label,
486                    });
487                }
488                // `revision_base` is folded into `kernel_revision_hash`, which
489                // is the key the verification ledger is looked up by. A drift
490                // here would merge kernels whose revision hashes were computed
491                // against different roots while presenting as one provider —
492                // silently invalidating those lookups rather than failing.
493                // Compared as `Option` so "one file declares it, the other
494                // omits it" is caught too, not just two differing values.
495                if provider.revision_base != acc.revision_base {
496                    return Err(FkcError::ProviderMismatch {
497                        field: "provider.revision_base".to_string(),
498                        expected: format!("{:?}", acc.revision_base),
499                        found: format!("{:?}", provider.revision_base),
500                        file: file_label.clone(),
501                    });
502                }
503                // `link_registry` names the symbol table a file's entry points
504                // are declared to resolve against — but a glob binds every file
505                // it merges through the ONE registry the caller supplied. A
506                // drift here means at least one file's `entry_point`s were
507                // resolved against a table its author never named; they may
508                // still resolve, to a same-named symbol from a different
509                // provider. Same `Option` comparison as above, and for the same
510                // reason: declared-in-one-file-only is a drift too.
511                if provider.link_registry != acc.link_registry {
512                    return Err(FkcError::ProviderMismatch {
513                        field: "provider.link_registry".to_string(),
514                        expected: format!("{:?}", acc.link_registry),
515                        found: format!("{:?}", provider.link_registry),
516                        file: file_label.clone(),
517                    });
518                }
519                // Agreed — fold this file's kernels into the merged provider.
520                acc.primitives.extend(provider.primitives);
521                acc.fused.extend(provider.fused);
522                acc.warnings.extend(provider.warnings);
523            }
524        }
525    }
526
527    Ok(merged.expect("non-empty path list yields a provider"))
528}
529
530// ===========================================================================
531// Helpers
532// ===========================================================================
533
534/// Map a front-matter `backend` string to a [`BackendId`]. Mirrors
535/// `lower.rs`'s `lower_backend` (kept local to avoid widening that fn's
536/// visibility for one call site). `UnknownBackend` on a bad string.
537fn lower_backend_str(s: &str) -> Result<BackendId, FkcError> {
538    match s {
539        "Cpu" => Ok(BackendId::Cpu),
540        "Cuda" => Ok(BackendId::Cuda),
541        "Vulkan" => Ok(BackendId::Vulkan),
542        "Metal" => Ok(BackendId::Metal),
543        other => Err(FkcError::UnknownBackend {
544            section: "<front-matter provider>".to_string(),
545            backend: other.to_string(),
546        }),
547    }
548}
549
550/// Minimal `<dir>/<filename-pattern>` glob: list the directory and keep
551/// files whose name matches the pattern's last component (with `*`
552/// wildcards). No new dependency; no `**` support (single directory level).
553fn glob_files(pattern: &str) -> Result<Vec<std::path::PathBuf>, FkcError> {
554    // Split into directory + filename pattern on the last path separator.
555    let p = Path::new(pattern);
556    let file_pat = p
557        .file_name()
558        .map(|n| n.to_string_lossy().to_string())
559        .ok_or_else(|| FkcError::Io {
560            path: pattern.to_string(),
561            reason: "glob pattern has no filename component".to_string(),
562        })?;
563    let dir = p.parent().filter(|d| !d.as_os_str().is_empty());
564    let dir = dir.unwrap_or_else(|| Path::new("."));
565
566    let read = std::fs::read_dir(dir).map_err(|e| FkcError::Io {
567        path: dir.display().to_string(),
568        reason: e.to_string(),
569    })?;
570
571    let mut out = Vec::new();
572    for entry in read {
573        let entry = entry.map_err(|e| FkcError::Io {
574            path: dir.display().to_string(),
575            reason: e.to_string(),
576        })?;
577        let path = entry.path();
578        if !path.is_file() {
579            continue;
580        }
581        let name = entry.file_name().to_string_lossy().to_string();
582        if matches_glob(&file_pat, &name) {
583            out.push(path);
584        }
585    }
586    Ok(out)
587}
588
589/// Match a filename against a `*`-wildcard glob pattern (single path
590/// component; `*` matches any run of non-separator characters). A
591/// pattern with no `*` is an exact match.
592fn matches_glob(pattern: &str, name: &str) -> bool {
593    // Split the pattern on `*`; every literal segment must appear in
594    // order, with the first segment anchored at the start and the last at
595    // the end (unless the pattern starts/ends with `*`).
596    let parts: Vec<&str> = pattern.split('*').collect();
597    if parts.len() == 1 {
598        // No wildcard — exact match.
599        return pattern == name;
600    }
601    let mut pos = 0usize;
602    for (i, part) in parts.iter().enumerate() {
603        if part.is_empty() {
604            continue;
605        }
606        if i == 0 {
607            // First literal segment must anchor at the start.
608            if !name[pos..].starts_with(part) {
609                return false;
610            }
611            pos += part.len();
612        } else if i == parts.len() - 1 {
613            // Last literal segment must anchor at the end (and not overlap
614            // an already-consumed prefix).
615            let rest = &name[pos..];
616            return rest.len() >= part.len() && rest.ends_with(part);
617        } else {
618            // Middle segment: must occur somewhere at/after pos.
619            match name[pos..].find(part) {
620                Some(idx) => pos += idx + part.len(),
621                None => return false,
622            }
623        }
624    }
625    true
626}
627
628#[cfg(test)]
629mod tests {
630    use super::*;
631    use crate::fkc::caps_map::{ResolvedLayout, Tri};
632    use crate::fkc::cost_expr::CompiledCostExpr;
633    use crate::fkc::lower::ResolvedFused;
634    use crate::fused::{KernelRevisionHash, PrecisionGuarantee};
635    use crate::kernel::{KernelCaps, KernelDTypes, KernelRef};
636    use fuel_graph::registry::FusedOps;
637    use fuel_ir::DType;
638    use fuel_ir::dispatch::OpKind;
639    use smallvec::SmallVec;
640    use std::sync::{Arc, RwLock};
641
642    const ELEMENTWISE_BINARY: &str =
643        include_str!("../../kernel-contracts/cpu/elementwise-binary.fkc.md");
644
645    /// Every live CPU contract, read from disk.
646    ///
647    /// ⚠️ **This started as two hand-picked contracts, and that was the same
648    /// mistake one level up.** The tests below were rewritten to LOCATE a
649    /// downgraded entry rather than name one, because naming `add_f32` made
650    /// them fail once the precision program earned its claims — and then they
651    /// failed AGAIN when the program earned everything in the two contracts I
652    /// had picked to search. **A hand-picked search SET expires exactly like a
653    /// hand-picked fixture.** The population is now "all of them", which is
654    /// the only version that does not need re-picking as coverage grows.
655    #[allow(
656        dead_code,
657        reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
658    )]
659    fn all_cpu_contracts() -> Vec<(String, String)> {
660        let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("kernel-contracts/cpu");
661        let mut out = Vec::new();
662        for e in std::fs::read_dir(&dir).unwrap_or_else(|e| panic!("read {dir:?}: {e}")) {
663            let path = e.expect("dir entry").path();
664            if path.extension().and_then(|x| x.to_str()) != Some("md") {
665                continue;
666            }
667            let name = path
668                .file_name()
669                .and_then(|n| n.to_str())
670                .unwrap_or_default()
671                .to_string();
672            if let Ok(text) = std::fs::read_to_string(&path) {
673                out.push((name, text));
674            }
675        }
676        out.sort();
677        assert!(
678            out.len() >= 10,
679            "only {} CPU contracts found under {dir:?} — the search below would be over \
680             a subset, and a 'nothing is downgraded' result would then be about the \
681             wrong population",
682            out.len()
683        );
684        out
685    }
686
687    /// Find an imported primitive whose guarantee was downgraded, together
688    /// with the claims the gate reported unbacked.
689    #[allow(
690        dead_code,
691        reason = "GAP-236 (unpublished verify API): fkc::verify's modules are private, so nothing outside this crate can reach it. Does NOT retire itself -- the expiry lives in GAP-236 and in Unpopped's handback precondition guard, which fires on their side when the API is named."
692    )]
693    fn find_downgraded() -> Option<(String, Vec<String>)> {
694        for (_name, text) in all_cpu_contracts() {
695            let link = EntryPointLink::new();
696            let Ok(provider) = import_bundle_str(&text, &link) else {
697                continue;
698            };
699            for w in provider.warnings.iter() {
700                if !w.message.contains("downgraded to UNAUDITED") {
701                    continue;
702                }
703                let claims = match (w.message.find('['), w.message.find(']')) {
704                    (Some(a), Some(b)) if b > a => w.message[a + 1..b]
705                        .split(',')
706                        .map(|c| c.trim().trim_matches('"').to_string())
707                        .collect(),
708                    _ => continue,
709                };
710                return Some((w.message.clone(), claims));
711            }
712        }
713        None
714    }
715
716    // -- two distinct dummy kernels (distinct fn items ⇒ distinct ptrs) --
717
718    fn dummy_a(
719        _i: &[Arc<RwLock<fuel_memory::Storage>>],
720        _o: &mut [Arc<RwLock<fuel_memory::Storage>>],
721        _l: &[fuel_ir::Layout],
722        _p: &crate::kernel::OpParams,
723    ) -> fuel_ir::Result<()> {
724        Ok(())
725    }
726    fn dummy_b(
727        _i: &[Arc<RwLock<fuel_memory::Storage>>],
728        _o: &mut [Arc<RwLock<fuel_memory::Storage>>],
729        _l: &[fuel_ir::Layout],
730        _p: &crate::kernel::OpParams,
731    ) -> fuel_ir::Result<()> {
732        Ok(())
733    }
734
735    /// A LinkRegistry stub mapping each DISTINCT `entry_point` string to a
736    /// distinct dummy `KernelRef` — so importing a many-section contract
737    /// does not collapse every section onto one pointer (which would trip
738    /// the finalize gate spuriously). It hands out `dummy_a` / `dummy_b`
739    /// in alternation per unique symbol (enough distinct pointers for the
740    /// elementwise-binary corpus where every section has a unique key).
741    struct DistinctLink {
742        seen: Mutex<std::collections::HashMap<String, KernelRef>>,
743    }
744    impl DistinctLink {
745        fn new() -> Self {
746            Self {
747                seen: Mutex::new(std::collections::HashMap::new()),
748            }
749        }
750        fn resolve(&self, symbol: &str) -> Option<KernelRef> {
751            let mut g = self.seen.lock().unwrap();
752            if let Some(k) = g.get(symbol) {
753                return Some(*k);
754            }
755            // Alternate between two distinct fn items by current count
756            // parity. Each unique symbol gets a stable pointer; the keys
757            // in the elementwise-binary corpus are unique per section so
758            // two pointers suffice to avoid same-key collisions there.
759            let k: KernelRef = if g.len().is_multiple_of(2) {
760                dummy_a
761            } else {
762                dummy_b
763            };
764            g.insert(symbol.to_string(), k);
765            Some(k)
766        }
767    }
768    impl LinkRegistry for DistinctLink {
769        fn resolve_primitive(&self, symbol: &str) -> Option<KernelRef> {
770            self.resolve(symbol)
771        }
772        fn resolve_fused(&self, symbol: &str) -> Option<KernelRef> {
773            self.resolve(symbol)
774        }
775    }
776
777    /// A LinkRegistry stub that maps EVERY symbol to the SAME pointer —
778    /// used for the duplicate-detection test.
779    struct SameLink;
780    impl LinkRegistry for SameLink {
781        fn resolve_primitive(&self, _symbol: &str) -> Option<KernelRef> {
782            Some(dummy_a)
783        }
784        fn resolve_fused(&self, _symbol: &str) -> Option<KernelRef> {
785            Some(dummy_a)
786        }
787    }
788
789    // =====================================================================
790    // END-TO-END: a real contract file → live registration
791    // =====================================================================
792
793    #[test]
794    fn import_real_elementwise_binary_registers_add_f32_end_to_end() {
795        // Parse + lower the authored CPU elementwise-binary bundle, then
796        // register it into a FRESH binding table and assert the kernel is
797        // present + the table finalizes Ok.
798        let link = DistinctLink::new();
799        let provider = import_bundle_str(ELEMENTWISE_BINARY, &link)
800            .expect("authored elementwise-binary.fkc.md imports");
801
802        assert_eq!(provider.name, "fuel-cpu-backend");
803        assert_eq!(provider.backend, BackendId::Cpu);
804        assert_eq!(provider.kernel_source, "portable-cpu");
805        assert!(
806            !provider.primitives.is_empty(),
807            "elementwise-binary yields primitives"
808        );
809        assert!(provider.fused.is_empty(), "no fused ops in this bundle");
810
811        let mut table = KernelBindingTable::new();
812        let mut fused = FusedKernelRegistry::new();
813        provider
814            .register_into(&mut table, &mut fused)
815            .expect("register_into a fresh table succeeds");
816
817        // The add_f32 contract: (AddElementwise, [F32,F32,F32], Cpu).
818        let key_dtypes = [DType::F32, DType::F32, DType::F32];
819        let looked_up = table.lookup(OpKind::AddElementwise, &key_dtypes, BackendId::Cpu);
820        assert!(
821            looked_up.is_ok(),
822            "AddElementwise/[F32,F32,F32]/Cpu must be registered: {looked_up:?}"
823        );
824
825        // The table is internally consistent.
826        assert!(table.finalize().is_ok(), "finalize is Ok after import");
827        assert!(table.len() >= provider.primitives.len());
828    }
829
830    // =====================================================================
831    // VERTICAL SLICE: import through a REAL LinkRegistry → the real kernel
832    // =====================================================================
833
834    /// A REAL (non-stub) [`LinkRegistry`]: resolves the authored contract's
835    /// `add_f32` entry-point symbol to the ACTUAL production CPU kernel
836    /// wrapper (`dispatch::add_elementwise_f32_cpu_wrapper`). Every other
837    /// section's symbol gets a distinct dummy so the multi-section bundle
838    /// still imports without a spurious finalize collision. This is the first
839    /// non-stub LinkRegistry — it proves the FKC import path resolves a
840    /// contract symbol to a real, executable kernel, not a placeholder.
841    struct EntryPointLink {
842        seen: Mutex<std::collections::HashMap<String, KernelRef>>,
843    }
844    impl EntryPointLink {
845        fn new() -> Self {
846            Self {
847                seen: Mutex::new(std::collections::HashMap::new()),
848            }
849        }
850        fn resolve(&self, symbol: &str) -> Option<KernelRef> {
851            if symbol == "fuel_cpu_backend::byte_kernels::add_f32" {
852                // THE point of the slice: the real production kernel.
853                return Some(crate::dispatch::add_elementwise_f32_cpu_wrapper as KernelRef);
854            }
855            let mut g = self.seen.lock().unwrap();
856            if let Some(k) = g.get(symbol) {
857                return Some(*k);
858            }
859            let k: KernelRef = if g.len().is_multiple_of(2) {
860                dummy_a
861            } else {
862                dummy_b
863            };
864            g.insert(symbol.to_string(), k);
865            Some(k)
866        }
867    }
868    impl LinkRegistry for EntryPointLink {
869        fn resolve_primitive(&self, symbol: &str) -> Option<KernelRef> {
870            self.resolve(symbol)
871        }
872        fn resolve_fused(&self, symbol: &str) -> Option<KernelRef> {
873            self.resolve(symbol)
874        }
875    }
876
877    #[test]
878    fn import_add_f32_through_real_link_registry_binds_the_real_kernel() {
879        // The vertical slice: import the authored CPU elementwise-binary
880        // contract through a REAL LinkRegistry that resolves add_f32's
881        // entry-point symbol to the production kernel wrapper, register it,
882        // and prove the registered binding IS that real kernel — by pointer
883        // identity AND by executing it on real F32 storage.
884        let link = EntryPointLink::new();
885        let provider = import_bundle_str(ELEMENTWISE_BINARY, &link)
886            .expect("authored elementwise-binary.fkc.md imports through the real link");
887
888        let mut table = KernelBindingTable::new();
889        let mut fused = FusedKernelRegistry::new();
890        provider
891            .register_into(&mut table, &mut fused)
892            .expect("register_into a fresh table succeeds");
893
894        let key = [DType::F32, DType::F32, DType::F32];
895        // The contract registers TWO alternatives at this key: the shared
896        // `binary` chassis representative and the concrete `add_f32` — so
897        // `lookup` (first alternative) returns the chassis. We assert the real
898        // add_f32 wrapper is present *among the alternatives* and invoke it.
899        let expected: KernelRef = crate::dispatch::add_elementwise_f32_cpu_wrapper;
900        let alts = table.lookup_alternatives(OpKind::AddElementwise, &key, BackendId::Cpu);
901        assert!(
902            !alts.is_empty(),
903            "AddElementwise/[F32,F32,F32]/Cpu present after FKC import"
904        );
905
906        // (1) The FKC-imported binding IS the real production kernel — not a
907        // stub, not a different fn — proven by pointer identity.
908        let resolved: KernelRef = alts
909            .iter()
910            .map(|e| e.kernel)
911            .find(|k| *k as usize == expected as usize)
912            .expect("FKC import must bind the real add_f32 wrapper among the alternatives");
913
914        // (2) It actually runs end-to-end on real F32 storage: [1,2,3]+[4,5,6].
915        let a = Arc::new(RwLock::new(fuel_memory::from_slice_cpu(&[
916            1.0f32, 2.0, 3.0,
917        ])));
918        let b = Arc::new(RwLock::new(fuel_memory::from_slice_cpu(&[
919            4.0f32, 5.0, 6.0,
920        ])));
921        let out = Arc::new(RwLock::new(
922            fuel_memory::alloc_cpu_zeroed(DType::F32, 3).expect("alloc out"),
923        ));
924        let inputs = [a, b];
925        let mut outputs = [out];
926        let shape = fuel_ir::Shape::from_dims(&[3]);
927        let layouts = [
928            fuel_ir::Layout::contiguous(shape.clone()),
929            fuel_ir::Layout::contiguous(shape),
930        ];
931        resolved(
932            &inputs,
933            &mut outputs,
934            &layouts,
935            &crate::kernel::OpParams::None,
936        )
937        .expect("the FKC-resolved add_f32 kernel executes on real storage");
938    }
939
940    // =====================================================================
941    // V-FKC-9 IMPORT-TIME GATE: unverified precision claims are downgraded
942    // =====================================================================
943
944    /// The V-FKC-9 gate downgrades a declared guarantee whose claims are not
945    /// all backed, and the warning NAMES which ones.
946    ///
947    /// ⚠️ **This test has now expired twice on live data and is constructed
948    /// because of it.** It first named `add_f32` and failed when the precision
949    /// program earned that entry's claims. It was rewritten to LOCATE a
950    /// downgraded entry, and failed again when the two contracts it searched
951    /// became fully backed. It was widened to every CPU contract — and failed
952    /// a third time, because **there are now zero unbacked declared claims on
953    /// the whole CPU surface.**
954    ///
955    /// Each rewrite was a smaller version of the same mistake: sourcing a
956    /// NEGATIVE case from data that the work under test is actively removing.
957    /// A gate's "it fires" test cannot depend on something still being broken.
958    /// So the unbacked case is now BUILT: an empty ledger backs nothing, so
959    /// every declared claim is unbacked by construction, permanently.
960    #[test]
961    fn the_import_gate_downgrades_an_entry_whose_claims_are_not_all_backed() {
962        use crate::fkc::verify::{LedgerQuery, VerificationLedger, gate_precision};
963        use crate::fused::PrecisionGuarantee;
964
965        let declared = PrecisionGuarantee {
966            bit_stable_on_same_hardware: true,
967            max_ulp: Some(0),
968            ..PrecisionGuarantee::UNAUDITED
969        };
970        let dtypes = [DType::F32, DType::F32, DType::F32];
971        let q = LedgerQuery {
972            kernel_ref: "constructed",
973            backend: fuel_ir::probe::BackendId::Cpu,
974            dtypes: &dtypes,
975            kernel_revision_hash: 0xDEAD_BEEF,
976        };
977        let mut warnings = Vec::new();
978        let gated = gate_precision(declared, &q, &VerificationLedger::default(), &mut warnings);
979
980        assert!(
981            !gated.bit_stable_on_same_hardware && gated.max_ulp.is_none(),
982            "an entry whose claims are backed by NOTHING must be downgraded whole"
983        );
984        assert_eq!(
985            gated.notes,
986            PrecisionGuarantee::UNAUDITED.notes,
987            "the downgrade must land on the UNAUDITED sentinel, not a partial edit"
988        );
989        assert!(
990            warnings
991                .iter()
992                .any(|w| w.message.contains("bit_stable_on_same_hardware")
993                    && w.message.contains("max_ulp")),
994            "the warning must NAME both unbacked claims, or a census keyed on those \
995             names reads a subset: {warnings:?}"
996        );
997    }
998
999    /// **Earning one claim buys NOTHING while a sibling claim is unearned.**
1000    ///
1001    /// `gate_precision` collapses the WHOLE guarantee if ANY declared claim
1002    /// lacks a pass, so coverage of one claim does not convert into changed
1003    /// guarantees for dual-claim entries. That is invisible in a
1004    /// claim-coverage number and is exactly the inference a plan makes
1005    /// silently — converted into a test so it fails if someone makes it.
1006    ///
1007    /// Constructed for the same reason as the test above: a ledger holding
1008    /// exactly ONE of the two declared claims cannot be produced from live
1009    /// data any more, and depending on live data to still be broken is what
1010    /// expired the previous three versions.
1011    #[test]
1012    fn a_backed_claim_does_not_rescue_an_entry_whose_sibling_claim_is_unbacked() {
1013        // `LedgerRecord`'s re-export is feature-gated (`jit`/`cuda`), so reach
1014        // it by module path — this test is unconditional and must not become
1015        // one that only runs under a feature nobody's default build enables.
1016        use crate::fkc::verify::{LedgerQuery, LedgerRecord, VerificationLedger, gate_precision};
1017        use crate::fused::PrecisionGuarantee;
1018
1019        let dtypes = [DType::F32, DType::F32, DType::F32];
1020        let rev = 0xDEAD_BEEF_u64;
1021        // A ledger that backs bit-stability and NOTHING ELSE.
1022        let ledger = VerificationLedger::from_records(vec![LedgerRecord {
1023            kernel_ref: "constructed".to_string(),
1024            backend: "Cpu".to_string(),
1025            dtypes: dtypes.iter().map(|d| format!("{d:?}")).collect(),
1026            kernel_revision_hash: rev,
1027            claim: "bit_stable_on_same_hardware".to_string(),
1028            result: "pass".to_string(),
1029            verified_at: "epoch:0".to_string(),
1030            protocol_version: 1,
1031            evidence: serde_json::Value::Null,
1032        }]);
1033
1034        let q = LedgerQuery {
1035            kernel_ref: "constructed",
1036            backend: fuel_ir::probe::BackendId::Cpu,
1037            dtypes: &dtypes,
1038            kernel_revision_hash: rev,
1039        };
1040
1041        // Control: the ledger really does back the bit-stable claim, so a
1042        // failure below is about the SIBLING and not about a lookup miss.
1043        assert!(
1044            ledger.has_pass(q.backend, q.dtypes, rev, "bit_stable_on_same_hardware"),
1045            "precondition: the constructed ledger must back bit-stability"
1046        );
1047
1048        let declared = PrecisionGuarantee {
1049            bit_stable_on_same_hardware: true,
1050            max_ulp: Some(0),
1051            ..PrecisionGuarantee::UNAUDITED
1052        };
1053        let mut warnings = Vec::new();
1054        let gated = gate_precision(declared, &q, &ledger, &mut warnings);
1055
1056        assert!(
1057            !gated.bit_stable_on_same_hardware,
1058            "ONE backed claim must not rescue an entry whose sibling is unbacked — the \
1059             whole guarantee collapses"
1060        );
1061        let named: Vec<&str> = warnings.iter().map(|w| w.message.as_str()).collect();
1062        assert!(
1063            named.iter().any(|m| m.contains("max_ulp")),
1064            "the warning must cite the UNBACKED sibling: {named:?}"
1065        );
1066        assert!(
1067            !named
1068                .iter()
1069                .any(|m| m.contains("[\"bit_stable_on_same_hardware\"")),
1070            "the BACKED claim must not be reported unbacked — that would mean the gate \
1071             does not discriminate per claim: {named:?}"
1072        );
1073    }
1074
1075    #[test]
1076    fn cpu_link_registry_binds_elementwise_binary_to_live_kernels() {
1077        // The CPU backend is the first FKC conformance reference: import its
1078        // authored elementwise-binary contract through the PRODUCTION
1079        // CpuLinkRegistry (not a stub) and verify every (op, dtype) section
1080        // resolves to the real production wrapper — proving an imported
1081        // contract describes, and binds to, the live CPU kernels.
1082        let provider = import_bundle_str(ELEMENTWISE_BINARY, &crate::fkc::CpuLinkRegistry)
1083            .expect("elementwise-binary imports through the production CpuLinkRegistry");
1084        let mut table = KernelBindingTable::new();
1085        let mut fused = FusedKernelRegistry::new();
1086        provider
1087            .register_into(&mut table, &mut fused)
1088            .expect("register_into a fresh table succeeds");
1089
1090        // All 8 ops × 4 dtypes are bound from the contract.
1091        let ops = [
1092            OpKind::AddElementwise,
1093            OpKind::SubElementwise,
1094            OpKind::MulElementwise,
1095            OpKind::DivElementwise,
1096            OpKind::MaximumElementwise,
1097            OpKind::MinimumElementwise,
1098            OpKind::PowElementwise,
1099            OpKind::RemElementwise,
1100        ];
1101        let dts = [DType::F32, DType::F64, DType::F16, DType::BF16];
1102        for op in ops {
1103            for dt in dts {
1104                assert!(
1105                    table.lookup(op, &[dt, dt, dt], BackendId::Cpu).is_ok(),
1106                    "{op:?}/{dt:?} must be bound from the imported contract",
1107                );
1108            }
1109        }
1110
1111        // Spot-check two distinct (op, dtype) resolve to the EXACT production
1112        // wrappers — the link registry bound real symbols, not stubs.
1113        let add_f32 = table
1114            .lookup(OpKind::AddElementwise, &[DType::F32; 3], BackendId::Cpu)
1115            .unwrap();
1116        assert_eq!(
1117            add_f32 as usize,
1118            crate::dispatch::add_elementwise_f32_cpu_wrapper as *const () as usize,
1119        );
1120        let pow_bf16 = table
1121            .lookup(OpKind::PowElementwise, &[DType::BF16; 3], BackendId::Cpu)
1122            .unwrap();
1123        assert_eq!(
1124            pow_bf16 as usize,
1125            crate::dispatch::pow_elementwise_bf16_cpu_wrapper as *const () as usize,
1126        );
1127
1128        assert!(
1129            table.finalize().is_ok(),
1130            "finalize is Ok after a real-link import"
1131        );
1132    }
1133
1134    // =====================================================================
1135    // FUSED SEAM: the production CpuLinkRegistry resolves a REAL authored
1136    // `fused_op` bundle's entry_point symbols to the live CPU fused wrappers
1137    // (the fused analogue of the elementwise-binary live-kernel test above).
1138    // =====================================================================
1139
1140    /// The authored norm/softmax FUSED bundle — every section declares
1141    /// `fused_op:` (a `FusedOps::*` id), not `op_kind:`.
1142    const FUSED_NORM_SOFTMAX: &str =
1143        include_str!("../../kernel-contracts/fused/norm-softmax.fkc.md");
1144
1145    #[test]
1146    fn cpu_link_registry_binds_norm_softmax_fused_ops_to_live_kernels() {
1147        // BORN-RED → GREEN (fused dtype-fan, §3.4). Each `fused_op` section
1148        // enumerates `dtypes: [F32, F64, BF16, F16]` on a BASE `entry_point`, so
1149        // `lower_fused` now FANS it into 4 per-dtype impls, each resolving
1150        // `<base>_<dt>` through `CPU_FUSED_NORM_ENTRY_POINTS`. Before the table
1151        // grew to its 32 per-dtype rows, the fanned symbols (e.g.
1152        // `…::softmax_last_dim_cpu_f32`) resolved to `None` → `UnknownEntryPoint`
1153        // and this import errored (RED). With the 32-row table every fanned
1154        // symbol binds the ACTUAL per-dtype production wrapper (GREEN) — a 1:1
1155        // replacement for the hand-written `register_default_fused_kernels`
1156        // per-dtype registrations, not just the F32 representative.
1157        let provider = import_bundle_str(FUSED_NORM_SOFTMAX, &crate::fkc::CpuLinkRegistry).expect(
1158            "authored norm-softmax fused bundle imports through the production CpuLinkRegistry",
1159        );
1160        // A fused-only bundle: no primitive `op_kind` sections. The 8 sections
1161        // each fan over 4 dtypes ⇒ 32 fused impls.
1162        assert!(
1163            provider.primitives.is_empty(),
1164            "norm-softmax declares only fused ops",
1165        );
1166        assert_eq!(
1167            provider.fused.len(),
1168            32,
1169            "8 fused sections × 4 dtypes = 32 per-dtype impls (fused dtype-fan)",
1170        );
1171
1172        let mut table = KernelBindingTable::new();
1173        let mut fused = FusedKernelRegistry::new();
1174        provider
1175            .register_into(&mut table, &mut fused)
1176            .expect("register_into fresh registries succeeds");
1177
1178        let dts = [DType::F32, DType::F64, DType::BF16, DType::F16];
1179
1180        // Each FORWARD op (key `[dt, dt]`) binds all 4 dtypes to the EXACT
1181        // per-dtype production wrapper — proven by pointer identity — and carries
1182        // the contract's REAL revision hash (hand-written regs stamp UNTRACKED).
1183        let forward = [
1184            (
1185                FusedOps::SOFTMAX_LAST_DIM,
1186                [
1187                    crate::dispatch::softmax_last_dim_f32_cpu_wrapper as *const () as usize,
1188                    crate::dispatch::softmax_last_dim_f64_cpu_wrapper as *const () as usize,
1189                    crate::dispatch::softmax_last_dim_bf16_cpu_wrapper as *const () as usize,
1190                    crate::dispatch::softmax_last_dim_f16_cpu_wrapper as *const () as usize,
1191                ],
1192            ),
1193            (
1194                FusedOps::RMS_NORM_LAST_DIM,
1195                [
1196                    crate::dispatch::rms_norm_last_dim_f32_cpu_wrapper as *const () as usize,
1197                    crate::dispatch::rms_norm_last_dim_f64_cpu_wrapper as *const () as usize,
1198                    crate::dispatch::rms_norm_last_dim_bf16_cpu_wrapper as *const () as usize,
1199                    crate::dispatch::rms_norm_last_dim_f16_cpu_wrapper as *const () as usize,
1200                ],
1201            ),
1202            (
1203                FusedOps::LAYER_NORM_LAST_DIM,
1204                [
1205                    crate::dispatch::layer_norm_last_dim_f32_cpu_wrapper as *const () as usize,
1206                    crate::dispatch::layer_norm_last_dim_f64_cpu_wrapper as *const () as usize,
1207                    crate::dispatch::layer_norm_last_dim_bf16_cpu_wrapper as *const () as usize,
1208                    crate::dispatch::layer_norm_last_dim_f16_cpu_wrapper as *const () as usize,
1209                ],
1210            ),
1211        ];
1212        for (id, wrappers) in forward {
1213            for (dt, expected) in dts.iter().zip(wrappers) {
1214                let got = fused
1215                    .lookup_by_dtypes(id, BackendId::Cpu, &[*dt, *dt])
1216                    .unwrap_or_else(|| panic!("{id:?} {dt:?} fused impl bound from the contract"));
1217                assert_eq!(
1218                    got.kernel as usize, expected,
1219                    "{id:?} {dt:?} binds its exact per-dtype production wrapper",
1220                );
1221                assert_ne!(
1222                    got.revision,
1223                    KernelRevisionHash::UNTRACKED,
1224                    "FKC import stamps the contract's real revision (hand-written stamps UNTRACKED)",
1225                );
1226            }
1227        }
1228
1229        // Each BACKWARD op (key `[dt, dt, dt]`) binds all 4 dtypes to the EXACT
1230        // per-dtype production wrapper.
1231        let backward = [
1232            (
1233                FusedOps::SOFTMAX_LAST_DIM_BACKWARD,
1234                [
1235                    crate::dispatch::softmax_last_dim_backward_f32_cpu_wrapper as *const ()
1236                        as usize,
1237                    crate::dispatch::softmax_last_dim_backward_f64_cpu_wrapper as *const ()
1238                        as usize,
1239                    crate::dispatch::softmax_last_dim_backward_bf16_cpu_wrapper as *const ()
1240                        as usize,
1241                    crate::dispatch::softmax_last_dim_backward_f16_cpu_wrapper as *const ()
1242                        as usize,
1243                ],
1244            ),
1245            (
1246                FusedOps::LAYER_NORM_LAST_DIM_BACKWARD,
1247                [
1248                    crate::dispatch::layer_norm_last_dim_backward_f32_cpu_wrapper as *const ()
1249                        as usize,
1250                    crate::dispatch::layer_norm_last_dim_backward_f64_cpu_wrapper as *const ()
1251                        as usize,
1252                    crate::dispatch::layer_norm_last_dim_backward_bf16_cpu_wrapper as *const ()
1253                        as usize,
1254                    crate::dispatch::layer_norm_last_dim_backward_f16_cpu_wrapper as *const ()
1255                        as usize,
1256                ],
1257            ),
1258            (
1259                FusedOps::RMS_NORM_LAST_DIM_BACKWARD,
1260                [
1261                    crate::dispatch::rms_norm_last_dim_backward_f32_cpu_wrapper as *const ()
1262                        as usize,
1263                    crate::dispatch::rms_norm_last_dim_backward_f64_cpu_wrapper as *const ()
1264                        as usize,
1265                    crate::dispatch::rms_norm_last_dim_backward_bf16_cpu_wrapper as *const ()
1266                        as usize,
1267                    crate::dispatch::rms_norm_last_dim_backward_f16_cpu_wrapper as *const ()
1268                        as usize,
1269                ],
1270            ),
1271            (
1272                FusedOps::REDUCE_MAX_TO_BACKWARD,
1273                [
1274                    crate::dispatch::reduce_max_to_backward_f32_cpu_wrapper as *const () as usize,
1275                    crate::dispatch::reduce_max_to_backward_f64_cpu_wrapper as *const () as usize,
1276                    crate::dispatch::reduce_max_to_backward_bf16_cpu_wrapper as *const () as usize,
1277                    crate::dispatch::reduce_max_to_backward_f16_cpu_wrapper as *const () as usize,
1278                ],
1279            ),
1280            (
1281                FusedOps::POWI_BACKWARD,
1282                [
1283                    crate::dispatch::powi_backward_f32_cpu_wrapper as *const () as usize,
1284                    crate::dispatch::powi_backward_f64_cpu_wrapper as *const () as usize,
1285                    crate::dispatch::powi_backward_bf16_cpu_wrapper as *const () as usize,
1286                    crate::dispatch::powi_backward_f16_cpu_wrapper as *const () as usize,
1287                ],
1288            ),
1289        ];
1290        for (id, wrappers) in backward {
1291            for (dt, expected) in dts.iter().zip(wrappers) {
1292                let got = fused
1293                    .lookup_by_dtypes(id, BackendId::Cpu, &[*dt, *dt, *dt])
1294                    .unwrap_or_else(|| panic!("{id:?} {dt:?} fused impl bound from the contract"));
1295                assert_eq!(
1296                    got.kernel as usize, expected,
1297                    "{id:?} {dt:?} binds its exact per-dtype production wrapper",
1298                );
1299            }
1300        }
1301    }
1302
1303    // =====================================================================
1304    // §5 RETURN-CONTRACT CROSS-CHECK: a fused contract's declared shape_rule /
1305    // dtype_rule must agree with the REAL registered `FusedOpEntry` fn — the
1306    // born-red test for Task 3.3 (Finding 5.1).
1307    // =====================================================================
1308
1309    #[test]
1310    fn fused_contract_shape_rule_disagreeing_with_registered_fn_is_rejected() {
1311        // Real SoftmaxLastDim dtype_rule is passthrough(input0) = F32 at the F32 probe.
1312        // Mutate ONLY the first section's declared dtype_rule to fixed(F16): now it
1313        // disagrees with the registered fused fn at every probe combo → hard reject.
1314        let mutated =
1315            FUSED_NORM_SOFTMAX.replacen("dtype_rule: passthrough(x)", "dtype_rule: fixed(F16)", 1);
1316        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1317            "a return rule that disagrees with the registered fused fn must be rejected",
1318        );
1319        assert!(
1320            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1321            "expected ShapeRuleMismatch, got {err:?}"
1322        );
1323    }
1324
1325    #[test]
1326    fn unmutated_fused_corpus_still_imports_after_return_check() {
1327        import_bundle_str(FUSED_NORM_SOFTMAX, &crate::fkc::CpuLinkRegistry)
1328            .expect("real corpus return rules agree with the registered fused fns");
1329    }
1330
1331    // =====================================================================
1332    // Convergence-C C-3: the shape-oracle cross-check ACTIVATED across the
1333    // remaining expressible fused ops. Each op below is proven to FIRE (not
1334    // merely import clean) by a MUTATION that makes the DECLARED shape rule
1335    // disagree with the REAL registered FusedOpEntry fn — a skipped/dormant
1336    // cross-check would let the mutated import succeed (the false-green risk).
1337    // The unmutated companions prove the real contracts AGREE.
1338    //
1339    // NOTE (adversarial fix, review Finding 2): the `const(N)` mutations below
1340    // change the output RANK, so they only ever proved RANK discrimination. The
1341    // GQA probe is now shape-DISTINCT (Hq = 2*Hkv), so a same-rank OPERAND-ROLE
1342    // drift is caught too — see `flash_attn_backward_k_operand_role_swap_is_rejected`
1343    // (dK `same_as(k)` mis-declared as `same_as(q)`), which used to import clean.
1344    // =====================================================================
1345
1346    /// Finding 1 (arity pre-check): a synthetic 3-input FLASH_ATTN contract
1347    /// (q/k/v, no alibi) — the shape of the metal `matmul-attn.fkc.md`
1348    /// `sdpa_vector` sections. Its declared FLASH_ATTN registry fn
1349    /// `debug_assert!`s 4-or-5 inputs, so a 3-input probe panics in DEBUG (caught
1350    /// + skipped) but is stripped in RELEASE (fn reads operand 0) — the
1351    ///
1352    /// debug-vs-release split. The arity pre-check must skip it CONSISTENTLY in
1353    /// both build modes with a warning (not a silent debug-only skip).
1354    const SYNTH_FLASH_ATTN_3IN: &str = r#"---
1355fkc_version: 1
1356provider:
1357  name: synth-attn-3input
1358  backend: Cpu
1359  kernel_source: "portable-cpu"
1360---
1361
1362# synthetic 3-input FLASH_ATTN (Finding 1 arity pre-check)
1363
1364## flash_attn_3in
1365
1366Synthetic 3-input flash attention (q, k, v) to exercise the arity pre-check.
1367
1368```fkc
1369kernel: flash_attn_3in
1370fused_op: FLASH_ATTN
1371blurb: "synthetic 3-input flash attn (q,k,v) to exercise the arity pre-check"
1372backend: Cpu
1373kernel_source: "portable-cpu"
1374entry_point: "synthetic::flash_attn_3in_cpu"
1375kernel_revision_hash: auto
1376
1377accept:
1378  inputs:
1379    - name: q
1380      dtypes: [F32]
1381      layout: { contiguous: required, strided: rejected, broadcast_stride0: rejected, start_offset: rejected, reverse_strides: rejected }
1382      rank: 4
1383    - name: k
1384      dtypes: [F32]
1385      layout: { contiguous: required, strided: rejected, broadcast_stride0: rejected, start_offset: rejected, reverse_strides: rejected }
1386      rank: 4
1387    - name: v
1388      dtypes: [F32]
1389      layout: { contiguous: required, strided: rejected, broadcast_stride0: rejected, start_offset: rejected, reverse_strides: rejected }
1390      rank: 4
1391  op_params:
1392    variant: FlashAttn
1393    fields:
1394      softmax_scale:     { kind: f32 }
1395      causal:            { kind: bool }
1396      window_size_left:  { kind: "Option<usize>" }
1397      window_size_right: { kind: "Option<usize>" }
1398      softcap:           { kind: "Option<f32>" }
1399      k_len:             { kind: DynScalar }
1400
1401return:
1402  outputs:
1403    - name: out
1404      dtype_rule: passthrough(q)
1405      shape_rule: same_as(q)
1406      layout_guarantee: contiguous
1407      aliasing: none
1408
1409caps:
1410  awkward_layout_strategy: requires_contiguous
1411  in_place: false
1412
1413cost:
1414  provenance: judge_measured
1415  class: attention
1416
1417precision:
1418  bit_stable_on_same_hardware: false
1419  max_ulp: ~
1420  max_relative: ~
1421  max_absolute: ~
1422  audited: false
1423  notes: "synthetic"
1424
1425determinism: same_hardware_bitwise
1426```
1427"#;
1428
1429    /// The three fused-op bundles whose cross-checks C-3 turns on.
1430    const FUSED_ATTENTION: &str = include_str!("../../kernel-contracts/fused/attention.fkc.md");
1431    const FUSED_LINEAR_QUANT: &str =
1432        include_str!("../../kernel-contracts/fused/linear-quant.fkc.md");
1433    const FUSED_CONV_ROPE: &str = include_str!("../../kernel-contracts/fused/conv-rope.fkc.md");
1434
1435    /// Replace `from` → `to` exactly once, asserting `from` occurs EXACTLY once
1436    /// in `src` — so a mutation test can never silently no-op (a 0-count replace
1437    /// would leave the bundle unmutated and hide a cross-check that never fired).
1438    /// GAP-175: the anchor is located **whitespace-tolerantly** (see
1439    /// [`find_ws_tolerant`]) so a `.fkc.md` reflow cannot break these tests.
1440    /// **The EXACTLY-ONCE guard is unchanged, deliberately** — loosening the
1441    /// ANCHOR and loosening the COUNT are different changes and only the first
1442    /// is wanted. A 0- or 2-count must still fail loudly.
1443    fn mutate_once(src: &str, from: &str, to: &str) -> String {
1444        let spans = find_ws_tolerant(src, from);
1445        assert_eq!(
1446            spans.len(),
1447            1,
1448            "mutation anchor `{from}` must occur EXACTLY once (got {}). \
1449             NOTE (GAP-175): anchors are matched WHITESPACE-TOLERANTLY — a run \
1450             of spaces matches one-or-more — so a count of 0 is NOT a column \
1451             alignment problem in the .fkc.md. Look for a changed token, a \
1452             reworded comment, or a removed contract section instead.",
1453            spans.len()
1454        );
1455        let (start, end) = spans[0];
1456        format!("{}{}{}", &src[..start], to, &src[end..])
1457    }
1458
1459    /// Locate `needle` in `hay` treating **each run of spaces in `needle` as
1460    /// "one or more spaces"**; every other character matches exactly. Returns
1461    /// non-overlapping match spans as byte ranges.
1462    ///
1463    /// GAP-175: the mutation anchors below quote lines out of `.fkc.md` contract
1464    /// files whose columns are PADDED for readability, e.g.
1465    /// `same_as(q)<17 spaces># FusedOp.shape_rule = q shape`. Under exact
1466    /// matching that padding is load-bearing — realign a table, run a formatter,
1467    /// reflow a comment, and the anchor silently stops matching, reporting a
1468    /// MISSING ANCHOR and sending the reader after a contract-parsing bug that
1469    /// does not exist. Matching space runs elastically makes these tests depend
1470    /// on the contract's CONTENT rather than its FORMATTING, which was always
1471    /// the intent.
1472    ///
1473    /// Deliberately hand-rolled: `fuel-dispatch` has no `regex` dependency (nor
1474    /// a dev-dependency on one), and a test helper does not justify adding one.
1475    fn find_ws_tolerant(hay: &str, needle: &str) -> Vec<(usize, usize)> {
1476        let h: Vec<(usize, char)> = hay.char_indices().collect();
1477        let n: Vec<char> = needle.chars().collect();
1478        let mut out = Vec::new();
1479        if n.is_empty() {
1480            return out;
1481        }
1482        let mut i = 0usize;
1483        while i < h.len() {
1484            let mut hi = i;
1485            let mut ni = 0usize;
1486            let matched = loop {
1487                if ni == n.len() {
1488                    break true;
1489                }
1490                if n[ni] == ' ' {
1491                    // A run of spaces in the needle consumes 1+ spaces in the hay.
1492                    let mut seen = 0usize;
1493                    while hi < h.len() && h[hi].1 == ' ' {
1494                        hi += 1;
1495                        seen += 1;
1496                    }
1497                    if seen == 0 {
1498                        break false;
1499                    }
1500                    while ni < n.len() && n[ni] == ' ' {
1501                        ni += 1;
1502                    }
1503                } else {
1504                    if hi >= h.len() || h[hi].1 != n[ni] {
1505                        break false;
1506                    }
1507                    hi += 1;
1508                    ni += 1;
1509                }
1510            };
1511            if matched {
1512                let start = h[i].0;
1513                let end = if hi < h.len() { h[hi].0 } else { hay.len() };
1514                out.push((start, end));
1515                i = hi.max(i + 1); // non-overlapping
1516            } else {
1517                i += 1;
1518            }
1519        }
1520        out
1521    }
1522
1523    /// **GAP-175 born-red witness: a `.fkc.md` reflow must not break a mutation
1524    /// anchor.** The exact-match form finds the anchor in the aligned text and
1525    /// NOT in the reflowed text — that is the defect, demonstrated rather than
1526    /// asserted. The whitespace-tolerant form finds it in both.
1527    #[test]
1528    fn mutation_anchor_survives_a_contract_reflow() {
1529        let aligned = "  - { name: dq, dtype_rule: passthrough(q), \
1530                       shape_rule: same_as(q)                 # FusedOp.shape_rule_q\n";
1531        // The SAME content with the column padding collapsed — an innocuous
1532        // reflow, the event this row is about.
1533        let reflowed = "  - { name: dq, dtype_rule: passthrough(q), \
1534                        shape_rule: same_as(q)   # FusedOp.shape_rule_q\n";
1535        let anchor = "shape_rule: same_as(q)                 # FusedOp.shape_rule_q";
1536
1537        // The old behaviour, kept as the CONTRAST that makes this test mean
1538        // something: exact matching is what breaks.
1539        assert_eq!(
1540            aligned.matches(anchor).count(),
1541            1,
1542            "exact match works on the aligned text"
1543        );
1544        assert_eq!(
1545            reflowed.matches(anchor).count(),
1546            0,
1547            "exact match FAILS after a reflow — this is the defect GAP-175 names"
1548        );
1549
1550        // The fix: content-dependent, not formatting-dependent.
1551        assert_eq!(find_ws_tolerant(aligned, anchor).len(), 1);
1552        assert_eq!(
1553            find_ws_tolerant(reflowed, anchor).len(),
1554            1,
1555            "GAP-175: a column reflow must NOT break the anchor"
1556        );
1557        let out = mutate_once(
1558            reflowed,
1559            anchor,
1560            "shape_rule: const(9) # FusedOp.shape_rule_q",
1561        );
1562        assert!(
1563            out.contains("const(9)"),
1564            "the mutation applies to the reflowed text"
1565        );
1566        assert!(!out.contains("same_as(q)"), "and the original rule is gone");
1567    }
1568
1569    /// GAP-175: loosening the ANCHOR must not loosen the COUNT guard. A 0-count
1570    /// is the case that would silently no-op and hide a cross-check that never
1571    /// fired, so it must still panic.
1572    #[test]
1573    #[should_panic(expected = "must occur EXACTLY once")]
1574    fn mutate_once_still_rejects_a_zero_count() {
1575        mutate_once("shape_rule: same_as(q)\n", "shape_rule: same_as(NOPE)", "x");
1576    }
1577
1578    /// GAP-175: and a 2-count must still panic — whitespace tolerance widens
1579    /// what matches, so the ambiguity guard matters MORE, not less.
1580    #[test]
1581    #[should_panic(expected = "must occur EXACTLY once")]
1582    fn mutate_once_still_rejects_a_multiple_count() {
1583        mutate_once("a  b\nand again a b\n", "a b", "x");
1584    }
1585
1586    /// A link registry that resolves EVERY symbol to a no-op kernel. The
1587    /// graph-side fused `attention.fkc.md` is a spec contract for the registry's
1588    /// `FusedOpEntry` (`shape_rule`/`dtype_rule`) and is NOT bound on the CPU
1589    /// `CpuLinkRegistry` (its CPU kernels come from the PRIMITIVE
1590    /// `cpu/attention.fkc.md`), so its `flash_attn_cpu_*` entry points do not
1591    /// resolve there. The cross-check runs BEFORE entry resolution and uses the
1592    /// REAL `default_registry()` fns regardless of link, so a resolve-anything
1593    /// stub isolates the cross-check under test from the (irrelevant here) CPU
1594    /// binding step.
1595    struct StubResolveAll;
1596    fn stub_kernel(
1597        _inputs: &[std::sync::Arc<std::sync::RwLock<fuel_memory::Storage>>],
1598        _outputs: &mut [std::sync::Arc<std::sync::RwLock<fuel_memory::Storage>>],
1599        _layouts: &[fuel_ir::Layout],
1600        _params: &crate::kernel::OpParams,
1601    ) -> fuel_ir::Result<()> {
1602        Ok(())
1603    }
1604    impl crate::fkc::lower::LinkRegistry for StubResolveAll {
1605        fn resolve_primitive(&self, _symbol: &str) -> Option<crate::kernel::KernelRef> {
1606            Some(stub_kernel)
1607        }
1608        fn resolve_fused(&self, _symbol: &str) -> Option<crate::kernel::KernelRef> {
1609            Some(stub_kernel)
1610        }
1611    }
1612
1613    // ---- Tier 1: same_as / bundle cross-checks (synth-gated) ----
1614
1615    #[test]
1616    fn inplace_affine_cross_check_fires() {
1617        // InplaceAffine now synth-supported; its `same_as(x)` (= input 0) is
1618        // evaluable. Mutating it to a rank-1 `const(9)` disagrees with the real
1619        // registry fn (which returns x's shape) at every probe → hard reject.
1620        let mutated = mutate_once(
1621            FUSED_LINEAR_QUANT,
1622            "shape_rule: same_as(x)",
1623            "shape_rule: const(9)",
1624        );
1625        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1626            "a mutated InplaceAffine shape_rule must be rejected (proves the check FIRES)",
1627        );
1628        assert!(
1629            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1630            "expected ShapeRuleMismatch, got {err:?}"
1631        );
1632    }
1633
1634    #[test]
1635    fn fused_linear_matmul_cross_check_fires() {
1636        // fused_linear declares the whole-shape `matmul(a, b)` rule (Tier-3),
1637        // now evaluable. The registry fn is `matmul_output_shape` (= a_batch ++
1638        // [M, N]); the UNMUTATED contract agrees (proven below). Mutate the rule
1639        // to `same_as(bias)` (rank-1 [N]) — disagrees with the rank-2 [M, N]
1640        // matmul output at every probe → hard reject (proves the check FIRES).
1641        let mutated = mutate_once(
1642            FUSED_LINEAR_QUANT,
1643            "shape_rule: matmul(a, b)",
1644            "shape_rule: same_as(bias)",
1645        );
1646        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1647            "a mutated fused_linear shape_rule must be rejected (proves the matmul check FIRES)",
1648        );
1649        assert!(
1650            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1651            "expected ShapeRuleMismatch, got {err:?}"
1652        );
1653    }
1654
1655    #[test]
1656    fn flash_attn_cross_check_fires() {
1657        // FlashAttn out = same_as(q) (Tier-2 doc fix from from_params(q)); the
1658        // registry fn returns input 0 (q). Mutate ONLY the value to a rank-1
1659        // const, preserving the `#` comment (the `q shape` tail is unique to
1660        // FlashAttn vs PagedAttn's `q (decode)` and dQ's `shape_rule_q`).
1661        let anchor = "same_as(q)                 # FusedOp.shape_rule = q shape";
1662        let mutated = mutate_once(
1663            FUSED_ATTENTION,
1664            anchor,
1665            "const(9) # FusedOp.shape_rule = q shape",
1666        );
1667        let err = import_bundle_str(&mutated, &StubResolveAll)
1668            .expect_err("a mutated FlashAttn shape_rule must be rejected (proves the check FIRES)");
1669        assert!(
1670            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1671            "expected ShapeRuleMismatch, got {err:?}"
1672        );
1673    }
1674
1675    #[test]
1676    fn paged_attn_cross_check_fires() {
1677        // PagedAttn out = same_as(q) (Tier-2 doc fix from from_params(q)); the
1678        // registry fn returns input 0 (q). Mutate ONLY the value, preserving the
1679        // `#` comment (`q (decode)` is unique to PagedAttn).
1680        let anchor = "same_as(q)                 # FusedOp.shape_rule = q (decode)";
1681        let mutated = mutate_once(
1682            FUSED_ATTENTION,
1683            anchor,
1684            "const(9) # FusedOp.shape_rule = q (decode)",
1685        );
1686        let err = import_bundle_str(&mutated, &StubResolveAll)
1687            .expect_err("a mutated PagedAttn shape_rule must be rejected (proves the check FIRES)");
1688        assert!(
1689            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1690            "expected ShapeRuleMismatch, got {err:?}"
1691        );
1692    }
1693
1694    #[test]
1695    fn flash_attn_backward_q_cross_check_fires() {
1696        // dQ = same_as(q) (= input 0). FLASH_ATTN_BACKWARD_{Q,K,V} share the
1697        // FlashAttnBackward variant, now synth-supported. Mutate dQ's rule.
1698        // (Stub link: attention is a graph-side spec contract, not CPU-bound.)
1699        let mutated = mutate_once(
1700            FUSED_ATTENTION,
1701            "shape_rule: same_as(q)                 # FusedOp.shape_rule_q",
1702            "shape_rule: const(9)                   # FusedOp.shape_rule_q",
1703        );
1704        let err = import_bundle_str(&mutated, &StubResolveAll)
1705            .expect_err("a mutated FlashAttnBackwardQ shape_rule must be rejected");
1706        assert!(
1707            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1708            "expected ShapeRuleMismatch, got {err:?}"
1709        );
1710    }
1711
1712    #[test]
1713    fn flash_attn_backward_k_cross_check_fires() {
1714        // dK = same_as(k) (= input 1); `same_as(k)` (parenthesised) is unique.
1715        let mutated = mutate_once(
1716            FUSED_ATTENTION,
1717            "shape_rule: same_as(k)",
1718            "shape_rule: const(9)",
1719        );
1720        let err = import_bundle_str(&mutated, &StubResolveAll)
1721            .expect_err("a mutated FlashAttnBackwardK shape_rule must be rejected");
1722        assert!(
1723            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1724            "expected ShapeRuleMismatch, got {err:?}"
1725        );
1726    }
1727
1728    #[test]
1729    fn flash_attn_backward_v_cross_check_fires() {
1730        // dV = same_as(v) (= input 2); `same_as(v)` (parenthesised) is unique.
1731        let mutated = mutate_once(
1732            FUSED_ATTENTION,
1733            "shape_rule: same_as(v)",
1734            "shape_rule: const(9)",
1735        );
1736        let err = import_bundle_str(&mutated, &StubResolveAll)
1737            .expect_err("a mutated FlashAttnBackwardV shape_rule must be rejected");
1738        assert!(
1739            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1740            "expected ShapeRuleMismatch, got {err:?}"
1741        );
1742    }
1743
1744    #[test]
1745    fn selective_scan_bundle_cross_check_fires() {
1746        // SelectiveScan now synth-supported ⇒ the bundle arity check runs.
1747        // Add a phantom 3rd slot: declared 3 ≠ real output_views arity 2.
1748        let ys = "- { name: y,          dtype_rule: passthrough(u), shape_rule: same_as(u),               layout_guarantee: contiguous }";
1749        let mutated = mutate_once(
1750            FUSED_CONV_ROPE,
1751            ys,
1752            &format!(
1753                "{ys}\n    - {{ name: phantom, dtype_rule: passthrough(u), shape_rule: same_as(u), layout_guarantee: contiguous }}"
1754            ),
1755        );
1756        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry)
1757            .expect_err("a SelectiveScan bundle with a phantom slot must be rejected");
1758        assert!(
1759            matches!(err, FkcError::BundleArityMismatch { .. }),
1760            "expected BundleArityMismatch, got {err:?}"
1761        );
1762    }
1763
1764    #[test]
1765    fn ssd_chunk_scan_bundle_cross_check_fires() {
1766        // SsdChunkScan now synth-supported ⇒ the bundle arity check runs.
1767        let ys = "- { name: y,          dtype_rule: passthrough(x), shape_rule: same_as(x),               layout_guarantee: contiguous }";
1768        let mutated = mutate_once(
1769            FUSED_CONV_ROPE,
1770            ys,
1771            &format!(
1772                "{ys}\n    - {{ name: phantom, dtype_rule: passthrough(x), shape_rule: same_as(x), layout_guarantee: contiguous }}"
1773            ),
1774        );
1775        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry)
1776            .expect_err("an SsdChunkScan bundle with a phantom slot must be rejected");
1777        assert!(
1778            matches!(err, FkcError::BundleArityMismatch { .. }),
1779            "expected BundleArityMismatch, got {err:?}"
1780        );
1781    }
1782
1783    #[test]
1784    fn unmutated_c3_bundles_still_import_after_activation() {
1785        // The real contracts AGREE with the registered fns across every probe.
1786        // linear-quant + conv-rope are CPU-bound (production import path).
1787        import_bundle_str(FUSED_LINEAR_QUANT, &crate::fkc::CpuLinkRegistry)
1788            .expect("linear-quant bundle return rules agree with the registered fused fns");
1789        import_bundle_str(FUSED_CONV_ROPE, &crate::fkc::CpuLinkRegistry)
1790            .expect("conv-rope bundle return rules agree with the registered fused fns");
1791        // attention is a graph-side spec contract (not CPU-bound); the cross-check
1792        // still validates its declared rules against the registry fns.
1793        import_bundle_str(FUSED_ATTENTION, &StubResolveAll)
1794            .expect("attention bundle return rules agree with the registered fused fns");
1795    }
1796
1797    // =====================================================================
1798    // Convergence-C C-3 adversarial fix — FINDING 1 (guard_rule warn +
1799    // arity pre-check closes the debug-vs-release split).
1800    // =====================================================================
1801
1802    #[test]
1803    fn under_arity_flash_attn_skips_differential_consistently_and_warns() {
1804        // A 3-input FLASH_ATTN contract (the metal `matmul-attn` `sdpa_vector`
1805        // shape) feeds a 3-input probe to the registry flash_attn fn whose
1806        // `debug_assert!(len == 4 || 5)` PANICS in a debug build but is stripped
1807        // in release. The arity pre-check must skip the differential CONSISTENTLY
1808        // across build modes and record a warning (no silent, debug-only skip).
1809        // Import succeeds (never-panic) and the warning fires.
1810        let provider = import_bundle_str(SYNTH_FLASH_ATTN_3IN, &StubResolveAll)
1811            .expect("a 3-input FLASH_ATTN contract imports (no panic, no debug-only silent skip)");
1812        assert!(
1813            provider
1814                .warnings
1815                .iter()
1816                .any(|w| w.message.contains("requires >= 4") && w.message.contains("skipped")),
1817            "the under-arity attention differential must be skipped WITH a warning \
1818             (consistent debug/release): {:?}",
1819            provider.warnings,
1820        );
1821    }
1822
1823    // =====================================================================
1824    // Convergence-C C-3 adversarial fix — FINDING 2 (GQA probe now
1825    // shape-DISTINCT: an operand-role swap in a return rule is caught).
1826    // =====================================================================
1827
1828    #[test]
1829    fn flash_attn_backward_k_operand_role_swap_is_rejected() {
1830        // With the GQA probe now shape-DISTINCT (Hq = 2*Hkv via the cross-operand
1831        // `divisible(q.dim[1], k.dim[1])`), a realistic operand-role drift — dK's
1832        // `shape_rule: same_as(k)` mis-authored as `same_as(q)` — is genuinely
1833        // caught: the declared q shape [.,2*Hkv,.,.] differs from the registry dK
1834        // oracle (input 1 = k) [.,Hkv,.,.]. Before the fix q/k seeded identically
1835        // and this swap imported clean (the const(9) mutation only proved RANK
1836        // discrimination). Proves operand-role drift is now caught, not just rank.
1837        let mutated = mutate_once(
1838            FUSED_ATTENTION,
1839            "shape_rule: same_as(k)",
1840            "shape_rule: same_as(q)",
1841        );
1842        let err = import_bundle_str(&mutated, &StubResolveAll).expect_err(
1843            "dK same_as(k) mis-declared as same_as(q) must be rejected (operand-role drift)",
1844        );
1845        assert!(
1846            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1847            "expected ShapeRuleMismatch, got {err:?}"
1848        );
1849    }
1850
1851    // =====================================================================
1852    // Convergence-C C-3 adversarial fix — FINDING 3 (bundle slot shapes are
1853    // now differentially compared to the output_views oracle).
1854    // =====================================================================
1855
1856    #[test]
1857    fn selective_scan_bundle_slot_content_drift_is_rejected() {
1858        // A SAME-RANK content drift in a bundle slot — SelectiveScan slot 0
1859        // declared `same_as(b)` instead of `same_as(u)` (both rank 3) — was
1860        // previously uncaught: the bundle block only checked arity + rank (<= 6),
1861        // never comparing an evaluated slot shape to the output_views oracle.
1862        // Over the now role-DISTINCT bundle probe (u [2,2,2] vs bumped b [5,2,2])
1863        // the drift diverges from the oracle (u-derived [2,2,2]) and is rejected.
1864        // Stays within §4 (reference = output_views, not decompose).
1865        let mutated = mutate_once(
1866            FUSED_CONV_ROPE,
1867            "shape_rule: same_as(u)",
1868            "shape_rule: same_as(b)",
1869        );
1870        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1871            "a same-rank bundle slot content drift (same_as(u) -> same_as(b)) must be rejected",
1872        );
1873        assert!(
1874            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1875            "expected ShapeRuleMismatch, got {err:?}"
1876        );
1877    }
1878
1879    // =====================================================================
1880    // C-4 T3: the cross-check loops over synthesized param POINTS, so the
1881    // dtype differentials for the params-DEPENDENT fused ops (Conv2D /
1882    // ConvTranspose2D / QMatMul / FusedSoftmaxCrossEntropy / CausalConv1d)
1883    // are now LIVE. Each op is proven to FIRE by a dtype mutation that
1884    // disagrees with the real registered fn (a dormant differential would
1885    // let the mutated import succeed — the false-green risk); the unmutated
1886    // corpus, which agrees, stays importable WITHOUT any guard-caught panic
1887    // (no debug-only skips hiding under the differential).
1888    // =====================================================================
1889
1890    /// EOL-normalize an embedded corpus file. `include_str!` carries the
1891    /// CHECKOUT's line endings (CRLF on an autocrlf Windows tree, LF
1892    /// elsewhere), so a multi-line mutation anchor written with `\n` would
1893    /// fail `mutate_once`'s exactly-once assert on one convention and pass on
1894    /// the other. Normalizing to LF makes the two-line anchors below
1895    /// checkout-independent; the FKC parser accepts either convention.
1896    fn lf(src: &str) -> String {
1897        src.replace("\r\n", "\n")
1898    }
1899
1900    #[test]
1901    fn fsce_dtype_differential_fires() {
1902        // FSCE's real registered dtype fn is CONSTANT F32 (the loss
1903        // accumulator dtype), independent of inputs and params. A contract
1904        // declaring `fixed(F16)` must be rejected. Before C-4 T3 the FSCE
1905        // differential never ran at all (`synth_probe_params` returns None
1906        // for params-dependent variants), so this exact mutation imported
1907        // clean — the plan's mutation proof that enforcement is now live.
1908        let mutated = mutate_once(
1909            FUSED_LINEAR_QUANT,
1910            "dtype_rule: fixed(F32)          # ALWAYS F32 regardless of input dtype",
1911            "dtype_rule: fixed(F16)          # ALWAYS F32 regardless of input dtype",
1912        );
1913        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1914            "an FSCE dtype_rule disagreeing with the constant-F32 real fn must be rejected",
1915        );
1916        assert!(
1917            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1918            "expected ShapeRuleMismatch, got {err:?}"
1919        );
1920    }
1921
1922    #[test]
1923    fn qmatmul_dtype_differential_fires() {
1924        // QMatMul's real dtype fn returns input 0 (`a`, F32 at every probe —
1925        // the contract declares a: [F32]). Declaring fixed(F16) disagrees.
1926        let mutated = mutate_once(
1927            FUSED_LINEAR_QUANT,
1928            "dtype_rule: fixed(F32)          # output is always F32 (dequant-and-contract); = a (F32)",
1929            "dtype_rule: fixed(F16)          # output is always F32 (dequant-and-contract); = a (F32)",
1930        );
1931        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1932            "a QMatMul dtype_rule disagreeing with the real passthrough fn must be rejected",
1933        );
1934        assert!(
1935            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1936            "expected ShapeRuleMismatch, got {err:?}"
1937        );
1938    }
1939
1940    #[test]
1941    fn conv2d_dtype_differential_fires() {
1942        // Conv2D's real dtype fn is passthrough(x) (= F32 at the probes; x's
1943        // first declared dtype). Declaring fixed(F64) disagrees. The bare
1944        // `dtype_rule: passthrough(x)` line is shared by 4 sections, so the
1945        // anchor spans into the section-unique shape_rule line (LF-normalized).
1946        let mutated = mutate_once(
1947            &lf(FUSED_CONV_ROPE),
1948            "dtype_rule: passthrough(x)\n      shape_rule: conv2d(params)",
1949            "dtype_rule: fixed(F64)\n      shape_rule: conv2d(params)",
1950        );
1951        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1952            "a Conv2D dtype_rule disagreeing with the real passthrough fn must be rejected",
1953        );
1954        assert!(
1955            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1956            "expected ShapeRuleMismatch, got {err:?}"
1957        );
1958    }
1959
1960    #[test]
1961    fn conv_transpose2d_dtype_differential_fires() {
1962        // ConvTranspose2D probes carry 3 operands (x, weight, optional bias —
1963        // the solver includes optional operands), so this differential also
1964        // pins the registry fn's 2-or-3 arity tolerance: were the fn still
1965        // `debug_assert_eq!(len, 2)`, a debug build would guard-catch the
1966        // panic and SKIP (import clean → this test fails), while release
1967        // checked — the exact debug-vs-release split the pre-check work bans.
1968        let mutated = mutate_once(
1969            &lf(FUSED_CONV_ROPE),
1970            "dtype_rule: passthrough(x)\n      shape_rule: conv_transpose2d(params)",
1971            "dtype_rule: fixed(F64)\n      shape_rule: conv_transpose2d(params)",
1972        );
1973        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry)
1974            .expect_err("a ConvTranspose2D dtype_rule disagreeing with the real passthrough fn must be rejected");
1975        assert!(
1976            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1977            "expected ShapeRuleMismatch, got {err:?}"
1978        );
1979    }
1980
1981    #[test]
1982    fn causal_conv1d_dtype_differential_fires() {
1983        let mutated = mutate_once(
1984            &lf(FUSED_CONV_ROPE),
1985            "dtype_rule: passthrough(x)\n      shape_rule: from_params(seq_out)",
1986            "dtype_rule: fixed(F64)\n      shape_rule: from_params(seq_out)",
1987        );
1988        let err = import_bundle_str(&mutated, &crate::fkc::CpuLinkRegistry).expect_err(
1989            "a CausalConv1d dtype_rule disagreeing with the real passthrough fn must be rejected",
1990        );
1991        assert!(
1992            matches!(err, FkcError::ShapeRuleMismatch { .. }),
1993            "expected ShapeRuleMismatch, got {err:?}"
1994        );
1995    }
1996
1997    /// C-4 T3 (regression + never-panic): the UNMUTATED corpus imports with
1998    /// its now-live dtype differentials actually RUNNING — and none of them
1999    /// leans on a guard-caught panic (a `guard_rule` catch would push a
2000    /// "panicked" warning and silently skip the differential in debug builds
2001    /// only). The params-dependent ops' `conv2d(params)`/`from_params(...)`
2002    /// SHAPE rules remain non-evaluable → documented skips, unchanged.
2003    #[test]
2004    fn unmutated_corpus_dtype_differentials_run_without_guard_panics() {
2005        for (src, name) in [
2006            (FUSED_LINEAR_QUANT, "linear-quant"),
2007            (FUSED_CONV_ROPE, "conv-rope"),
2008        ] {
2009            let provider = import_bundle_str(src, &crate::fkc::CpuLinkRegistry)
2010                .unwrap_or_else(|e| panic!("{name} must import clean: {e:?}"));
2011            let panicked: Vec<_> = provider
2012                .warnings
2013                .iter()
2014                .filter(|w| w.message.contains("panicked"))
2015                .collect();
2016            assert!(
2017                panicked.is_empty(),
2018                "{name}: live differentials must not rely on guard-caught panics \
2019                 (debug-only skips): {panicked:?}",
2020            );
2021        }
2022    }
2023
2024    /// C-4 T3 (Conv2D arity pre-check): a synthetic 1-input CONV2D contract.
2025    /// The registry conv2d rule fns read `input_shapes[1]` / assert 2-or-3
2026    /// inputs, so an under-declared contract must be skipped CONSISTENTLY in
2027    /// debug and release with a warning — mirroring the attention-family
2028    /// pre-check (real 2-input CONV2D fused sections exist in
2029    /// `vulkan/conv-attn-rope.fkc.md`, so the under-declaration risk is live).
2030    const SYNTH_CONV2D_1IN: &str = r#"---
2031fkc_version: 1
2032provider:
2033  name: synth-conv2d-1input
2034  backend: Cpu
2035  kernel_source: "portable-cpu"
2036---
2037
2038# synthetic 1-input CONV2D (C-4 T3 arity pre-check)
2039
2040## conv2d_1in
2041
2042Synthetic 1-input Conv2D (x only, no weight) to exercise the arity pre-check.
2043
2044```fkc
2045kernel: conv2d_1in
2046fused_op: CONV2D
2047blurb: "synthetic 1-input conv2d (x only) to exercise the arity pre-check"
2048backend: Cpu
2049kernel_source: "portable-cpu"
2050entry_point: "synthetic::conv2d_1in_cpu"
2051kernel_revision_hash: auto
2052
2053accept:
2054  inputs:
2055    - name: x
2056      dtypes: [F32]
2057      layout: { contiguous: required, strided: rejected, broadcast_stride0: rejected, start_offset: rejected, reverse_strides: rejected }
2058      rank: 4
2059  op_params:
2060    variant: Conv2D
2061    fields:
2062      stride:  { kind: "(usize, usize)" }
2063      padding: { kind: "(usize, usize)" }
2064      groups:  { kind: usize }
2065
2066return:
2067  outputs:
2068    - name: out
2069      dtype_rule: passthrough(x)
2070      shape_rule: conv2d(params)
2071      layout_guarantee: contiguous
2072
2073caps:
2074  awkward_layout_strategy: requires_contiguous
2075  in_place: false
2076
2077cost:
2078  provenance: judge_measured
2079  class: conv
2080
2081precision:
2082  bit_stable_on_same_hardware: false
2083  max_ulp: ~
2084  max_relative: ~
2085  max_absolute: ~
2086  audited: false
2087  notes: "synthetic"
2088
2089determinism: same_hardware_bitwise
2090```
2091"#;
2092
2093    #[test]
2094    fn under_arity_conv2d_skips_differential_consistently_and_warns() {
2095        // Without the pre-check a 1-input CONV2D contract skips SILENTLY
2096        // (the shape-coupled synth declines the unreadable combo), leaving no
2097        // trace of the dead differential. The pre-check surfaces the skip.
2098        let provider = import_bundle_str(SYNTH_CONV2D_1IN, &StubResolveAll)
2099            .expect("a 1-input CONV2D contract imports (never-panic; differential skipped)");
2100        assert!(
2101            provider
2102                .warnings
2103                .iter()
2104                .any(|w| w.message.contains("requires >= 2") && w.message.contains("skipped")),
2105            "the under-arity Conv2D differential must be skipped WITH a warning \
2106             (consistent debug/release): {:?}",
2107            provider.warnings,
2108        );
2109    }
2110
2111    /// Review fix (silent empty-points skip): a params-DEPENDENT variant whose
2112    /// probe combo the shape-coupled synth can't safely read (here: a rank-3
2113    /// `x` — the derivation needs rank-4) gets EMPTY param points, so every
2114    /// shape/dtype differential for that combo is skipped. That skip must
2115    /// surface an `ImportWarning` (the module's "a caught panic is no longer a
2116    /// silent skip" norm applied to the points path); it passes the arity
2117    /// pre-check (2 inputs), so without its own warning the coverage hole
2118    /// would leave no trace.
2119    const SYNTH_CONV2D_RANK3: &str = r#"---
2120fkc_version: 1
2121provider:
2122  name: synth-conv2d-rank3
2123  backend: Cpu
2124  kernel_source: "portable-cpu"
2125---
2126
2127# synthetic rank-3 CONV2D (review fix: empty-param-points warning)
2128
2129## conv2d_rank3
2130
2131Synthetic 2-input Conv2D whose `x` declares rank 3 (the shape-coupled synth needs rank 4), to
2132exercise the empty-points warning.
2133
2134```fkc
2135kernel: conv2d_rank3
2136fused_op: CONV2D
2137blurb: "synthetic rank-3-x conv2d to exercise the empty-param-points warning"
2138backend: Cpu
2139kernel_source: "portable-cpu"
2140entry_point: "synthetic::conv2d_rank3_cpu"
2141kernel_revision_hash: auto
2142
2143accept:
2144  inputs:
2145    - name: x
2146      dtypes: [F32]
2147      layout: { contiguous: required, strided: rejected, broadcast_stride0: rejected, start_offset: rejected, reverse_strides: rejected }
2148      rank: 3
2149    - name: weight
2150      dtypes: [F32]
2151      layout: { contiguous: required, strided: rejected, broadcast_stride0: rejected, start_offset: rejected, reverse_strides: rejected }
2152      rank: 4
2153  op_params:
2154    variant: Conv2D
2155    fields:
2156      stride:  { kind: "(usize, usize)" }
2157      padding: { kind: "(usize, usize)" }
2158      groups:  { kind: usize }
2159
2160return:
2161  outputs:
2162    - name: out
2163      dtype_rule: passthrough(x)
2164      shape_rule: conv2d(params)
2165      layout_guarantee: contiguous
2166
2167caps:
2168  awkward_layout_strategy: requires_contiguous
2169  in_place: false
2170
2171cost:
2172  provenance: judge_measured
2173  class: conv
2174
2175precision:
2176  bit_stable_on_same_hardware: false
2177  max_ulp: ~
2178  max_relative: ~
2179  max_absolute: ~
2180  audited: false
2181  notes: "synthetic"
2182
2183determinism: same_hardware_bitwise
2184```
2185"#;
2186
2187    #[test]
2188    fn empty_param_points_for_params_dependent_variant_warns() {
2189        let provider = import_bundle_str(SYNTH_CONV2D_RANK3, &StubResolveAll)
2190            .expect("a rank-3-x CONV2D contract imports (never-panic; differentials skipped)");
2191        assert!(
2192            provider
2193                .warnings
2194                .iter()
2195                .any(|w| w.message.contains("no param point") && w.message.contains("skipped")),
2196            "an unreadable combo for a params-dependent variant must skip its \
2197             differentials WITH a warning, not silently: {:?}",
2198            provider.warnings,
2199        );
2200    }
2201
2202    // =====================================================================
2203    // DUPLICATE: two sections at the same key+pointer → DuplicateKernelRef
2204    // =====================================================================
2205
2206    #[test]
2207    /// FKC-CLAUSE: FKC-10.10-0001 — path (1), the FKC IMPORT path MUST PROPAGATE.
2208    /// A provider contract is untrusted input, so a duplicate is a rejectable
2209    /// contract carrying a typed `FkcError::DuplicateKernelRef`, never a crash.
2210    fn same_pointer_on_one_key_surfaces_duplicate_kernel_ref() {
2211        // A hand-built bundle: two sections that resolve to the SAME
2212        // (op, dtypes, backend) key — and the SameLink maps both
2213        // entry_points to the SAME pointer. register_into's finalize gate
2214        // must surface DuplicateKernelRef.
2215        let src = "\
2216---
2217fkc_version: 1
2218provider:
2219  name: dup-provider
2220  backend: Cpu
2221  kernel_source: \"dup-cpu\"
2222---
2223
2224# dup bundle
2225
2226## add_a
2227
2228A.
2229
2230```fkc
2231kernel: add_a
2232op_kind: AddElementwise
2233blurb: \"a\"
2234entry_point: \"x::add_a\"
2235accept:
2236  inputs:
2237    - name: lhs
2238      dtypes: [F32]
2239      layout: { contiguous: required, strided: rejected }
2240    - name: rhs
2241      dtypes: [F32]
2242      layout: { contiguous: required, strided: rejected }
2243  op_params: { variant: None }
2244return:
2245  outputs:
2246    - name: out
2247      dtype_rule: passthrough(lhs)
2248cost:
2249  provenance: declared
2250  class: cheap_elementwise
2251  flops: \"n\"
2252precision:
2253  bit_stable_on_same_hardware: true
2254  audited: true
2255determinism: same_hardware_bitwise
2256```
2257
2258## add_b
2259
2260B.
2261
2262```fkc
2263kernel: add_b
2264op_kind: AddElementwise
2265blurb: \"b\"
2266entry_point: \"x::add_b\"
2267accept:
2268  inputs:
2269    - name: lhs
2270      dtypes: [F32]
2271      layout: { contiguous: required, strided: rejected }
2272    - name: rhs
2273      dtypes: [F32]
2274      layout: { contiguous: required, strided: rejected }
2275  op_params: { variant: None }
2276return:
2277  outputs:
2278    - name: out
2279      dtype_rule: passthrough(lhs)
2280cost:
2281  provenance: declared
2282  class: cheap_elementwise
2283  flops: \"n\"
2284precision:
2285  bit_stable_on_same_hardware: true
2286  audited: true
2287determinism: same_hardware_bitwise
2288```
2289";
2290        let provider =
2291            import_bundle_str(src, &SameLink).expect("the dup bundle imports (lowering is fine)");
2292        // Both sections share (AddElementwise, [F32,F32,F32], Cpu) AND the
2293        // same pointer → finalize must reject.
2294        let mut table = KernelBindingTable::new();
2295        let mut fused = FusedKernelRegistry::new();
2296        let err = provider
2297            .register_into(&mut table, &mut fused)
2298            .expect_err("same pointer on one key must error");
2299        assert!(
2300            matches!(err, FkcError::DuplicateKernelRef(_)),
2301            "got {err:?}"
2302        );
2303    }
2304
2305    // =====================================================================
2306    // COST COMPILER (§2.3, FKC gap-closure Task 2.2): a contract's declared
2307    // `cost.flops` expression must reach `BindingEntry.cost_expr` as a
2308    // compiled AST, not be dropped in favor of the `unknown_cost` sentinel.
2309    // =====================================================================
2310
2311    #[test]
2312    fn imported_contract_declared_cost_reaches_binding_cost_fn() {
2313        let src = "---\nfkc_version: 1\nprovider:\n  name: cost-provider\n  backend: Cpu\n  kernel_source: \"cost-cpu\"\n---\n\n# cost bundle\n\n## add_f32\n\nA.\n\n```fkc\nkernel: add_f32\nop_kind: AddElementwise\nblurb: \"a\"\nentry_point: \"x::add_f32\"\naccept:\n  inputs:\n    - name: lhs\n      dtypes: [F32]\n      layout: { contiguous: required, strided: rejected }\n    - name: rhs\n      dtypes: [F32]\n      layout: { contiguous: required, strided: rejected }\n  op_params: { variant: None }\nreturn:\n  outputs:\n    - name: out\n      dtype_rule: passthrough(lhs)\ncost:\n  provenance: declared\n  class: cheap_elementwise\n  flops: \"n\"\nprecision:\n  bit_stable_on_same_hardware: true\n  audited: true\ndeterminism: same_hardware_bitwise\n```\n";
2314        let provider = import_bundle_str(src, &SameLink).expect("declared-cost contract imports");
2315        let mut table = KernelBindingTable::new();
2316        let mut fused = FusedKernelRegistry::new();
2317        provider
2318            .register_into(&mut table, &mut fused)
2319            .expect("registers");
2320        let alts = table.lookup_alternatives(
2321            OpKind::AddElementwise,
2322            &[DType::F32, DType::F32, DType::F32],
2323            BackendId::Cpu,
2324        );
2325        let entry = alts.first().expect("binding present");
2326        let expr = entry
2327            .cost_expr
2328            .expect("declared flops formula reaches the binding as a compiled AST");
2329        let est = crate::fkc::cost_estimate(
2330            expr,
2331            OpKind::AddElementwise,
2332            &[fuel_ir::Shape::from_dims(&[4])],
2333            &[DType::F32, DType::F32, DType::F32],
2334            &crate::kernel::OpParams::None,
2335        )
2336        .expect("declared cost evaluates");
2337        assert_eq!(est.flops, 4, "flops = n = elem_count([4])");
2338    }
2339
2340    // =====================================================================
2341    // GLOB: agreeing front-matter merges; a mismatch → ProviderMismatch
2342    // =====================================================================
2343
2344    fn write_temp(dir: &Path, name: &str, contents: &str) {
2345        std::fs::write(dir.join(name), contents).expect("write temp fkc file");
2346    }
2347
2348    fn bundle_with(provider_backend: &str, kernel: &str, op_kind: &str, entry: &str) -> String {
2349        bundle_with_revision_base(provider_backend, kernel, op_kind, entry, None)
2350    }
2351
2352    fn bundle_with_revision_base(
2353        provider_backend: &str,
2354        kernel: &str,
2355        op_kind: &str,
2356        entry: &str,
2357        revision_base: Option<&str>,
2358    ) -> String {
2359        bundle_with_front_matter(
2360            provider_backend,
2361            kernel,
2362            op_kind,
2363            entry,
2364            revision_base,
2365            None,
2366        )
2367    }
2368
2369    fn bundle_with_link_registry(
2370        provider_backend: &str,
2371        kernel: &str,
2372        op_kind: &str,
2373        entry: &str,
2374        link_registry: Option<&str>,
2375    ) -> String {
2376        bundle_with_front_matter(
2377            provider_backend,
2378            kernel,
2379            op_kind,
2380            entry,
2381            None,
2382            link_registry,
2383        )
2384    }
2385
2386    fn bundle_with_front_matter(
2387        provider_backend: &str,
2388        kernel: &str,
2389        op_kind: &str,
2390        entry: &str,
2391        revision_base: Option<&str>,
2392        link_registry: Option<&str>,
2393    ) -> String {
2394        // A raw string with real newlines (NO `\`-continuations, which
2395        // would eat the YAML indentation).
2396        let template = r#"---
2397fkc_version: 1
2398provider:
2399  name: glob-provider
2400  backend: __BACKEND__
2401  kernel_source: "glob-cpu"__REVISION_BASE____LINK_REGISTRY__
2402---
2403
2404# glob bundle
2405
2406## __KERNEL__
2407
2408blurb.
2409
2410```fkc
2411kernel: __KERNEL__
2412op_kind: __OP_KIND__
2413blurb: "k"
2414entry_point: "__ENTRY__"
2415accept:
2416  inputs:
2417    - name: lhs
2418      dtypes: [F32]
2419      layout: { contiguous: required, strided: rejected }
2420    - name: rhs
2421      dtypes: [F32]
2422      layout: { contiguous: required, strided: rejected }
2423  op_params: { variant: None }
2424return:
2425  outputs:
2426    - name: out
2427      dtype_rule: passthrough(lhs)
2428cost:
2429  provenance: declared
2430  class: cheap_elementwise
2431  flops: "n"
2432precision:
2433  bit_stable_on_same_hardware: true
2434  audited: true
2435determinism: same_hardware_bitwise
2436```
2437"#;
2438        let rev_line = match revision_base {
2439            Some(r) => format!("\n  revision_base: \"{r}\""),
2440            None => String::new(),
2441        };
2442        let link_line = match link_registry {
2443            Some(r) => format!("\n  link_registry: \"{r}\""),
2444            None => String::new(),
2445        };
2446        template
2447            .replace("__REVISION_BASE__", &rev_line)
2448            .replace("__LINK_REGISTRY__", &link_line)
2449            .replace("__BACKEND__", provider_backend)
2450            .replace("__KERNEL__", kernel)
2451            .replace("__OP_KIND__", op_kind)
2452            .replace("__ENTRY__", entry)
2453    }
2454
2455    #[test]
2456    fn import_glob_merges_agreeing_files() {
2457        let dir = std::env::temp_dir().join(format!("fkc_glob_ok_{}", std::process::id()));
2458        let _ = std::fs::remove_dir_all(&dir);
2459        std::fs::create_dir_all(&dir).unwrap();
2460
2461        write_temp(
2462            &dir,
2463            "a.fkc.md",
2464            &bundle_with("Cpu", "add_f32", "AddElementwise", "x::add"),
2465        );
2466        write_temp(
2467            &dir,
2468            "b.fkc.md",
2469            &bundle_with("Cpu", "sub_f32", "SubElementwise", "x::sub"),
2470        );
2471
2472        let link = DistinctLink::new();
2473        let pattern = dir.join("*.fkc.md").display().to_string();
2474        let provider = import_glob(&pattern, &link).expect("two agreeing files merge");
2475
2476        assert_eq!(provider.name, "glob-provider");
2477        assert_eq!(provider.backend, BackendId::Cpu);
2478        assert_eq!(provider.primitives.len(), 2, "both kernels present");
2479
2480        // And they register end-to-end.
2481        let mut table = KernelBindingTable::new();
2482        let mut fused = FusedKernelRegistry::new();
2483        provider
2484            .register_into(&mut table, &mut fused)
2485            .expect("merged provider registers");
2486        assert!(
2487            table
2488                .lookup(
2489                    OpKind::AddElementwise,
2490                    &[DType::F32, DType::F32, DType::F32],
2491                    BackendId::Cpu
2492                )
2493                .is_ok()
2494        );
2495        assert!(
2496            table
2497                .lookup(
2498                    OpKind::SubElementwise,
2499                    &[DType::F32, DType::F32, DType::F32],
2500                    BackendId::Cpu
2501                )
2502                .is_ok()
2503        );
2504
2505        let _ = std::fs::remove_dir_all(&dir);
2506    }
2507
2508    /// §9.2 says the provider front-matter must AGREE across the files a glob
2509    /// merges. `revision_base` is part of that front-matter and is folded into
2510    /// `kernel_revision_hash` — which is in turn the key the verification
2511    /// ledger is looked up by. Two files of one globbed provider declaring
2512    /// different bases therefore produce kernels whose revision hashes are
2513    /// computed against different roots while presenting as a single provider,
2514    /// silently invalidating ledger lookups.
2515    ///
2516    /// This is the "existence != enforcement" shape: the loop is *commented*
2517    /// "front-matter must agree across files (§9.2)" and checks 3 of the 5
2518    /// declared fields.
2519    #[test]
2520    fn import_glob_mismatched_revision_base_is_provider_mismatch() {
2521        let dir = std::env::temp_dir().join(format!("fkc_glob_rev_{}", std::process::id()));
2522        let _ = std::fs::remove_dir_all(&dir);
2523        std::fs::create_dir_all(&dir).unwrap();
2524
2525        write_temp(
2526            &dir,
2527            "a.fkc.md",
2528            &bundle_with_revision_base(
2529                "Cpu",
2530                "add_f32",
2531                "AddElementwise",
2532                "x::add",
2533                Some("git:aaaaaaaa"),
2534            ),
2535        );
2536        write_temp(
2537            &dir,
2538            "b.fkc.md",
2539            &bundle_with_revision_base(
2540                "Cpu",
2541                "sub_f32",
2542                "SubElementwise",
2543                "x::sub",
2544                Some("git:bbbbbbbb"),
2545            ),
2546        );
2547
2548        let link = DistinctLink::new();
2549        let pattern = dir.join("*.fkc.md").display().to_string();
2550        let err = import_glob(&pattern, &link)
2551            .expect_err("a revision_base drift across a globbed provider must error");
2552        let msg = err.to_string();
2553        assert!(
2554            msg.contains("revision_base"),
2555            "the error must name the drifted field, got: {msg}"
2556        );
2557
2558        let _ = std::fs::remove_dir_all(&dir);
2559    }
2560
2561    /// The agreeing case must still merge — a guard that rejects everything is
2562    /// not a guard.
2563    #[test]
2564    fn import_glob_matching_revision_base_still_merges() {
2565        let dir = std::env::temp_dir().join(format!("fkc_glob_rev_ok_{}", std::process::id()));
2566        let _ = std::fs::remove_dir_all(&dir);
2567        std::fs::create_dir_all(&dir).unwrap();
2568
2569        for (f, k, op, e) in [
2570            ("a.fkc.md", "add_f32", "AddElementwise", "x::add"),
2571            ("b.fkc.md", "sub_f32", "SubElementwise", "x::sub"),
2572        ] {
2573            write_temp(
2574                &dir,
2575                f,
2576                &bundle_with_revision_base("Cpu", k, op, e, Some("git:deadbeef")),
2577            );
2578        }
2579
2580        let link = DistinctLink::new();
2581        let pattern = dir.join("*.fkc.md").display().to_string();
2582        let provider =
2583            import_glob(&pattern, &link).expect("agreeing revision_base must still merge");
2584        assert_eq!(provider.primitives.len(), 2, "both kernels present");
2585        assert_eq!(
2586            provider.revision_base.as_deref(),
2587            Some("git:deadbeef"),
2588            "the merged provider must retain the agreed revision_base"
2589        );
2590
2591        let _ = std::fs::remove_dir_all(&dir);
2592    }
2593
2594    /// The other half of §9.2's five fields. `link_registry` names the symbol
2595    /// table a file's `entry_point`s are meant to resolve against; `import_glob`
2596    /// binds every merged file through the ONE registry its caller passed in.
2597    /// So a glob whose files disagree on `link_registry` has at least one file
2598    /// whose entry points were resolved against a table its author never named
2599    /// — the symbols may well resolve, silently, to a different provider's
2600    /// kernels of the same name.
2601    #[test]
2602    fn import_glob_mismatched_link_registry_is_provider_mismatch() {
2603        let dir = std::env::temp_dir().join(format!("fkc_glob_link_{}", std::process::id()));
2604        let _ = std::fs::remove_dir_all(&dir);
2605        std::fs::create_dir_all(&dir).unwrap();
2606
2607        write_temp(
2608            &dir,
2609            "a.fkc.md",
2610            &bundle_with_link_registry(
2611                "Cpu",
2612                "add_f32",
2613                "AddElementwise",
2614                "x::add",
2615                Some("fuel_cpu_backend::fkc::ENTRY_POINTS"),
2616            ),
2617        );
2618        write_temp(
2619            &dir,
2620            "b.fkc.md",
2621            &bundle_with_link_registry(
2622                "Cpu",
2623                "sub_f32",
2624                "SubElementwise",
2625                "x::sub",
2626                Some("fuel_other_backend::fkc::ENTRY_POINTS"),
2627            ),
2628        );
2629
2630        let link = DistinctLink::new();
2631        let pattern = dir.join("*.fkc.md").display().to_string();
2632        let err = import_glob(&pattern, &link)
2633            .expect_err("a link_registry drift across a globbed provider must error");
2634        let msg = err.to_string();
2635        assert!(
2636            msg.contains("link_registry"),
2637            "the error must name the drifted field, got: {msg}"
2638        );
2639
2640        let _ = std::fs::remove_dir_all(&dir);
2641    }
2642
2643    /// The agreeing case must still merge, and must retain the agreed value —
2644    /// otherwise "enforced" could be satisfied by rejecting everything.
2645    #[test]
2646    fn import_glob_matching_link_registry_still_merges() {
2647        let dir = std::env::temp_dir().join(format!("fkc_glob_link_ok_{}", std::process::id()));
2648        let _ = std::fs::remove_dir_all(&dir);
2649        std::fs::create_dir_all(&dir).unwrap();
2650
2651        for (f, k, op, e) in [
2652            ("a.fkc.md", "add_f32", "AddElementwise", "x::add"),
2653            ("b.fkc.md", "sub_f32", "SubElementwise", "x::sub"),
2654        ] {
2655            write_temp(
2656                &dir,
2657                f,
2658                &bundle_with_link_registry(
2659                    "Cpu",
2660                    k,
2661                    op,
2662                    e,
2663                    Some("fuel_cpu_backend::fkc::ENTRY_POINTS"),
2664                ),
2665            );
2666        }
2667
2668        let link = DistinctLink::new();
2669        let pattern = dir.join("*.fkc.md").display().to_string();
2670        let provider =
2671            import_glob(&pattern, &link).expect("agreeing link_registry must still merge");
2672        assert_eq!(
2673            provider.link_registry.as_deref(),
2674            Some("fuel_cpu_backend::fkc::ENTRY_POINTS"),
2675            "the merged provider must retain the agreed link_registry"
2676        );
2677
2678        let _ = std::fs::remove_dir_all(&dir);
2679    }
2680
2681    #[test]
2682    fn import_glob_mismatched_backend_is_provider_mismatch() {
2683        let dir = std::env::temp_dir().join(format!("fkc_glob_bad_{}", std::process::id()));
2684        let _ = std::fs::remove_dir_all(&dir);
2685        std::fs::create_dir_all(&dir).unwrap();
2686
2687        // Two agreeing CPU files + a third with a different backend.
2688        write_temp(
2689            &dir,
2690            "a.fkc.md",
2691            &bundle_with("Cpu", "add_f32", "AddElementwise", "x::add"),
2692        );
2693        write_temp(
2694            &dir,
2695            "b.fkc.md",
2696            &bundle_with("Cpu", "sub_f32", "SubElementwise", "x::sub"),
2697        );
2698        write_temp(
2699            &dir,
2700            "c.fkc.md",
2701            &bundle_with("Vulkan", "mul_f32", "MulElementwise", "x::mul"),
2702        );
2703
2704        let link = DistinctLink::new();
2705        let pattern = dir.join("*.fkc.md").display().to_string();
2706        let err = import_glob(&pattern, &link).expect_err("mismatched backend must error");
2707        assert!(
2708            matches!(
2709                err,
2710                FkcError::ProviderMismatch { ref field, .. } if field == "provider.backend"
2711            ),
2712            "got {err:?}"
2713        );
2714
2715        let _ = std::fs::remove_dir_all(&dir);
2716    }
2717
2718    // =====================================================================
2719    // DESCRIBE-ONLY (§3.10): a registrable: false section is excluded from
2720    // register_into; a sibling registrable section still registers.
2721    // =====================================================================
2722
2723    #[test]
2724    fn describe_only_section_is_excluded_from_register_into() {
2725        // A bundle with a describe-only chassis umbrella (`## binary`,
2726        // op_kind = the DESCRIPTIVE token `binary`, registrable: false) plus
2727        // one real registrable thunk (`## add_f32`). Only the thunk lowers +
2728        // registers; the umbrella is documentation.
2729        let src = "\
2730---
2731fkc_version: 1
2732provider:
2733  name: describe-provider
2734  backend: Cpu
2735  kernel_source: \"describe-cpu\"
2736---
2737
2738# describe bundle
2739
2740## binary
2741
2742The shared chassis (documentation umbrella).
2743
2744```fkc
2745kernel: binary
2746registrable: false
2747op_kind: binary
2748blurb: \"shared binary chassis\"
2749entry_point: \"x::chassis\"
2750accept:
2751  inputs:
2752    - name: lhs
2753      dtypes: [F32, F64, BF16, F16]
2754      layout: { contiguous: required, strided: rejected }
2755    - name: rhs
2756      dtypes: [F32, F64, BF16, F16]
2757      layout: { contiguous: required, strided: rejected }
2758return:
2759  outputs:
2760    - name: out
2761      dtype_rule: passthrough(lhs)
2762cost:
2763  provenance: judge_measured
2764  class: cheap_elementwise
2765precision:
2766  bit_stable_on_same_hardware: true
2767  audited: true
2768determinism: same_hardware_bitwise
2769```
2770
2771## add_f32
2772
2773The real F32 addition thunk.
2774
2775```fkc
2776kernel: add_f32
2777op_kind: AddElementwise
2778blurb: \"F32 add\"
2779entry_point: \"x::add_f32\"
2780accept:
2781  inputs:
2782    - name: lhs
2783      dtypes: [F32]
2784      layout: { contiguous: required, strided: rejected }
2785    - name: rhs
2786      dtypes: [F32]
2787      layout: { contiguous: required, strided: rejected }
2788  op_params: { variant: None }
2789return:
2790  outputs:
2791    - name: out
2792      dtype_rule: passthrough(lhs)
2793cost:
2794  provenance: declared
2795  class: cheap_elementwise
2796  flops: \"n\"
2797precision:
2798  bit_stable_on_same_hardware: true
2799  audited: true
2800determinism: same_hardware_bitwise
2801```
2802";
2803        let link = DistinctLink::new();
2804        let provider = import_bundle_str(src, &link)
2805            .expect("describe-only + registrable bundle imports (umbrella is valid docs)");
2806
2807        // Only the registrable thunk lowered — the describe-only umbrella is
2808        // excluded from the registered set.
2809        assert_eq!(
2810            provider.primitives.len(),
2811            1,
2812            "exactly one registrable primitive (the umbrella is documentation-only)"
2813        );
2814        assert_eq!(provider.primitives[0].op, OpKind::AddElementwise);
2815
2816        // It registers end-to-end and the real key is present.
2817        let mut table = KernelBindingTable::new();
2818        let mut fused = FusedKernelRegistry::new();
2819        provider
2820            .register_into(&mut table, &mut fused)
2821            .expect("register_into succeeds (no describe-only section reaches the table)");
2822        assert!(
2823            table
2824                .lookup(
2825                    OpKind::AddElementwise,
2826                    &[DType::F32, DType::F32, DType::F32],
2827                    BackendId::Cpu
2828                )
2829                .is_ok()
2830        );
2831    }
2832
2833    // =====================================================================
2834    // DESCRIBE-ONLY GATHER (§3.10 + §14): a `registrable: false` section that
2835    // trips a consumer-ahead validator (FDX gather → GatherNotYetSupported)
2836    // must NOT block a bundle's importable sections. The valid sibling still
2837    // imports + registers; the describe-only gather section is documentation.
2838    // =====================================================================
2839
2840    #[test]
2841    fn describe_only_gather_section_does_not_block_bundle_import() {
2842        // A bundle with (a) one VALID registrable op_kind section (add_f32) and
2843        // (b) a `registrable: false` section whose operand carries an
2844        // `fdx.gather: paged_blocks` block — which the VALIDATE pass flags
2845        // `GatherNotYetSupported` (§14, consumer-ahead). Import must SKIP the
2846        // describe-only section's validation (it is documentation, carries no
2847        // dispatch target) and still register the valid sibling.
2848        //
2849        // **Born-red**: before the validate-skip fix, `validate_file` walked
2850        // EVERY section (incl. describe-only) and `validate_kernel` ran the gather
2851        // coherence check on the describe-only section → the whole
2852        // `import_bundle_str` returned `GatherNotYetSupported` (RED). After the
2853        // fix (`validate_file` skips `registrable: false` sections) → the valid
2854        // section imports + registers (GREEN).
2855        let src = r#"---
2856fkc_version: 1
2857provider:
2858  name: gather-describe-provider
2859  backend: Cpu
2860  kernel_source: "gather-cpu"
2861---
2862
2863# describe-only gather bundle
2864
2865## add_f32
2866
2867The real F32 addition thunk (registrable).
2868
2869```fkc
2870kernel: add_f32
2871op_kind: AddElementwise
2872blurb: "F32 add"
2873entry_point: "x::add_f32"
2874accept:
2875  inputs:
2876    - name: lhs
2877      dtypes: [F32]
2878      layout: { contiguous: required, strided: rejected }
2879    - name: rhs
2880      dtypes: [F32]
2881      layout: { contiguous: required, strided: rejected }
2882  op_params: { variant: None }
2883return:
2884  outputs:
2885    - name: out
2886      dtype_rule: passthrough(lhs)
2887cost:
2888  provenance: declared
2889  class: cheap_elementwise
2890  flops: "n"
2891precision:
2892  bit_stable_on_same_hardware: true
2893  audited: true
2894determinism: same_hardware_bitwise
2895```
2896
2897## paged_gather
2898
2899Describe-only: a paged KV pool with an FDX gather sidecar (consumer-ahead).
2900
2901```fkc
2902kernel: paged_gather
2903registrable: false
2904op_kind: PagedAttn
2905blurb: "describe-only paged gather"
2906entry_point: "x::paged_gather"
2907accept:
2908  inputs:
2909    - name: q
2910      dtypes: [F32]
2911      layout: { contiguous: required, strided: rejected }
2912    - name: k_cache
2913      dtypes: [F32]
2914      layout: { contiguous: required, strided: rejected }
2915      fdx:
2916        requires_ext: true
2917        symbolic_extent: required
2918        gather: { kind: paged_blocks, block_table: block_table, context_lens: context_lens }
2919    - name: block_table
2920      dtypes: [U32]
2921      layout: { contiguous: required, strided: rejected }
2922    - name: context_lens
2923      dtypes: [U32]
2924      layout: { contiguous: required, strided: rejected }
2925  op_params: { variant: PagedAttn }
2926return:
2927  outputs:
2928    - name: out
2929      dtype_rule: passthrough(q)
2930cost:
2931  provenance: declared
2932  class: attention
2933  flops: "n"
2934precision:
2935  bit_stable_on_same_hardware: true
2936  audited: true
2937determinism: same_hardware_bitwise
2938```
2939"#;
2940        let link = DistinctLink::new();
2941        let provider = import_bundle_str(src, &link).expect(
2942            "a describe-only gather section must NOT block the bundle's importable sections",
2943        );
2944
2945        // Only the registrable add_f32 lowered; the describe-only gather section
2946        // is documentation (excluded from the registered set).
2947        assert_eq!(
2948            provider.primitives.len(),
2949            1,
2950            "exactly one registrable primitive (the gather section is describe-only)",
2951        );
2952        assert_eq!(provider.primitives[0].op, OpKind::AddElementwise);
2953
2954        // The valid sibling registers end-to-end.
2955        let mut table = KernelBindingTable::new();
2956        let mut fused = FusedKernelRegistry::new();
2957        provider
2958            .register_into(&mut table, &mut fused)
2959            .expect("the valid sibling registers end-to-end");
2960        assert!(
2961            table
2962                .lookup(
2963                    OpKind::AddElementwise,
2964                    &[DType::F32, DType::F32, DType::F32],
2965                    BackendId::Cpu
2966                )
2967                .is_ok()
2968        );
2969    }
2970
2971    // =====================================================================
2972    // FUSED: a hand-built ResolvedFused registers into the fused registry
2973    // =====================================================================
2974
2975    #[test]
2976    fn hand_built_fused_registers_into_registry() {
2977        // The fused corpus declares `fused_op:` names that don't match the
2978        // registry's CamelCase entry names today, so we cover the fused
2979        // register path with a hand-built ResolvedFused (faithful to the
2980        // shape `register_into` consumes).
2981        let mut dtypes: KernelDTypes = SmallVec::new();
2982        dtypes.push(DType::F32); // input x
2983        dtypes.push(DType::F32); // output
2984
2985        let f = ResolvedFused {
2986            id: FusedOps::SOFTMAX_LAST_DIM,
2987            dtypes,
2988            backend: BackendId::Cpu,
2989            caps: KernelCaps::empty(),
2990            layouts: vec![ResolvedLayout {
2991                contiguous: Tri::Required,
2992                strided: Tri::Rejected,
2993                broadcast_stride0: Tri::Rejected,
2994                start_offset: Tri::Rejected,
2995                reverse_strides: Tri::Rejected,
2996            }],
2997            precision: PrecisionGuarantee::UNAUDITED,
2998            cost: CompiledCostExpr::Unknown,
2999            kernel: dummy_a,
3000            kernel_source: "portable-cpu".to_string(),
3001            revision: KernelRevisionHash::UNTRACKED,
3002            variant: None,
3003            bundle_slot_names: Vec::new(),
3004        };
3005
3006        let provider = ImportedProvider {
3007            name: "fuel-fused-registry".to_string(),
3008            backend: BackendId::Cpu,
3009            kernel_source: intern("portable-cpu"),
3010            revision_base: None,
3011            link_registry: None,
3012            primitives: Vec::new(),
3013            fused: vec![f],
3014            warnings: Vec::new(),
3015        };
3016
3017        let mut table = KernelBindingTable::new();
3018        let mut fused = FusedKernelRegistry::new();
3019        provider
3020            .register_into(&mut table, &mut fused)
3021            .expect("fused-only provider registers");
3022
3023        // The fused op is present in the registry.
3024        let got = fused.lookup_by_dtypes(
3025            FusedOps::SOFTMAX_LAST_DIM,
3026            BackendId::Cpu,
3027            &[DType::F32, DType::F32],
3028        );
3029        assert!(got.is_some(), "softmax fused impl registered + looked up");
3030        let impl_ = got.unwrap();
3031        // The interned dtypes round-trip.
3032        assert_eq!(impl_.dtypes, &[DType::F32, DType::F32]);
3033        // The fused-cost sentinel pointer was wired ([consumer-ahead]).
3034        let sentinel = fused_unknown_cost as *const () as usize;
3035        assert_eq!(
3036            impl_.cost as *const () as usize, sentinel,
3037            "the fused-unknown sentinel CostFn is wired for imported fused ops"
3038        );
3039        // The revision rode through unchanged.
3040        assert_eq!(impl_.revision, KernelRevisionHash::UNTRACKED);
3041    }
3042
3043    // =====================================================================
3044    // MULTI-DTYPE FAN-OUT (§3.4): a section whose operand(s) vary fans out
3045    // into N per-dtype bindings; `passthrough(role)` resolves the named
3046    // operand's dtype (NOT blindly the first input — the "where bug").
3047    // =====================================================================
3048
3049    /// A [`LinkRegistry`] that resolves EVERY requested symbol to a dummy
3050    /// pointer (keyed by the symbol string so a symbol maps stably) and
3051    /// RECORDS every requested symbol — so a test can assert exactly which
3052    /// `<base>_<suffix>` entry points the importer resolved. Permissive on
3053    /// purpose: it resolves the base symbol too, so the pre-change importer
3054    /// (which resolves the base as-is) still imports — letting the born-red
3055    /// fail on a clean binding-COUNT assertion, not an import error.
3056    struct FanStubLink {
3057        seen: Mutex<std::collections::HashMap<String, KernelRef>>,
3058        requested: Mutex<Vec<String>>,
3059    }
3060    impl FanStubLink {
3061        fn new() -> Self {
3062            Self {
3063                seen: Mutex::new(std::collections::HashMap::new()),
3064                requested: Mutex::new(Vec::new()),
3065            }
3066        }
3067        fn resolve(&self, symbol: &str) -> Option<KernelRef> {
3068            self.requested.lock().unwrap().push(symbol.to_string());
3069            let mut g = self.seen.lock().unwrap();
3070            if let Some(k) = g.get(symbol) {
3071                return Some(*k);
3072            }
3073            let k: KernelRef = if g.len().is_multiple_of(2) {
3074                dummy_a
3075            } else {
3076                dummy_b
3077            };
3078            g.insert(symbol.to_string(), k);
3079            Some(k)
3080        }
3081    }
3082    impl LinkRegistry for FanStubLink {
3083        fn resolve_primitive(&self, symbol: &str) -> Option<KernelRef> {
3084            self.resolve(symbol)
3085        }
3086        fn resolve_fused(&self, symbol: &str) -> Option<KernelRef> {
3087            self.resolve(symbol)
3088        }
3089    }
3090
3091    /// A synthetic bundle with (a) a UNIFORM multi-dtype section (`relu`: one
3092    /// input varying over `[F32,F64,BF16,F16]`, base `entry_point`) and (b) a
3093    /// MIXED section (`where_op`: a fixed `U8` `cond` + two varying operands +
3094    /// `passthrough(a)`). Authored with BASE entry_points (no dtype suffix) so
3095    /// the importer must resolve `<base>_<suffix>` per fanned dtype.
3096    const FANOUT_CONTRACT: &str = r#"---
3097fkc_version: 1
3098provider:
3099  name: fanout-provider
3100  backend: Cpu
3101  kernel_source: "fanout-cpu"
3102---
3103
3104# fanout bundle
3105
3106## relu
3107
3108Uniform multi-dtype unary: one input varying over 4 dtypes.
3109
3110```fkc
3111kernel: relu
3112op_kind: ReluElementwise
3113blurb: "relu fan-out"
3114entry_point: "stub::relu"
3115accept:
3116  inputs:
3117    - name: in
3118      dtypes: [F32, F64, BF16, F16]
3119      layout: { contiguous: required, strided: rejected }
3120  op_params: { variant: None }
3121return:
3122  outputs:
3123    - name: out
3124      dtype_rule: passthrough(in)
3125cost:
3126  provenance: declared
3127  class: cheap_elementwise
3128  flops: "n"
3129precision:
3130  bit_stable_on_same_hardware: true
3131  audited: true
3132determinism: same_hardware_bitwise
3133```
3134
3135## where_op
3136
3137Mixed: a fixed U8 cond + two varying operands; passthrough(a).
3138
3139```fkc
3140kernel: where_op
3141op_kind: Where
3142blurb: "where fan-out with passthrough(a)"
3143entry_point: "stub::where"
3144accept:
3145  inputs:
3146    - name: cond
3147      dtypes: [U8]
3148      layout: { contiguous: required, strided: rejected }
3149    - name: a
3150      dtypes: [F32, F64, BF16, F16]
3151      layout: { contiguous: required, strided: rejected }
3152    - name: b
3153      dtypes: [F32, F64, BF16, F16]
3154      layout: { contiguous: required, strided: rejected }
3155  op_params: { variant: None }
3156return:
3157  outputs:
3158    - name: out
3159      dtype_rule: passthrough(a)
3160cost:
3161  provenance: declared
3162  class: cheap_elementwise
3163  flops: "n"
3164precision:
3165  bit_stable_on_same_hardware: true
3166  audited: true
3167determinism: same_hardware_bitwise
3168```
3169"#;
3170
3171    #[test]
3172    fn multi_dtype_section_fans_out_into_per_dtype_bindings() {
3173        let link = FanStubLink::new();
3174        let provider = import_bundle_str(FANOUT_CONTRACT, &link).expect("fan-out contract imports");
3175
3176        // (1) FAN-OUT: `relu` (1 varying input) + `where_op` (2 varying inputs)
3177        // each fan to 4 per-dtype bindings ⇒ 8 primitives. Pre-change the
3178        // importer keyed on each operand's FIRST dtype and registered ONE
3179        // binding per section → 2. RED→GREEN.
3180        assert_eq!(
3181            provider.primitives.len(),
3182            8,
3183            "relu×4 + where×4 = 8 fanned bindings (pre-change: 2 — first-dtype only)"
3184        );
3185
3186        let mut table = KernelBindingTable::new();
3187        let mut fused = FusedKernelRegistry::new();
3188        provider
3189            .register_into(&mut table, &mut fused)
3190            .expect("fanned bindings register");
3191
3192        let dts = [DType::F32, DType::F64, DType::BF16, DType::F16];
3193
3194        // (2) UNIFORM fan-out: ReluElementwise bound at [dt, dt] for every dt.
3195        for dt in dts {
3196            assert!(
3197                table
3198                    .lookup(OpKind::ReluElementwise, &[dt, dt], BackendId::Cpu)
3199                    .is_ok(),
3200                "relu must be bound at [{dt:?}, {dt:?}]",
3201            );
3202        }
3203
3204        // (3) MIXED fan-out + passthrough-role FIX: Where bound at
3205        // [U8, dt, dt, dt] — the output mirrors operand `a` (= dt), NOT the
3206        // first input `cond` (U8).
3207        for dt in dts {
3208            assert!(
3209                table
3210                    .lookup(OpKind::Where, &[DType::U8, dt, dt, dt], BackendId::Cpu)
3211                    .is_ok(),
3212                "where must be bound at [U8, {dt:?}, {dt:?}, {dt:?}] (passthrough(a) = a's dtype)",
3213            );
3214            // The OLD buggy key (passthrough mirrored cond=U8) must NOT exist.
3215            assert!(
3216                table
3217                    .lookup(
3218                        OpKind::Where,
3219                        &[DType::U8, dt, dt, DType::U8],
3220                        BackendId::Cpu
3221                    )
3222                    .is_err(),
3223                "the pre-fix buggy key [U8,{dt:?},{dt:?},U8] must NOT be registered",
3224            );
3225        }
3226
3227        // (4) ENTRY-POINT base+suffix: the importer resolved `<base>_<suffix>`
3228        // for every fanned dtype (canonical `DType::as_str`, not a hand-rolled
3229        // spelling), NOT the bare base symbol.
3230        let requested = link.requested.lock().unwrap().clone();
3231        for suffix in ["f32", "f64", "bf16", "f16"] {
3232            assert!(
3233                requested
3234                    .iter()
3235                    .any(|s| s == &format!("stub::relu_{suffix}")),
3236                "relu variant must resolve stub::relu_{suffix}; requested={requested:?}",
3237            );
3238            assert!(
3239                requested
3240                    .iter()
3241                    .any(|s| s == &format!("stub::where_{suffix}")),
3242                "where variant must resolve stub::where_{suffix}; requested={requested:?}",
3243            );
3244        }
3245    }
3246
3247    /// Backward-compat guard: a section with NO varying operand (every operand
3248    /// single-dtype) produces EXACTLY ONE binding and resolves its declared
3249    /// `entry_point` AS-IS (no `_<suffix>` appended). This is what keeps the
3250    /// already-migrated per-(op,dtype) binary / affine / cast families
3251    /// byte-identical under fan-out. GREEN before AND after the change.
3252    #[test]
3253    fn single_dtype_section_yields_exactly_one_unchanged_binding() {
3254        let src = r#"---
3255fkc_version: 1
3256provider:
3257  name: single-provider
3258  backend: Cpu
3259  kernel_source: "single-cpu"
3260---
3261
3262# single bundle
3263
3264## add_f32
3265
3266```fkc
3267kernel: add_f32
3268op_kind: AddElementwise
3269blurb: "single-dtype add"
3270entry_point: "stub::add_f32"
3271accept:
3272  inputs:
3273    - name: lhs
3274      dtypes: [F32]
3275      layout: { contiguous: required, strided: rejected }
3276    - name: rhs
3277      dtypes: [F32]
3278      layout: { contiguous: required, strided: rejected }
3279  op_params: { variant: None }
3280return:
3281  outputs:
3282    - name: out
3283      dtype_rule: passthrough(lhs)
3284cost:
3285  provenance: declared
3286  class: cheap_elementwise
3287  flops: "n"
3288precision:
3289  bit_stable_on_same_hardware: true
3290  audited: true
3291determinism: same_hardware_bitwise
3292```
3293"#;
3294        let link = FanStubLink::new();
3295        let provider = import_bundle_str(src, &link).expect("single-dtype imports");
3296        assert_eq!(
3297            provider.primitives.len(),
3298            1,
3299            "no varying operand ⇒ exactly one binding"
3300        );
3301        assert_eq!(
3302            provider.primitives[0].dtypes.as_slice(),
3303            &[DType::F32, DType::F32, DType::F32],
3304        );
3305
3306        // entry_point resolved AS-IS (no `_f32` suffix appended to a
3307        // single-variant section — its declared symbol is already specific).
3308        let requested = link.requested.lock().unwrap().clone();
3309        assert!(
3310            requested.iter().any(|s| s == "stub::add_f32"),
3311            "single-variant resolves the declared symbol as-is; requested={requested:?}",
3312        );
3313        assert!(
3314            !requested.iter().any(|s| s == "stub::add_f32_f32"),
3315            "must NOT append a suffix to a single-variant section",
3316        );
3317    }
3318
3319    // =====================================================================
3320    // OPTIONAL-OPERAND FAN-OUT (§3.4): an `optional: true` LAST input fans
3321    // EACH dtype variant into TWO keys — one OMITTING the optional operand,
3322    // one INCLUDING it — BOTH bound to the SAME kernel_ref. Composes with
3323    // the dtype fan-out (multi-dtype AND optional ⇒ 2N bindings).
3324    // =====================================================================
3325
3326    /// A synthetic single-dtype contract: one REQUIRED input `x` + one
3327    /// `optional: true` LAST input `bias`, output `passthrough(x)`. With
3328    /// optional-operand support the importer registers TWO primitive bindings
3329    /// — no-bias `[x, out]` = `[F32, F32]` and with-bias `[x, bias, out]` =
3330    /// `[F32, F32, F32]` — BOTH resolving the SAME (single, as-is) `entry_point`
3331    /// ⇒ the SAME `KernelRef`.
3332    ///
3333    /// **Born-red**: BEFORE the fix the schema `TensorDesc` has no `optional`
3334    /// field, so serde silently drops `optional: true`; the operand is treated
3335    /// as REQUIRED and ONLY the with-bias key builds → `primitives.len() == 1`
3336    /// (RED). After the schema+key-builder fix → 2 (GREEN).
3337    const OPTIONAL_LAST_OPERAND_CONTRACT: &str = r#"---
3338fkc_version: 1
3339provider:
3340  name: opt-provider
3341  backend: Cpu
3342  kernel_source: "opt-cpu"
3343---
3344
3345# optional-operand bundle
3346
3347## opt_add
3348
3349One required input + one optional LAST input.
3350
3351```fkc
3352kernel: opt_add
3353op_kind: AddElementwise
3354blurb: "optional last operand"
3355entry_point: "stub::opt_add"
3356accept:
3357  inputs:
3358    - name: x
3359      dtypes: [F32]
3360      layout: { contiguous: required, strided: rejected }
3361    - name: bias
3362      dtypes: [F32]
3363      layout: { contiguous: required, strided: rejected }
3364      optional: true
3365  op_params: { variant: None }
3366return:
3367  outputs:
3368    - name: out
3369      dtype_rule: passthrough(x)
3370cost:
3371  provenance: declared
3372  class: cheap_elementwise
3373  flops: "n"
3374precision:
3375  bit_stable_on_same_hardware: true
3376  audited: true
3377determinism: same_hardware_bitwise
3378```
3379"#;
3380
3381    #[test]
3382    fn optional_last_operand_registers_both_with_and_without_keys() {
3383        let link = FanStubLink::new();
3384        let provider = import_bundle_str(OPTIONAL_LAST_OPERAND_CONTRACT, &link)
3385            .expect("optional-operand contract imports");
3386
3387        // TWO bindings: the with-optional key AND the without-optional key.
3388        // Pre-change (no `optional` schema field): serde drops the flag, the
3389        // operand is required, only the with-operand key builds → 1. RED→GREEN.
3390        assert_eq!(
3391            provider.primitives.len(),
3392            2,
3393            "an optional LAST input fans into 2 keys (with + without the operand); \
3394             pre-change (no `optional` schema field) only the with-operand key builds → 1",
3395        );
3396
3397        // BOTH keys bind the SAME kernel_ref (same entry_point resolved AS-IS —
3398        // single-dtype, so no `_<suffix>` is appended).
3399        let k0 = provider.primitives[0].kernel as usize;
3400        let k1 = provider.primitives[1].kernel as usize;
3401        assert_eq!(
3402            k0, k1,
3403            "both the with- and without-optional keys resolve the SAME kernel (one entry_point)",
3404        );
3405
3406        // The two keys are exactly `[x, out]` and `[x, bias, out]`.
3407        let mut keys: Vec<Vec<DType>> = provider
3408            .primitives
3409            .iter()
3410            .map(|p| p.dtypes.to_vec())
3411            .collect();
3412        keys.sort_by_key(|k| k.len());
3413        assert_eq!(
3414            keys[0],
3415            vec![DType::F32, DType::F32],
3416            "no-optional key = [x, out]",
3417        );
3418        assert_eq!(
3419            keys[1],
3420            vec![DType::F32, DType::F32, DType::F32],
3421            "with-optional key = [x, bias, out]",
3422        );
3423
3424        // Both register into the binding table + look up.
3425        let mut table = KernelBindingTable::new();
3426        let mut fused = FusedKernelRegistry::new();
3427        provider
3428            .register_into(&mut table, &mut fused)
3429            .expect("both keys register");
3430        assert!(
3431            table
3432                .lookup(
3433                    OpKind::AddElementwise,
3434                    &[DType::F32, DType::F32],
3435                    BackendId::Cpu
3436                )
3437                .is_ok(),
3438            "no-optional key [F32, F32] is bound",
3439        );
3440        assert!(
3441            table
3442                .lookup(
3443                    OpKind::AddElementwise,
3444                    &[DType::F32, DType::F32, DType::F32],
3445                    BackendId::Cpu,
3446                )
3447                .is_ok(),
3448            "with-optional key [F32, F32, F32] is bound",
3449        );
3450
3451        // The declared entry_point resolved AS-IS (single-dtype ⇒ no suffix).
3452        let requested = link.requested.lock().unwrap().clone();
3453        assert!(
3454            requested.iter().any(|s| s == "stub::opt_add"),
3455            "single-dtype section resolves its declared symbol as-is; requested={requested:?}",
3456        );
3457
3458        // BACKWARD-COMPAT: the SAME contract WITHOUT the `optional: true` flag is
3459        // a plain 2-input section → EXACTLY ONE binding (the fan is driven ONLY
3460        // by the optional flag; nothing else changed).
3461        let non_optional = OPTIONAL_LAST_OPERAND_CONTRACT.replace("      optional: true\n", "");
3462        let link2 = FanStubLink::new();
3463        let provider2 =
3464            import_bundle_str(&non_optional, &link2).expect("non-optional twin imports");
3465        assert_eq!(
3466            provider2.primitives.len(),
3467            1,
3468            "no optional operand ⇒ exactly one binding (backward-compat)",
3469        );
3470        assert_eq!(
3471            provider2.primitives[0].dtypes.to_vec(),
3472            vec![DType::F32, DType::F32, DType::F32],
3473            "the required-both key [x, bias, out]",
3474        );
3475    }
3476
3477    // =====================================================================
3478    // COST-FN TRAMPOLINE (§4.4, Task-F): a contract's `cost.cost_fn` NAME
3479    // resolves through the LinkRegistry to a real CostFn that is stamped on
3480    // the binding and SURVIVES the fill_unset pass. The LinkRegistry analog
3481    // of entry_point resolution — a named cost model, not the unknown_cost
3482    // sentinel. An unknown name is a typed UnknownCostFn (never silent).
3483    // =====================================================================
3484
3485    /// A distinctive test `CostFn` (distinct fn item ⇒ distinct pointer) that
3486    /// the trampoline pins onto a binding. Its 999_999 FLOPs value + its unique
3487    /// pointer identity make it observable that the CONTRACT's cost fn — not
3488    /// `unknown_cost` and not the op-family default — is what the binding
3489    /// carries after `register_into` AND after `fill_unset`.
3490    fn test_pinned_cost(
3491        _s: &[fuel_ir::Shape],
3492        _d: &[DType],
3493        _p: &crate::kernel::OpParams,
3494        _c: &fuel_ir::backend::BackendCapabilities,
3495    ) -> CostEstimate {
3496        CostEstimate {
3497            flops: 999_999,
3498            bytes_moved: 0,
3499            kernel_overhead_ns: 0,
3500        }
3501    }
3502
3503    /// A `LinkRegistry` that resolves the `cost.cost_fn` name `test_pinned_cost`
3504    /// to [`test_pinned_cost`] (and every entry_point to a dummy kernel) — the
3505    /// test analog of a provider that pins a real cost fn over its own cost-fn
3506    /// table (e.g. the CUDA `CUDA_COST_FNS` table).
3507    struct CostPinLink;
3508    impl LinkRegistry for CostPinLink {
3509        fn resolve_primitive(&self, _symbol: &str) -> Option<KernelRef> {
3510            Some(dummy_a)
3511        }
3512        fn resolve_fused(&self, _symbol: &str) -> Option<KernelRef> {
3513            Some(dummy_a)
3514        }
3515        fn resolve_cost_fn(&self, name: &str) -> Option<crate::kernel::CostFn> {
3516            if name == "test_pinned_cost" {
3517                Some(test_pinned_cost)
3518            } else {
3519                None
3520            }
3521        }
3522    }
3523
3524    /// A one-section bundle naming a cost fn in its `cost:` block. `__COST_FN__`
3525    /// is replaced by the test with the real (resolvable) or a bogus name.
3526    const COST_PIN_BUNDLE: &str = "\
3527---
3528fkc_version: 1
3529provider:
3530  name: cost-pin-provider
3531  backend: Cpu
3532  kernel_source: \"cost-pin-cpu\"
3533---
3534
3535# cost-pin bundle
3536
3537## add_pinned
3538
3539A.
3540
3541```fkc
3542kernel: add_pinned
3543op_kind: AddElementwise
3544blurb: \"a\"
3545entry_point: \"x::add_pinned\"
3546accept:
3547  inputs:
3548    - name: lhs
3549      dtypes: [F32]
3550      layout: { contiguous: required, strided: rejected }
3551    - name: rhs
3552      dtypes: [F32]
3553      layout: { contiguous: required, strided: rejected }
3554  op_params: { variant: None }
3555return:
3556  outputs:
3557    - name: out
3558      dtype_rule: passthrough(lhs)
3559cost:
3560  provenance: declared
3561  class: cheap_elementwise
3562  flops: \"n\"
3563  cost_fn: \"__COST_FN__\"
3564precision:
3565  bit_stable_on_same_hardware: true
3566  audited: true
3567determinism: same_hardware_bitwise
3568```
3569";
3570
3571    #[test]
3572    fn contract_pinned_cost_fn_survives_fill_unset() {
3573        // BORN-RED → GREEN. A contract whose cost block NAMES `test_pinned_cost`
3574        // must register the binding with THAT CostFn (resolved through the
3575        // LinkRegistry), and the `fill_unset_cost_for_backend` pass must LEAVE it
3576        // (that pass only replaces the `unknown_cost` sentinel). RED before the
3577        // trampoline wiring: `register_into` stamped `unknown_cost`, so fill_unset
3578        // clobbered the cell with the op-family default `cost_elementwise_binary_cpu`.
3579        let src = COST_PIN_BUNDLE.replace("__COST_FN__", "test_pinned_cost");
3580        let provider = import_bundle_str(&src, &CostPinLink)
3581            .expect("a bundle naming a resolvable cost fn imports");
3582
3583        // (1) Lowering resolved the NAME to the concrete CostFn on the record.
3584        assert_eq!(provider.primitives.len(), 1);
3585        assert!(
3586            provider.primitives[0].cost_fn.is_some(),
3587            "lower_primitive must resolve cost.cost_fn through resolve_cost_fn",
3588        );
3589
3590        let mut table = KernelBindingTable::new();
3591        let mut fused = FusedKernelRegistry::new();
3592        provider
3593            .register_into(&mut table, &mut fused)
3594            .expect("register_into succeeds");
3595
3596        let key = [DType::F32, DType::F32, DType::F32];
3597
3598        // (2) register_into stamped the PINNED cost fn, NOT the unknown_cost sentinel.
3599        let cost_before = table.lookup_cost(OpKind::AddElementwise, &key, BackendId::Cpu);
3600        assert_eq!(
3601            cost_before as usize, test_pinned_cost as *const () as usize,
3602            "register_into must stamp the contract-pinned CostFn (not unknown_cost)",
3603        );
3604        assert_ne!(
3605            cost_before as usize,
3606            crate::kernel::unknown_cost as *const () as usize,
3607            "the pinned CostFn must not be the unknown_cost sentinel",
3608        );
3609
3610        // (3) THE POINT OF TASK-F: fill_unset must NOT overwrite the pinned cost.
3611        table.fill_unset_cpu_cost(crate::cost::default_cost_for_op_kind);
3612        let cost_after = table.lookup_cost(OpKind::AddElementwise, &key, BackendId::Cpu);
3613        assert_eq!(
3614            cost_after as usize, test_pinned_cost as *const () as usize,
3615            "fill_unset must leave the contract-pinned CostFn untouched",
3616        );
3617        assert_ne!(
3618            cost_after as usize,
3619            crate::cost::cost_elementwise_binary_cpu as *const () as usize,
3620            "the pinned cost must NOT have been clobbered by the op-family default",
3621        );
3622
3623        // (4) FKC gap-closure Task 2.2: this contract ALSO declares
3624        // `flops: "n"` alongside the pinned `cost_fn` — the pinned fn must
3625        // win outright, so the binding's declared-AST slot stays None (the
3626        // AST does not compete with a contract-pinned CostFn).
3627        let alts = table.lookup_alternatives(OpKind::AddElementwise, &key, BackendId::Cpu);
3628        let entry = alts.first().expect("binding present");
3629        assert!(
3630            entry.cost_expr.is_none(),
3631            "a pinned cost_fn wins outright; the declared cost AST must not be stamped alongside it",
3632        );
3633    }
3634
3635    #[test]
3636    fn unknown_cost_fn_name_is_typed_error() {
3637        // A cost block naming a cost fn absent from the link registry's cost-fn
3638        // table is a typed UnknownCostFn at import time — never a silent
3639        // fallback to unknown_cost.
3640        let src = COST_PIN_BUNDLE.replace("__COST_FN__", "no_such_cost_fn");
3641        let err = import_bundle_str(&src, &CostPinLink)
3642            .expect_err("an unresolved cost_fn name must error");
3643        assert!(
3644            matches!(err, FkcError::UnknownCostFn { ref cost_fn, .. } if cost_fn == "no_such_cost_fn"),
3645            "got {err:?}",
3646        );
3647    }
3648
3649    // =====================================================================
3650    // WARNINGS SINK (Task 0.2): ImportedProvider carries a warnings vec.
3651    // =====================================================================
3652
3653    #[test]
3654    fn imported_provider_exposes_warnings_field_defaulting_empty() {
3655        // Direct struct construction (not via import) so this stays green across
3656        // every later component (component 4's gate will make import-path warnings
3657        // non-empty for precision-claiming contracts).
3658        let p = ImportedProvider {
3659            name: "p".into(),
3660            backend: fuel_ir::probe::BackendId::Cpu,
3661            kernel_source: "ks",
3662            revision_base: None,
3663            link_registry: None,
3664            primitives: Vec::new(),
3665            fused: Vec::new(),
3666            warnings: Vec::new(),
3667        };
3668        assert!(p.warnings.is_empty());
3669    }
3670}