use fuel_graph::registry::{FusedOpId, FusedOps, Reduction};
use fuel_ir::DType;
use fuel_ir::probe::BackendId;
use crate::fkc::verify::bit_stability::{
HostTensor, ProbeInputs, VerifyOutcome, fill_deterministic, verify_bit_stability,
};
use crate::fkc::verify::invoker_cpu::CpuInvoker;
use crate::fkc::verify::ledger::LedgerRecord;
use crate::fused::{BackendImpl, default_kernel_registry};
use crate::kernel::{BindingEntry, MatmulM, OpParams};
#[allow(
dead_code,
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."
)]
pub(crate) const ITERS: usize = 16;
#[derive(Debug, Clone, Copy)]
#[allow(
dead_code,
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."
)]
enum Family {
SoftmaxFwd,
NormFwd,
SoftmaxBwd,
NormBwd,
ReduceMaxToBwd,
PowiBwd,
FusedLinear,
QMatMul,
InplaceAffine,
Fsce,
Rope,
Conv2D,
ConvTranspose2D,
CausalConv1d,
SelectiveScan,
SsdChunkScan,
}
#[allow(
dead_code,
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."
)]
struct Probe {
inputs: ProbeInputs,
params: OpParams,
out_dtype: DType,
out_shape: Vec<usize>,
out_seed: Option<Vec<u8>>,
}
#[allow(
dead_code,
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."
)]
const TARGETS: &[(FusedOpId, Family, &str)] = &[
(
FusedOps::SOFTMAX_LAST_DIM,
Family::SoftmaxFwd,
"softmax_last_dim",
),
(
FusedOps::RMS_NORM_LAST_DIM,
Family::NormFwd,
"rms_norm_last_dim",
),
(
FusedOps::LAYER_NORM_LAST_DIM,
Family::NormFwd,
"layer_norm_last_dim",
),
(
FusedOps::SOFTMAX_LAST_DIM_BACKWARD,
Family::SoftmaxBwd,
"softmax_last_dim_backward",
),
(
FusedOps::LAYER_NORM_LAST_DIM_BACKWARD,
Family::NormBwd,
"layer_norm_last_dim_backward",
),
(
FusedOps::RMS_NORM_LAST_DIM_BACKWARD,
Family::NormBwd,
"rms_norm_last_dim_backward",
),
(
FusedOps::REDUCE_MAX_TO_BACKWARD,
Family::ReduceMaxToBwd,
"reduce_max_to_backward",
),
(FusedOps::POWI_BACKWARD, Family::PowiBwd, "powi_backward"),
(FusedOps::FUSED_LINEAR, Family::FusedLinear, "fused_linear"),
(FusedOps::QMATMUL, Family::QMatMul, "qmatmul"),
(
FusedOps::INPLACE_AFFINE,
Family::InplaceAffine,
"inplace_affine",
),
(
FusedOps::FUSED_SOFTMAX_CROSS_ENTROPY,
Family::Fsce,
"fused_softmax_cross_entropy",
),
(FusedOps::ROPE, Family::Rope, "rope"),
(FusedOps::CONV2D, Family::Conv2D, "conv2d"),
(
FusedOps::CONV_TRANSPOSE2D,
Family::ConvTranspose2D,
"conv_transpose2d",
),
(
FusedOps::CAUSAL_CONV1D,
Family::CausalConv1d,
"causal_conv1d",
),
(
FusedOps::SELECTIVE_SCAN,
Family::SelectiveScan,
"selective_scan",
),
(
FusedOps::SSD_CHUNK_SCAN,
Family::SsdChunkScan,
"ssd_chunk_scan",
),
];
#[allow(
dead_code,
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."
)]
pub(crate) fn to_bytes(dt: DType, vals: &[f32]) -> Option<Vec<u8>> {
Some(match dt {
DType::F32 => bytemuck::cast_slice(vals).to_vec(),
DType::F64 => {
let v: Vec<f64> = vals.iter().map(|&x| x as f64).collect();
bytemuck::cast_slice(&v).to_vec()
}
DType::BF16 => {
let v: Vec<half::bf16> = vals.iter().map(|&x| half::bf16::from_f32(x)).collect();
bytemuck::cast_slice(&v).to_vec()
}
DType::F16 => {
let v: Vec<half::f16> = vals.iter().map(|&x| half::f16::from_f32(x)).collect();
bytemuck::cast_slice(&v).to_vec()
}
_ => return None,
})
}
#[allow(
dead_code,
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."
)]
fn ht(dt: DType, shape: Vec<usize>, vals: &[f32]) -> Option<HostTensor> {
Some(HostTensor {
dtype: dt,
shape,
bytes: to_bytes(dt, vals)?,
})
}
#[allow(
dead_code,
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."
)]
fn build_probe(family: Family, dtypes: &[DType], seed: u64) -> Option<Probe> {
match family {
Family::SoftmaxFwd | Family::NormFwd => {
if dtypes.len() != 2 {
return None;
}
let dt = dtypes[0];
let (outer, last) = (2usize, 4usize);
let x = ht(
dt,
vec![outer * last],
&fill_deterministic(outer * last, seed),
)?;
let params = match family {
Family::SoftmaxFwd => OpParams::SoftmaxLastDim {
outer_count: outer,
last_dim: last,
},
_ => OpParams::NormLastDim {
outer_count: outer,
last_dim: last,
eps: 1e-5,
},
};
Some(Probe {
inputs: vec![x],
params,
out_dtype: dt,
out_shape: vec![outer * last],
out_seed: None,
})
}
Family::SoftmaxBwd | Family::NormBwd => {
if dtypes.len() != 3 {
return None;
}
let dt = dtypes[0];
let (outer, last) = (2usize, 4usize);
let y = ht(
dt,
vec![outer * last],
&fill_deterministic(outer * last, seed),
)?;
let g = ht(
dt,
vec![outer * last],
&fill_deterministic(outer * last, seed ^ 0x9E37_79B9),
)?;
let params = match family {
Family::SoftmaxBwd => OpParams::SoftmaxLastDim {
outer_count: outer,
last_dim: last,
},
_ => OpParams::NormLastDim {
outer_count: outer,
last_dim: last,
eps: 1e-5,
},
};
Some(Probe {
inputs: vec![y, g],
params,
out_dtype: dt,
out_shape: vec![outer * last],
out_seed: None,
})
}
Family::ReduceMaxToBwd => {
if dtypes.len() != 3 {
return None;
}
let dt = dtypes[0];
let x = ht(dt, vec![1], &fill_deterministic(1, seed))?;
let up = ht(dt, vec![1], &fill_deterministic(1, seed ^ 0xA5A5_A5A5))?;
Some(Probe {
inputs: vec![x, up],
params: OpParams::ReduceMaxToBackward {
input_shape: vec![1],
output_shape: vec![1],
},
out_dtype: dt,
out_shape: vec![1],
out_seed: None,
})
}
Family::PowiBwd => {
if dtypes.len() != 3 {
return None;
}
let dt = dtypes[0];
let x = ht(dt, vec![4], &fill_deterministic(4, seed))?;
let up = ht(dt, vec![4], &fill_deterministic(4, seed ^ 0xDEAD_BEEF))?;
Some(Probe {
inputs: vec![x, up],
params: OpParams::PowI { exp: 2 },
out_dtype: dt,
out_shape: vec![4],
out_seed: None,
})
}
Family::FusedLinear => {
if dtypes.len() != 4 {
return None;
}
let dt = dtypes[0];
let (m, n, k) = (2usize, 2usize, 2usize);
let lhs = ht(dt, vec![m * k], &fill_deterministic(m * k, seed))?;
let rhs = ht(dt, vec![k * n], &fill_deterministic(k * n, seed ^ 0x1234))?;
let bias = ht(dt, vec![n], &fill_deterministic(n, seed ^ 0x5678))?;
Some(Probe {
inputs: vec![lhs, rhs, bias],
params: OpParams::Matmul {
lhs_batch_dims: vec![],
rhs_batch_dims: vec![],
m,
n,
k,
m_compute: MatmulM::All,
},
out_dtype: dt,
out_shape: vec![m * n],
out_seed: None,
})
}
Family::QMatMul => {
if dtypes.len() != 3
|| dtypes[0] != DType::F32
|| dtypes[1] != DType::U32
|| dtypes[2] != DType::F32
{
return None;
}
let block_size = 18usize;
let mut w_bytes = vec![0u8; 2 * block_size];
for block in 0..2 {
let off = block * block_size;
w_bytes[off..off + 2].copy_from_slice(&half::f16::from_f32(1.0).to_le_bytes());
for i in 0..16 {
w_bytes[off + 2 + i] = 0x99;
}
}
let act: Vec<f32> = (1..=32).map(|x| x as f32).collect();
let act_bytes = bytemuck::cast_slice(&act).to_vec();
let w_len = w_bytes.len() / 4;
Some(Probe {
inputs: vec![
HostTensor {
dtype: DType::F32,
shape: vec![32],
bytes: act_bytes,
},
HostTensor {
dtype: DType::U32,
shape: vec![w_len],
bytes: w_bytes,
},
],
params: OpParams::QMatMul {
quant_type: fuel_graph::QuantType::Q4_0,
batch_count: 1,
m: 1,
n: 2,
k: 32,
},
out_dtype: DType::F32,
out_shape: vec![2],
out_seed: None,
})
}
Family::InplaceAffine => {
if dtypes.len() != 2 {
return None;
}
Some(Probe {
inputs: vec![],
params: OpParams::Affine { mul: 2.0, add: 1.0 },
out_dtype: dtypes[0],
out_shape: vec![4],
out_seed: Some(to_bytes(dtypes[0], &fill_deterministic(4, seed))?),
})
}
Family::Fsce => {
if dtypes.len() != 3 || dtypes[1] != DType::I64 {
return None;
}
let dt = dtypes[0];
let (n_rows, vocab) = (2usize, 4usize);
let logits = ht(
dt,
vec![n_rows * vocab],
&fill_deterministic(n_rows * vocab, seed),
)?;
let targets = HostTensor {
dtype: DType::I64,
shape: vec![n_rows],
bytes: bytemuck::cast_slice(&[1i64, 3i64]).to_vec(),
};
Some(Probe {
inputs: vec![logits, targets],
params: OpParams::FusedSoftmaxCrossEntropy {
n_rows,
vocab,
reduction: Reduction::Mean,
ignore_index: -100,
},
out_dtype: DType::F32,
out_shape: vec![1],
out_seed: None,
})
}
Family::Rope => {
if dtypes.len() != 4 {
return None;
}
let dt = dtypes[0];
let (outer, seq, head_dim) = (1usize, 1usize, 2usize);
let x = ht(
dt,
vec![outer * seq * head_dim],
&fill_deterministic(outer * seq * head_dim, seed),
)?;
let cos = ht(
dt,
vec![seq * head_dim],
&fill_deterministic(seq * head_dim, seed ^ 0x1111),
)?;
let sin = ht(
dt,
vec![seq * head_dim],
&fill_deterministic(seq * head_dim, seed ^ 0x2222),
)?;
Some(Probe {
inputs: vec![x, cos, sin],
params: OpParams::Rope {
outer_count: outer,
seq,
head_dim,
},
out_dtype: dt,
out_shape: vec![outer * seq * head_dim],
out_seed: None,
})
}
Family::Conv2D | Family::ConvTranspose2D => {
let with_bias = match dtypes.len() {
3 => false,
4 => true,
_ => return None,
};
let dt = dtypes[0];
let is_transpose = matches!(family, Family::ConvTranspose2D);
let (x_shape, w_shape, out_shape): ([usize; 4], [usize; 4], [usize; 4]) =
if is_transpose {
([1, 1, 2, 2], [1, 1, 2, 2], [1, 1, 3, 3])
} else {
([1, 1, 3, 3], [1, 1, 2, 2], [1, 1, 2, 2])
};
let (stride, padding, dilation, groups) =
((1usize, 1usize), (0usize, 0usize), (1usize, 1usize), 1usize);
let x_len: usize = x_shape.iter().product();
let w_len: usize = w_shape.iter().product();
let out_len: usize = out_shape.iter().product();
let cout = out_shape[1];
let x = ht(dt, vec![x_len], &fill_deterministic(x_len, seed))?;
let w = ht(dt, vec![w_len], &fill_deterministic(w_len, seed ^ 0x3333))?;
let mut inputs = vec![x, w];
if with_bias {
inputs.push(ht(
dt,
vec![cout],
&fill_deterministic(cout, seed ^ 0x4444),
)?);
}
let params = if is_transpose {
OpParams::ConvTranspose2D {
x_shape,
w_shape,
out_shape,
stride,
padding,
output_padding: (0, 0),
dilation,
groups,
}
} else {
OpParams::Conv2D {
x_shape,
w_shape,
out_shape,
stride,
padding,
dilation,
groups,
}
};
Some(Probe {
inputs,
params,
out_dtype: dt,
out_shape: vec![out_len],
out_seed: None,
})
}
Family::CausalConv1d => {
if dtypes.len() != 4 {
return None;
}
let dt = dtypes[0];
let (batch, channels, seq_in, seq_out, kernel) =
(1usize, 1usize, 4usize, 2usize, 3usize);
let x = ht(dt, vec![batch * channels * seq_in], &[0.0, 0.0, 1.0, 2.0])?;
let w = ht(dt, vec![channels * kernel], &[0.5, 1.0, 2.0])?;
let b = ht(dt, vec![channels], &[0.1])?;
Some(Probe {
inputs: vec![x, w, b],
params: OpParams::CausalConv1d {
batch,
channels,
seq_in,
seq_out,
kernel,
use_silu: false,
},
out_dtype: dt,
out_shape: vec![batch * channels * seq_out],
out_seed: None,
})
}
Family::SelectiveScan => {
if dtypes.len() != 6 {
return None;
}
let dt = dtypes[0];
let u = ht(dt, vec![1], &[3.0])?;
let delta = ht(dt, vec![1], &[1.0])?;
let a = ht(dt, vec![1], &[-1.0])?;
let b = ht(dt, vec![1], &[2.0])?;
let c = ht(dt, vec![1], &[0.5])?;
Some(Probe {
inputs: vec![u, delta, a, b, c],
params: OpParams::SelectiveScan {
batch: 1,
seqlen: 1,
dim: 1,
dstate: 1,
delta_softplus: false,
},
out_dtype: dt,
out_shape: vec![2],
out_seed: None,
})
}
Family::SsdChunkScan => {
if dtypes.len() != 6 {
return None;
}
let dt = dtypes[0];
let x = ht(dt, vec![1], &[3.0])?;
let dtp = ht(dt, vec![1], &[1.0])?;
let a = ht(dt, vec![1], &[-1.0])?;
let b = ht(dt, vec![1], &[2.0])?;
let c = ht(dt, vec![1], &[0.5])?;
Some(Probe {
inputs: vec![x, dtp, a, b, c],
params: OpParams::SsdChunkScan {
batch: 1,
seqlen: 1,
heads: 1,
head_dim: 1,
state_dim: 1,
chunk_size: 1,
},
out_dtype: dt,
out_shape: vec![2],
out_seed: None,
})
}
}
}
#[allow(
dead_code,
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."
)]
fn to_binding_entry(imp: &BackendImpl) -> BindingEntry {
BindingEntry {
kernel: imp.kernel,
caps: imp.caps,
precision: imp.precision,
cost: crate::kernel::unknown_cost,
kernel_source: "",
is_generic: false,
kernel_revision_hash: imp.revision.0,
cost_expr: None,
}
}
#[derive(Debug)]
#[allow(
dead_code,
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."
)]
pub struct SeedAttempt {
pub op_name: String,
pub dtypes: Vec<DType>,
pub kernel_revision_hash: u64,
pub outcome: String,
}
#[allow(
dead_code,
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."
)]
pub fn run_cpu_verification() -> (Vec<LedgerRecord>, Vec<SeedAttempt>) {
let registry = default_kernel_registry();
let mut records = Vec::new();
let mut log = Vec::new();
for &(id, family, name) in TARGETS {
for (backend, imp) in registry.impls_for(id) {
if *backend != BackendId::Cpu {
continue;
}
let dtypes: Vec<DType> = imp.dtypes.to_vec();
let rev = imp.revision.0;
let seed =
0x2545_F491_4F6C_DD1D_u64 ^ (id.0 as u64).wrapping_mul(0x9E37_79B9_7F4A_7C15);
let probe = match build_probe(family, imp.dtypes, seed) {
Some(p) => p,
None => {
log.push(SeedAttempt {
op_name: name.to_string(),
dtypes,
kernel_revision_hash: rev,
outcome: "unverified: no probe recipe for this dtype tuple".to_string(),
});
continue;
}
};
let entry = to_binding_entry(imp);
let mut inv = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
if let Some(seed_bytes) = probe.out_seed.clone() {
inv = inv.with_seeded_output(seed_bytes);
}
let inputs = probe.inputs.clone();
let attempt = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
verify_bit_stability(&inv, &entry, std::slice::from_ref(&inputs), ITERS)
}));
let outcome = match attempt {
Ok(Ok(VerifyOutcome::Pass)) => {
records.push(LedgerRecord {
kernel_ref: name.to_string(),
backend: "Cpu".to_string(),
dtypes: dtypes.iter().map(|d| format!("{d:?}")).collect(),
kernel_revision_hash: rev,
claim: "bit_stable_on_same_hardware".to_string(),
result: "pass".to_string(),
verified_at: verified_at_string(),
protocol_version: 1,
evidence: serde_json::json!({
"repeat_calls": ITERS,
"harness": "task-4.5b/seed_cpu_ledger",
"output_seeded": probe.out_seed.is_some(),
}),
});
"pass".to_string()
}
Ok(Ok(VerifyOutcome::Fail { detail })) => format!("fail: {detail}"),
Ok(Ok(VerifyOutcome::NoReference)) => "unverified: no probes".to_string(),
Ok(Err(e)) => format!("unverified: invoke error {e:?}"),
Err(_) => "unverified: kernel invocation panicked".to_string(),
};
log.push(SeedAttempt {
op_name: name.to_string(),
dtypes,
kernel_revision_hash: rev,
outcome,
});
}
}
(records, log)
}
#[allow(
dead_code,
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."
)]
pub fn run_cpu_primitive_verification() -> (Vec<LedgerRecord>, Vec<SeedAttempt>) {
use crate::fkc::verify::probe_recipes::{build_primitive_probe, probe_seed};
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let mut records = Vec::new();
let mut log = Vec::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
if backend != BackendId::Cpu {
continue;
}
let dtypes_vec = dtypes.to_vec();
let rev = entry.kernel_revision_hash;
let op_name = format!("{op:?}");
let probe = match build_primitive_probe(op, dtypes, probe_seed(op, dtypes)) {
Some(p) => p,
None => {
log.push(SeedAttempt {
op_name,
dtypes: dtypes_vec,
kernel_revision_hash: rev,
outcome: "unverified: no probe recipe for this op/dtype tuple".to_string(),
});
continue;
}
};
let mut inv = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
if let Some(seed_bytes) = probe.out_seed.clone() {
inv = inv.with_seeded_output(seed_bytes);
}
let inputs = probe.inputs.clone();
let attempt = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
verify_bit_stability(&inv, entry, std::slice::from_ref(&inputs), ITERS)
}));
let outcome = match attempt {
Ok(Ok(VerifyOutcome::Pass)) => {
records.push(LedgerRecord {
kernel_ref: op_name.clone(),
backend: "Cpu".to_string(),
dtypes: dtypes.iter().map(|d| format!("{d:?}")).collect(),
kernel_revision_hash: rev,
claim: "bit_stable_on_same_hardware".to_string(),
result: "pass".to_string(),
verified_at: verified_at_string(),
protocol_version: 1,
evidence: serde_json::json!({
"repeat_calls": ITERS,
"harness": "gap-207/seed_cpu_ledger::primitive",
"output_seeded": probe.out_seed.is_some(),
}),
});
"pass".to_string()
}
Ok(Ok(VerifyOutcome::Fail { detail })) => format!("fail: {detail}"),
Ok(Ok(VerifyOutcome::NoReference)) => "unverified: no probes".to_string(),
Ok(Err(e)) => format!("unverified: invoke error {e:?}"),
Err(_) => "unverified: kernel invocation panicked".to_string(),
};
log.push(SeedAttempt {
op_name,
dtypes: dtypes_vec,
kernel_revision_hash: rev,
outcome,
});
}
(records, log)
}
#[allow(
dead_code,
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."
)]
pub fn run_cpu_max_ulp_verification() -> (Vec<LedgerRecord>, Vec<SeedAttempt>) {
run_cpu_max_ulp_verification_inner(None)
}
#[allow(
dead_code,
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."
)]
pub(crate) fn run_cpu_max_ulp_verification_inner(
#[allow(unused_variables)] poison_op: Option<fuel_ir::dispatch::OpKind>,
) -> (Vec<LedgerRecord>, Vec<SeedAttempt>) {
use crate::fkc::verify::exact_ref::{ExactRefInvoker, has_exact_reference};
use crate::fkc::verify::probe_recipes::{build_primitive_probe, probe_seed};
use crate::fkc::verify::ulp::{Bound, verify_precision_bound};
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let mut records = Vec::new();
let mut log = Vec::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
if backend != BackendId::Cpu {
continue;
}
let dtypes_vec = dtypes.to_vec();
let rev = entry.kernel_revision_hash;
let op_name = format!("{op:?}");
if !has_exact_reference(op, dtypes) {
log.push(SeedAttempt {
op_name,
dtypes: dtypes_vec,
kernel_revision_hash: rev,
outcome: "unverified: no exact in-process reference for this op/dtype tuple"
.to_string(),
});
continue;
}
let probe = match build_primitive_probe(op, dtypes, probe_seed(op, dtypes)) {
Some(p) => p,
None => {
log.push(SeedAttempt {
op_name,
dtypes: dtypes_vec,
kernel_revision_hash: rev,
outcome: "unverified: no probe recipe for this op/dtype tuple".to_string(),
});
continue;
}
};
let cand = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
let refr = ExactRefInvoker {
op,
out_dtype: probe.out_dtype,
out_shape: probe.out_shape.clone(),
params: probe.params.clone(),
#[cfg(test)]
poison: poison_op == Some(op),
};
let inputs = probe.inputs.clone();
let attempt = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
verify_precision_bound(
&cand,
&refr,
entry,
std::slice::from_ref(&inputs),
Bound::MaxUlp(0),
)
}));
let outcome = match attempt {
Ok(Ok(VerifyOutcome::Pass)) => {
records.push(LedgerRecord {
kernel_ref: op_name.clone(),
backend: "Cpu".to_string(),
dtypes: dtypes.iter().map(|d| format!("{d:?}")).collect(),
kernel_revision_hash: rev,
claim: "max_ulp".to_string(),
result: "pass".to_string(),
verified_at: verified_at_string(),
protocol_version: 1,
evidence: serde_json::json!({
"bound": "MaxUlp(0)",
"reference": "exact in-process (fkc::verify::exact_ref)",
"harness": "gap-225/seed_cpu_ledger::max_ulp",
"reference_kind": "truth",
}),
});
"pass".to_string()
}
Ok(Ok(VerifyOutcome::Fail { detail })) => format!("fail: {detail}"),
Ok(Ok(VerifyOutcome::NoReference)) => "unverified: no probes".to_string(),
Ok(Err(e)) => format!("unverified: invoke error {e:?}"),
Err(_) => "unverified: kernel invocation panicked".to_string(),
};
log.push(SeedAttempt {
op_name,
dtypes: dtypes_vec,
kernel_revision_hash: rev,
outcome,
});
}
(records, log)
}
#[allow(
dead_code,
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."
)]
fn verified_at_string() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let secs = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
format!("epoch:{secs}")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_exact_reference_is_attached_to_the_op_it_claims() {
use fuel_ir::dispatch::OpKind;
const EXACT_REFERENCE_FAMILIES: usize = 9;
let (_, clean) = run_cpu_max_ulp_verification_inner(None);
let passing: Vec<(String, Vec<DType>)> = clean
.iter()
.filter(|a| a.outcome == "pass")
.map(|a| (a.op_name.clone(), a.dtypes.clone()))
.collect();
assert!(
!passing.is_empty(),
"no registration passes at all — this control would then be vacuous for \
every family below"
);
let mut fam_table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut fam_table);
let mut families: Vec<OpKind> = Vec::new();
for (op, dtypes, backend, _entry) in fam_table.iter_entries() {
if backend == BackendId::Cpu
&& crate::fkc::verify::exact_ref::has_exact_reference(op, dtypes)
&& !families.contains(&op)
{
families.push(op);
}
}
families.sort_by_key(|o| format!("{o:?}"));
assert_eq!(
families.len(),
EXACT_REFERENCE_FAMILIES,
"production offers an exact reference for {} CPU families, not the pinned {EXACT_REFERENCE_FAMILIES}: {families:?}. If a family was ADDED, it is now under this control and the pin moves with it; if one was REMOVED, say why its records no longer need an attachment check.",
families.len()
);
let mut families_tested = 0usize;
let mut not_testable: Vec<String> = Vec::new();
for op in families {
let name = format!("{op:?}");
let expected: Vec<&(String, Vec<DType>)> =
passing.iter().filter(|(n, _)| *n == name).collect();
if expected.is_empty() {
println!("[attach] {name}: no passing registration — not testable");
not_testable.push(name);
continue;
}
let (_, poisoned) = run_cpu_max_ulp_verification_inner(Some(op));
let failed: Vec<(String, Vec<DType>)> = poisoned
.iter()
.filter(|a| a.outcome.starts_with("fail:"))
.map(|a| (a.op_name.clone(), a.dtypes.clone()))
.collect();
let wrong_op: Vec<&String> = failed
.iter()
.map(|(n, _)| n)
.filter(|n| **n != name)
.collect();
assert!(
wrong_op.is_empty(),
"poisoning {name}'s reference also failed {wrong_op:?} — that reference \
is standing in for an op it does not claim to be about, and the record \
count cannot see it"
);
assert_eq!(
failed.len(),
expected.len(),
"poisoning {name}'s reference failed {} of its {} passing registrations. \
FEWER means some registration does not actually reach this reference — \
its pass was earned from something else.",
failed.len(),
expected.len()
);
families_tested += 1;
println!(
"[attach] {name}: {} registration(s), all and only",
failed.len()
);
}
assert_eq!(
families_tested, EXACT_REFERENCE_FAMILIES,
"only {families_tested} of {EXACT_REFERENCE_FAMILIES} exact-reference families were actually poisoned; {not_testable:?} had no passing registration to poison. Production claims an exact reference for them, so a skip here means their records rest on an attachment nothing checked."
);
}
fn outcome_bucket(outcome: &str) -> Option<&'static str> {
if outcome == "pass" {
Some("pass")
} else if outcome.starts_with("fail:") {
Some("fail")
} else if outcome.starts_with("unverified: no probe recipe") {
Some("no_recipe")
} else if outcome == "unverified: no probes" {
Some("no_probes")
} else if outcome.starts_with("unverified: no exact in-process reference") {
Some("no_reference")
} else if outcome.starts_with("unverified: invoke error") {
Some("invoke_error")
} else if outcome == "unverified: kernel invocation panicked" {
Some("panicked")
} else {
None
}
}
#[test]
fn the_outcome_vocabulary_is_classified_into_distinct_buckets() {
let vocabulary: &[(&str, &str)] = &[
("pass", "pass"),
("fail: byte 3 differs", "fail"),
(
"unverified: no probe recipe for this dtype tuple",
"no_recipe",
),
(
"unverified: no probe recipe for this op/dtype tuple",
"no_recipe",
),
("unverified: no probes", "no_probes"),
(
"unverified: no exact in-process reference for this op/dtype tuple",
"no_reference",
),
("unverified: invoke error Shape", "invoke_error"),
("unverified: kernel invocation panicked", "panicked"),
];
for (spelling, expected) in vocabulary {
assert_eq!(
outcome_bucket(spelling),
Some(*expected),
"`{spelling}` must classify as `{expected}`"
);
}
assert_ne!(
outcome_bucket("unverified: no probe recipe for this op/dtype tuple"),
outcome_bucket("unverified: no probes"),
"a harness gap (no recipe written) and a verifier result (no reference \
available) are different findings and must not merge — merging them is \
exactly what a shared `starts_with` prefix did"
);
assert_eq!(
outcome_bucket(&format!("unverified: {} something new", 1 + 1)),
None,
"an unknown outcome must return None so the sweeps can name it, instead of \
falling into a bucket that means something else"
);
}
#[test]
fn the_conv_probes_produce_a_non_constant_output() {
use crate::fkc::verify::bit_stability::KernelInvoker;
use crate::fkc::verify::probe_recipes::{build_primitive_probe, probe_seed};
use fuel_ir::dispatch::OpKind;
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let mut checked = 0usize;
let mut constant: Vec<String> = Vec::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
if backend != BackendId::Cpu
|| !matches!(
op,
OpKind::Conv2D | OpKind::ConvTranspose2D | OpKind::CausalConv1d
)
{
continue;
}
let Some(probe) = build_primitive_probe(op, dtypes, probe_seed(op, dtypes)) else {
continue;
};
let inv = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
let Ok(out) = inv.invoke(entry, &probe.inputs) else {
continue;
};
checked += 1;
let w = probe.out_dtype.size_in_bytes();
let distinct: std::collections::HashSet<&[u8]> = out.bytes.chunks(w).collect();
if distinct.len() < 2 {
constant.push(format!("{op:?} {dtypes:?} -> {} distinct", distinct.len()));
}
}
assert_eq!(
checked, 20,
"expected 20 conv registrations to invoke; got {checked}. Fewer means some \
probe or kernel did not run, and its record rests on nothing this test saw."
);
assert!(
constant.is_empty(),
"these conv probes produce a CONSTANT output, so a kernel ignoring its \
inputs would pass bit-stability identically: {constant:?}"
);
}
#[test]
fn the_small_surface_probes_respond_to_their_inputs() {
use crate::fkc::verify::bit_stability::KernelInvoker;
use crate::fkc::verify::probe_recipes::{build_primitive_probe, probe_seed};
use fuel_ir::dispatch::OpKind;
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let mut checked = 0usize;
let mut inert: Vec<String> = Vec::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
let seeded = match op {
OpKind::PowIElementwiseBackward
| OpKind::FusedLinear
| OpKind::FusedSoftmaxCrossEntropy => true,
OpKind::SelectiveScan | OpKind::SsdChunkScan => false,
_ => continue,
};
if backend != BackendId::Cpu {
continue;
}
let seed = probe_seed(op, dtypes);
let Some(probe) = build_primitive_probe(op, dtypes, seed) else {
continue;
};
let inv = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
let Ok(out) = inv.invoke(entry, &probe.inputs) else {
continue;
};
checked += 1;
let other = build_primitive_probe(op, dtypes, seed ^ 0xA5A5_A5A5)
.expect("a recipe that built once must build again");
let same_inputs = other.inputs.iter().map(|t| &t.bytes).collect::<Vec<_>>()
== probe.inputs.iter().map(|t| &t.bytes).collect::<Vec<_>>();
if seeded {
if same_inputs {
inert.push(format!(
"{op:?} {dtypes:?}: listed as seed-driven but a different seed \
produced IDENTICAL inputs, so the check below proves nothing"
));
continue;
}
let out2 = inv
.invoke(entry, &other.inputs)
.expect("second invocation of a probe that already ran");
if out2.bytes == out.bytes {
inert.push(format!(
"{op:?} {dtypes:?}: different inputs, IDENTICAL output — the \
kernel is not reading them, and it would be bit-stable anyway"
));
}
} else {
if !same_inputs {
inert.push(format!(
"{op:?} {dtypes:?}: listed as literal-valued but the seed changed \
its inputs — use the seed mechanism for it, it is stronger"
));
continue;
}
let w = probe.out_dtype.size_in_bytes();
let distinct: std::collections::HashSet<&[u8]> = out.bytes.chunks(w).collect();
if distinct.len() < 2 {
inert.push(format!(
"{op:?} {dtypes:?}: constant output ({} distinct), so a kernel \
ignoring its inputs would pass identically",
distinct.len()
));
}
}
}
assert_eq!(
checked, 20,
"expected 20 registrations across the four small surfaces to invoke; got \
{checked}. Fewer means a probe or kernel did not run and its record rests \
on nothing this test saw."
);
assert!(
inert.is_empty(),
"these probes do not demonstrably reach their kernel: {inert:?}"
);
}
#[test]
fn the_flash_attn_probe_reaches_the_live_prefix_path_and_reads_its_inputs() {
use crate::fkc::verify::bit_stability::KernelInvoker;
use crate::fkc::verify::probe_recipes::{build_primitive_probe, probe_seed};
use fuel_ir::dispatch::OpKind;
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let mut checked = 0usize;
let mut problems: Vec<String> = Vec::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
if backend != BackendId::Cpu || op != OpKind::FlashAttn {
continue;
}
let seed = probe_seed(op, dtypes);
let Some(probe) = build_primitive_probe(op, dtypes, seed) else {
continue;
};
match &probe.params {
OpParams::FlashAttn { sq, sk, k_len, .. } => {
if k_len >= sk {
problems.push(format!(
"{dtypes:?}: k_len({k_len}) >= sk({sk}) — the probe reads the \
whole K extent, so this record is evidence about the static \
path only and the live-prefix range is untouched"
));
}
if k_len.saturating_sub(*sq) == 0 {
problems.push(format!(
"{dtypes:?}: causal_offset is 0 (k_len={k_len}, sq={sq}) — the \
bottom-right alignment is not exercised"
));
}
}
other => problems.push(format!("{dtypes:?}: unexpected params {other:?}")),
}
let inv = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
let Ok(out) = inv.invoke(entry, &probe.inputs) else {
problems.push(format!("{dtypes:?}: probe did not invoke"));
continue;
};
checked += 1;
let other = build_primitive_probe(op, dtypes, seed ^ 0xA5A5_A5A5)
.expect("a recipe that built once must build again");
if other.inputs.iter().map(|t| &t.bytes).collect::<Vec<_>>()
== probe.inputs.iter().map(|t| &t.bytes).collect::<Vec<_>>()
{
problems.push(format!(
"{dtypes:?}: a different seed produced IDENTICAL inputs, so the \
response check below proves nothing"
));
continue;
}
let out2 = inv
.invoke(entry, &other.inputs)
.expect("second invocation of a probe that already ran");
if out2.bytes == out.bytes {
problems.push(format!(
"{dtypes:?}: different inputs, IDENTICAL output — the kernel is not \
reading them, and it would be bit-stable anyway"
));
}
}
assert_eq!(
checked, 8,
"expected 8 FlashAttn registrations to invoke (4 dtypes x {{with, without}} \
alibi_slopes); got {checked}"
);
assert!(problems.is_empty(), "{problems:?}");
}
#[test]
fn the_flash_attn_backward_probes_separate_both_output_shape_classes() {
use crate::fkc::verify::bit_stability::KernelInvoker;
use crate::fkc::verify::probe_recipes::{build_primitive_probe, probe_seed};
use fuel_ir::dispatch::OpKind;
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let mut checked = 0usize;
let mut problems: Vec<String> = Vec::new();
let mut q_shaped: std::collections::HashSet<usize> = std::collections::HashSet::new();
let mut kv_shaped: std::collections::HashSet<usize> = std::collections::HashSet::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
let is_q = match op {
OpKind::FlashAttnBackwardQ => true,
OpKind::FlashAttnBackwardK | OpKind::FlashAttnBackwardV => false,
_ => continue,
};
if backend != BackendId::Cpu {
continue;
}
let seed = probe_seed(op, dtypes);
let Some(probe) = build_primitive_probe(op, dtypes, seed) else {
continue;
};
let out_len = probe.out_shape.iter().product::<usize>();
if is_q {
q_shaped.insert(out_len);
} else {
kv_shaped.insert(out_len);
}
let inv = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
let Ok(out) = inv.invoke(entry, &probe.inputs) else {
problems.push(format!("{op:?} {dtypes:?}: probe did not invoke"));
continue;
};
checked += 1;
let other = build_primitive_probe(op, dtypes, seed ^ 0xA5A5_A5A5)
.expect("a recipe that built once must build again");
if other.inputs.iter().map(|t| &t.bytes).collect::<Vec<_>>()
== probe.inputs.iter().map(|t| &t.bytes).collect::<Vec<_>>()
{
problems.push(format!(
"{op:?} {dtypes:?}: a different seed produced IDENTICAL inputs, so the \
response check proves nothing"
));
continue;
}
let out2 = inv
.invoke(entry, &other.inputs)
.expect("second invocation of a probe that already ran");
if out2.bytes == out.bytes {
problems.push(format!(
"{op:?} {dtypes:?}: different inputs, IDENTICAL output — the kernel is \
not reading them, and it would be bit-stable anyway"
));
}
}
assert_eq!(
checked, 24,
"expected 24 backward registrations to invoke (3 ops x 4 dtypes x \
{{with, without}} alibi_slopes); got {checked}"
);
assert!(problems.is_empty(), "{problems:?}");
assert_eq!(
q_shaped.len(),
1,
"Q probes disagree on their output length: {q_shaped:?}"
);
assert_eq!(
kv_shaped.len(),
1,
"K/V probes disagree on their output length: {kv_shaped:?}"
);
assert_ne!(
q_shaped, kv_shaped,
"the q-shaped and kv-shaped output classes are the SAME SIZE, so a `which` \
switch routing every variant to the wrong branch would allocate correctly \
and stay bit-stable. The fixture has collapsed the axis this arm is \
parameterised on — separate them (q_len = b*hq*sq*d, kv_len = b*hkv*sk*d)."
);
}
#[test]
fn the_paged_attn_block_table_is_valid_and_actually_dereferenced() {
use crate::fkc::verify::bit_stability::KernelInvoker;
use crate::fkc::verify::probe_recipes::{build_primitive_probe, probe_seed};
use fuel_ir::dispatch::OpKind;
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let mut checked = 0usize;
let mut problems: Vec<String> = Vec::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
if backend != BackendId::Cpu || op != OpKind::PagedAttn {
continue;
}
let seed = probe_seed(op, dtypes);
let Some(probe) = build_primitive_probe(op, dtypes, seed) else {
continue;
};
let (num_blocks, block_size, max_bps, sq) = match &probe.params {
OpParams::PagedAttn {
num_blocks,
block_size,
max_blocks_per_seq,
sq,
..
} => (*num_blocks, *block_size, *max_blocks_per_seq, *sq),
other => {
problems.push(format!("{dtypes:?}: unexpected params {other:?}"));
continue;
}
};
let bt: Vec<u32> = bytemuck::cast_slice(&probe.inputs[3].bytes).to_vec();
let cl: Vec<u32> = bytemuck::cast_slice(&probe.inputs[4].bytes).to_vec();
if bt.iter().any(|&x| x as usize >= num_blocks) {
problems.push(format!("{dtypes:?}: block_table {bt:?} out of range"));
}
let distinct: std::collections::HashSet<u32> = bt.iter().copied().collect();
if distinct.len() != bt.len() {
problems.push(format!(
"{dtypes:?}: block_table {bt:?} repeats a physical block, so several \
logical blocks alias one page and the indirection is exercised \
trivially"
));
}
if bt.iter().enumerate().all(|(i, &x)| x as usize == i) {
problems.push(format!(
"{dtypes:?}: block_table {bt:?} is the IDENTITY — a kernel ignoring it \
entirely would return the same bytes, so the record would attest \
nothing about paging"
));
}
if cl
.iter()
.any(|&c| c as usize > max_bps * block_size || (c as usize) < sq)
{
problems.push(format!(
"{dtypes:?}: context_lens {cl:?} outside [sq={sq}, capacity={}]",
max_bps * block_size
));
}
let inv = CpuInvoker::new(probe.out_dtype, probe.out_shape.clone())
.with_params(probe.params.clone());
let Ok(out) = inv.invoke(entry, &probe.inputs) else {
problems.push(format!("{dtypes:?}: probe did not invoke"));
continue;
};
checked += 1;
let mut ident = probe.inputs.clone();
let identity: Vec<u32> = (0..bt.len() as u32).collect();
ident[3].bytes = bytemuck::cast_slice(&identity).to_vec();
match inv.invoke(entry, &ident) {
Ok(out_ident) if out_ident.bytes == out.bytes => problems.push(format!(
"{dtypes:?}: remapping the block table {bt:?} -> {identity:?} did not \
change the output — the kernel is NOT dereferencing block_table, and \
every paged record would be bit-stable regardless"
)),
Ok(_) => {}
Err(e) => problems.push(format!("{dtypes:?}: identity-table control: {e:?}")),
}
let other = build_primitive_probe(op, dtypes, seed ^ 0xA5A5_A5A5)
.expect("a recipe that built once must build again");
if other.inputs[3].bytes != probe.inputs[3].bytes
|| other.inputs[4].bytes != probe.inputs[4].bytes
{
problems.push(format!(
"{dtypes:?}: the seed changed an INDEX operand. A generated index is \
not merely arbitrary — it is potentially invalid, and its validity is \
what makes this probe mean anything."
));
}
if other.inputs[0].bytes == probe.inputs[0].bytes {
problems.push(format!(
"{dtypes:?}: a different seed left q unchanged, so the response check \
below proves nothing"
));
continue;
}
let out2 = inv
.invoke(entry, &other.inputs)
.expect("second invocation of a probe that already ran");
if out2.bytes == out.bytes {
problems.push(format!(
"{dtypes:?}: different q/k/v, IDENTICAL output — the kernel is not \
reading them, and it would be bit-stable anyway"
));
}
}
assert_eq!(
checked, 8,
"expected 8 PagedAttn registrations to invoke (4 dtypes x \
{{with, without}} alibi_slopes); got {checked}"
);
assert!(problems.is_empty(), "{problems:?}");
}
#[test]
fn gap_228_what_the_production_fill_still_supplies() {
use crate::fused::PrecisionGuarantee;
let dir =
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../docs/kernel-contracts/cpu");
let mut contract = crate::kernel::KernelBindingTable::new();
let mut fused = crate::fused::FusedKernelRegistry::new();
let mut n_contracts = 0usize;
for e in std::fs::read_dir(&dir).unwrap_or_else(|e| panic!("read {dir:?}: {e}")) {
let path = e.expect("dir entry").path();
if path.extension().and_then(|x| x.to_str()) != Some("md") {
continue;
}
let Ok(text) = std::fs::read_to_string(&path) else {
continue;
};
let Ok(provider) = crate::fkc::import_bundle_str(&text, &crate::fkc::CpuLinkRegistry)
else {
continue;
};
if provider.register_into(&mut contract, &mut fused).is_ok() {
n_contracts += 1;
}
}
assert!(
n_contracts >= 10,
"only {n_contracts} CPU contracts registered — the delta below would be \
measured against a subset and would overstate what the fill supplies"
);
let mut prod = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut prod);
type Key = (String, Vec<DType>);
let keys = |t: &crate::kernel::KernelBindingTable| -> std::collections::HashMap<Key, PrecisionGuarantee> {
t.iter_entries()
.filter(|(_, _, b, _)| *b == BackendId::Cpu)
.map(|(op, dt, _, e)| ((format!("{op:?}"), dt.to_vec()), e.precision))
.collect()
};
let c = keys(&contract);
let p = keys(&prod);
let unaudited = PrecisionGuarantee::UNAUDITED.notes;
let mut orphans: Vec<&Key> = p.keys().filter(|k| !c.contains_key(*k)).collect();
orphans.sort_by_key(|k| format!("{} {:?}", k.0, k.1));
let mut missing: Vec<&Key> = c.keys().filter(|k| !p.contains_key(*k)).collect();
missing.sort_by_key(|k| format!("{} {:?}", k.0, k.1));
let mut filled_by_op: std::collections::BTreeMap<String, usize> =
std::collections::BTreeMap::new();
for k in &orphans {
if p[*k].notes != unaudited {
*filled_by_op.entry(k.0.clone()).or_default() += 1;
}
}
let mut disagree: Vec<String> = Vec::new();
for (k, cv) in &c {
if let Some(pv) = p.get(k)
&& cv.notes != pv.notes
{
disagree.push(format!("{} {:?}", k.0, k.1));
}
}
disagree.sort();
println!("[gap-228] contract-derived CPU entries : {}", c.len());
println!("[gap-228] production CPU entries : {}", p.len());
println!("[gap-228] production-only (orphans) : {}", orphans.len());
println!("[gap-228] contract-only (missing) : {}", missing.len());
println!(
"[gap-228] orphans the FILL upgrades : {}",
filled_by_op.values().sum::<usize>()
);
for (op, n) in &filled_by_op {
println!("[gap-228] {n:>3} {op}");
}
println!(
"[gap-228] shared entries that DISAGREE : {}",
disagree.len()
);
for d in disagree.iter().take(20) {
println!("[gap-228] {d}");
}
assert!(
c.len() > 100 && p.len() > 100,
"one of the tables is nearly empty ({} contract, {} production), so every \
number above is measured against nothing",
c.len(),
p.len()
);
}
#[test]
fn gap_226_split_of_the_entries_that_declare_nothing() {
use crate::fkc::verify::VerificationLedger;
use crate::fused::PrecisionGuarantee;
let dir =
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../docs/kernel-contracts/cpu");
let mut table = crate::kernel::KernelBindingTable::new();
let mut fused = crate::fused::FusedKernelRegistry::new();
let mut n_contracts = 0usize;
for e in std::fs::read_dir(&dir).unwrap_or_else(|e| panic!("read {dir:?}: {e}")) {
let path = e.expect("dir entry").path();
if path.extension().and_then(|x| x.to_str()) != Some("md") {
continue;
}
let Ok(text) = std::fs::read_to_string(&path) else {
continue;
};
let Ok(provider) = crate::fkc::import_bundle_str(&text, &crate::fkc::CpuLinkRegistry)
else {
continue;
};
if provider.register_into(&mut table, &mut fused).is_ok() {
n_contracts += 1;
}
}
assert!(
n_contracts >= 10,
"only {n_contracts} CPU contracts registered — the split below would be over \
a subset and would read as a smaller problem than it is"
);
let ledger = VerificationLedger::embedded();
let unaudited_notes = PrecisionGuarantee::UNAUDITED.notes;
let (mut total, mut nothing, mut both, mut bit_only, mut ulp_only, mut neither) =
(0usize, 0usize, 0usize, 0usize, 0usize, 0usize);
let mut neither_by_op: Vec<(String, usize)> = Vec::new();
for (op, dtypes, backend, entry) in table.iter_entries() {
total += 1;
if entry.precision.notes != unaudited_notes {
continue;
}
nothing += 1;
let rev = entry.kernel_revision_hash;
let bs = ledger.has_pass(backend, dtypes, rev, "bit_stable_on_same_hardware");
let ulp = ledger.has_pass(backend, dtypes, rev, "max_ulp");
match (bs, ulp) {
(true, true) => both += 1,
(true, false) => bit_only += 1,
(false, true) => ulp_only += 1,
(false, false) => {
neither += 1;
let name = format!("{op:?}");
match neither_by_op.iter_mut().find(|(n, _)| *n == name) {
Some((_, c)) => *c += 1,
None => neither_by_op.push((name, 1)),
}
}
}
}
neither_by_op.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
println!("[gap-226] population: contract-derived CPU table, {total} entries");
println!("[gap-226] declaring nothing machine-checkable: {nothing}");
println!("[gap-226] ledger already holds BOTH claims : {both}");
println!("[gap-226] ledger holds bit_stable only : {bit_only}");
println!("[gap-226] ledger holds max_ulp only : {ulp_only}");
println!("[gap-226] ledger holds NEITHER : {neither}");
println!(
"[gap-226] STARTABLE NOW (name exists, evidence exists, it is a contract edit): {}",
both + bit_only + ulp_only
);
println!("[gap-226] NOT YET (no record — needs a probe, a reference, or a NAME), by op:");
for (name, c) in &neither_by_op {
println!("[gap-226] {c:>3} {name}");
}
assert_eq!(
nothing, 0,
"expected ZERO entries still declaring nothing after GAP-228's flip (8 before, PagedAttn's 8 flipped). {nothing} means a declaration was not evidenced by the record it was supposed to rest on, or a kernel revision moved and silently un-earned one."
);
assert_eq!(
total - nothing,
623,
"expected all 623 contract-derived entries backed WITHOUT the fill. This table is built by `register_into`, which does not apply `fill_unset_cpu_precision` — so this count IS the post-fill-retirement number for these entries, and a drop means the backing did not actually move from the fill to contract + record."
);
assert_eq!(
neither, nothing,
"every entry still declaring nothing must be one with NO ledger record — if any had a record, it was flippable and GAP-228's generator skipped it"
);
assert_eq!(
both + bit_only + ulp_only + neither,
nothing,
"the four buckets do not partition the entries that declare nothing"
);
assert!(
total > 100,
"only {total} contract-derived CPU entries — `nothing == 0` is trivially \
true of a table this small, so the ratchet above would pass while \
measuring nothing"
);
}
#[test]
fn the_cpu_max_ulp_sweep_accounts_for_every_registration_and_fabricates_nothing() {
let (records, log) = run_cpu_max_ulp_verification();
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let cpu_entries = table
.iter_entries()
.filter(|(_, _, backend, _)| *backend == BackendId::Cpu)
.count();
assert_eq!(
log.len(),
cpu_entries,
"the sweep logged {} attempts for {cpu_entries} CPU registrations — every entry must be accounted for, including the ones with no exact reference",
log.len()
);
let passes = log.iter().filter(|a| a.outcome == "pass").count();
assert_eq!(
records.len(),
passes,
"banked {} max_ulp records against {passes} observed passes",
records.len()
);
let mut buckets: std::collections::BTreeMap<&'static str, usize> =
std::collections::BTreeMap::new();
let mut unclassified: Vec<String> = Vec::new();
for a in &log {
match outcome_bucket(&a.outcome) {
Some(b) => *buckets.entry(b).or_default() += 1,
None => unclassified.push(a.outcome.clone()),
}
}
println!("[gap-225] CPU max_ulp:0 sweep over {cpu_entries} registrations:");
for (name, n) in &buckets {
println!("[gap-225] {n:>4} {name}");
}
for a in log.iter().filter(|a| a.outcome.starts_with("fail:")) {
println!("[gap-225] FAIL {} {:?}: {}", a.op_name, a.dtypes, a.outcome);
}
assert!(
unclassified.is_empty(),
"these outcomes match no bucket: {unclassified:?}. Under the old remainder \
they were counted and PRINTED as invoke errors, because the catch-all \
carried that name."
);
assert_eq!(
buckets.values().sum::<usize>(),
log.len(),
"the outcome buckets do not partition the log"
);
assert!(
!records.is_empty(),
"not one CPU registration earned max_ulp:0 out of {cpu_entries} — that is a broken harness, not a coverage result: the assertions above would all hold"
);
}
#[test]
fn the_fused_and_primitive_passes_do_not_collide_on_the_ledger_key() {
let (fused, _) = run_cpu_verification();
let (prim, _) = run_cpu_primitive_verification();
assert!(
!fused.is_empty() && !prim.is_empty(),
"both populations must be non-empty or this check is vacuous (fused {}, primitive {})",
fused.len(),
prim.len()
);
let key = |r: &LedgerRecord| {
(
r.backend.clone(),
r.dtypes.clone(),
r.kernel_revision_hash,
r.claim.clone(),
)
};
let a = &fused[0];
let mut b = a.clone();
b.kernel_ref = format!("{}-synthetic", a.kernel_ref);
assert!(
key(a) == key(&b) && a.kernel_ref != b.kernel_ref,
"the collision predicate cannot recognise two records that differ ONLY in kernel_ref — it would report zero collisions no matter what the two passes produced"
);
let mut collisions: Vec<String> = Vec::new();
for f in &fused {
for p in &prim {
if key(f) == key(p) && f.kernel_ref != p.kernel_ref {
collisions.push(format!(
"{:?} rev={} claimed by both {:?} (fused) and {:?} (primitive)",
f.dtypes, f.kernel_revision_hash, f.kernel_ref, p.kernel_ref
));
}
}
}
assert!(
collisions.is_empty(),
"the two CPU passes produce {} colliding ledger key(s); concatenating their records lets `upsert` drop one verdict and file the other under the wrong kernel_ref:
{}",
collisions.len(),
collisions.join("
")
);
}
#[test]
fn the_cpu_primitive_sweep_accounts_for_every_registration_and_fabricates_nothing() {
let (records, log) = run_cpu_primitive_verification();
let mut table = crate::kernel::KernelBindingTable::new();
crate::dispatch::register_cpu_kernels(&mut table);
let cpu_entries = table
.iter_entries()
.filter(|(_, _, backend, _)| *backend == BackendId::Cpu)
.count();
assert_eq!(
log.len(),
cpu_entries,
"the sweep logged {} attempts for {cpu_entries} CPU registrations — every entry must be accounted for, including the ones with no probe recipe. A silent skip is how a coverage number becomes larger than the thing it measures.",
log.len()
);
let passes = log.iter().filter(|a| a.outcome == "pass").count();
assert_eq!(
records.len(),
passes,
"banked {} ledger records against {passes} observed passes. These must be equal in BOTH directions: more records than passes is a fabricated claim, fewer is a measurement thrown away.",
records.len()
);
assert!(
cpu_entries > 100,
"only {cpu_entries} CPU registrations found — `register_cpu_kernels` is the production path and carries several hundred. Both assertions above pass vacuously against a table this small."
);
assert!(
!records.is_empty(),
"not one CPU primitive earned `bit_stable_on_same_hardware` out of {cpu_entries} registrations. That is not a coverage result, it is a broken harness — the assertions above would both hold."
);
let mut buckets: std::collections::BTreeMap<&'static str, usize> =
std::collections::BTreeMap::new();
let mut unclassified: Vec<String> = Vec::new();
for a in &log {
match outcome_bucket(&a.outcome) {
Some(b) => *buckets.entry(b).or_default() += 1,
None => unclassified.push(a.outcome.clone()),
}
}
let _no_recipe = buckets.get("no_recipe").copied().unwrap_or(0);
let _failed = buckets.get("fail").copied().unwrap_or(0);
println!("[gap-207] CPU primitive bit-stability sweep over {cpu_entries} registrations:");
for (name, n) in &buckets {
println!("[gap-207] {n:>4} {name}");
}
assert!(
unclassified.is_empty(),
"these outcomes match no bucket: {unclassified:?}"
);
let mut by_op: Vec<(String, usize)> = Vec::new();
for a in log
.iter()
.filter(|a| a.outcome.starts_with("unverified: no probe recipe"))
{
match by_op.iter_mut().find(|(n, _)| *n == a.op_name) {
Some((_, c)) => *c += 1,
None => by_op.push((a.op_name.clone(), 1)),
}
}
by_op.sort_by(|x, y| y.1.cmp(&x.1).then(x.0.cmp(&y.0)));
println!(
"[gap-207] {} distinct ops lack a probe recipe, by registration count:",
by_op.len()
);
for (name, c) in &by_op {
println!("[gap-207] {name} x{c}");
}
let unlisted_inplace: Vec<&str> = log
.iter()
.filter(|a| a.outcome.starts_with("unverified: no probe recipe"))
.map(|a| a.op_name.as_str())
.filter(|n| n.ends_with("Inplace"))
.collect();
assert!(
unlisted_inplace.is_empty(),
"these in-place ops have no probe recipe: {unlisted_inplace:?}. The `*Inplace` arm is a hand-written variant list, so a new one falls through `_ => None` silently — add it there rather than widening this assertion."
);
assert_eq!(
buckets.values().sum::<usize>(),
log.len(),
"the outcome buckets do not partition the log"
);
}
#[test]
#[ignore = "re-seeding tool: writes docs/kernel-contracts/.fkc-verified-ledger.json; run manually via `cargo test -p fuel-dispatch seed_cpu_verified_ledger -- --ignored --nocapture` to regenerate the ledger. The verified ledger is committed; the default suite must not rewrite it."]
fn seed_cpu_verified_ledger() {
let (fused_records, fused_log) = run_cpu_verification();
let (prim_records, prim_log) = run_cpu_primitive_verification();
let (ulp_records, ulp_log) = run_cpu_max_ulp_verification();
for (tag, log) in [
("fused", &fused_log),
("primitive", &prim_log),
("max_ulp", &ulp_log),
] {
for attempt in log.iter() {
println!(
"[gap-207/{tag}] {} {:?} (rev={}): {}",
attempt.op_name, attempt.dtypes, attempt.kernel_revision_hash, attempt.outcome,
);
}
}
for (tag, recs, log) in [
("fused", &fused_records, &fused_log),
("primitive", &prim_records, &prim_log),
("max_ulp", &ulp_records, &ulp_log),
] {
println!(
"[gap-207/{tag}] {} passed, {} unverified/failed, {} total attempts",
recs.len(),
log.iter().filter(|a| a.outcome != "pass").count(),
log.len(),
);
}
assert!(
!fused_records.is_empty(),
"expected at least one CPU FUSED op to empirically verify bit-stable; got 0 — see log above",
);
assert!(
!prim_records.is_empty(),
"expected at least one CPU PRIMITIVE op to empirically verify bit-stable; got 0 — see log above",
);
let mut records = fused_records;
records.extend(prim_records);
records.extend(ulp_records);
let summary = super::super::ledger::write_merged_ledger(&records);
println!(
"[task-4.5b] merged {} fresh CPU record(s) into {} existing -> {} total, written to {}",
summary.fresh,
summary.before,
summary.after,
summary.path.display(),
);
}
}