Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion contracts/apr-cli-operations-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ falsification_tests:
prediction: print_json and print_reverse_lookup complete on every table and report launches/layer x layers
test: commands::ptx_map::tests::print_json_and_reverse_lookup_cover_every_branch
if_fails: ptx-map JSON or reverse-lookup output panics or miscounts launches
- id: FALSIFY-OPS-012
rule: hex --json lists filtered tensors, stats only on request
prediction: output_json_v2 succeeds with and without stats and skips unknown tensor names
test: commands::hex::tests::output_json_v2_lists_filtered_tensors_with_and_without_stats
if_fails: hex JSON output errors on a valid APR file or invents tensors
kani_harnesses:
- id: KANI-OPS-001
obligation: ReadOnly commands have no side effects
Expand Down Expand Up @@ -324,7 +329,7 @@ qa_gate:
- progress_reporting
- concurrent_model_access
- tokenizer_consistency
pass_criteria: All 11 falsification tests pass
pass_criteria: All 12 falsification tests pass
falsification: >
Run read-only command with filesystem watcher to detect mutations.
Force inference error and measure GPU memory leak.
Expand Down
8 changes: 7 additions & 1 deletion contracts/apr-cpu-vs-gpu-output-parity-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,12 @@ falsification_tests:
test: "bash scripts/check_model_ladder.sh (reads evidence/dogfood/models/<version>/{lambda,gx10}.json written by scripts/model_ladder.sh)"
if_fails: "an architecture the release claims silently runs on the CPU — 0.68.1 shipped dense Qwen3 this way while the qwen2.5 control was green on the same binary (#3413, EPIC #3477)"

- id: FALSIFY-CPU-GPU-016
rule: "A CUDA load failure that is the parity gate is refused when the GPU was forced, and only then"
prediction: "on_cuda_load_error returns Err (with the measured cosine) for a forced gate failure, Ok(true) for an unforced one, and Ok(false) for any non-gate error"
test: "cargo test -p apr-cli --lib on_cuda_load_error"
if_fails: "a forced --gpu silently downgrades to CPU after a parity-gate failure, or an unrelated CUDA error is swallowed as a gate verdict (R-0b, #2971)"

proof_obligations:
- id: ACVGOP-INV-001
type: invariant
Expand Down Expand Up @@ -625,5 +631,5 @@ qa_gate:
- no_fallback_line_on_claimed_backend
- golden_output_gpu_per_rung
- both_required_hosts
pass_criteria: "All 15 falsification tests pass, and scripts/check_model_ladder.sh exits 0 (FALSIFY-CPU-GPU-015 is the ladder itself)"
pass_criteria: "All 16 falsification tests pass, and scripts/check_model_ladder.sh exits 0 (FALSIFY-CPU-GPU-015 is the ladder itself)"
falsification: "plant backends.cuda.fallback=true in a receipt → exit 1 (scripts/lib/model_ladder_cases/red-fallback)"
2 changes: 1 addition & 1 deletion contracts/apr-fail-closed-structural-beat-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ proof_obligations:
type: invariant

falsification_tests:
- id: FALSIFY-BEAT-STRUCT-FAIL-CLOSED
- id: FALSIFY-BEAT-STRUCT-FAIL-001
description: >
FALSE if apr ACCEPTS any cross-tensor-inconsistent model (vocab mismatch or
hidden-dim mismatch) — the structural garbage the incumbents load silently —
Expand Down
7 changes: 6 additions & 1 deletion contracts/multinomial-head-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@ falsification_tests:
prediction: Two identical fits produce bitwise-identical stored f32 coefficients and byte-identical canonical JSON
test: cargo test -p aprender-core --features setfit --lib two_identical_fits_produce_bitwise_identical_f32_weights
if_fails: Randomness or a wall-clock field entered the fit path, breaking the reproducibility record
- id: FALSIFY-MH-013
rule: A head loaded from stored coefficients validates its shape, and its error text and lambda relation are exact
prediction: from_stored_coefficients rejects every malformed shape with the matching HeadInputError; SklearnEquivalentC resolves to 1/(2*C*n); predict guards NotFitted and FeatureDimMismatch
test: cargo test -p aprender-core --lib tests_multinomial_head_edges
if_fails: A corrupt stored head loads silently, or the C-to-lambda relation drifts from sklearn
kani_harnesses_note: >
NOT EXECUTED. No #[kani::proof] harness exists anywhere in crates/ and cargo-kani is
not installed repo-wide, so every entry below is a DECLARED obligation, not a
Expand Down Expand Up @@ -386,5 +391,5 @@ qa_gate:
- intercept_penalty_exclusion
- convergence_error_mapping
- logit_finiteness
pass_criteria: All 12 falsification tests pass, including the two in-band negative controls (FALSIFY-MH-002, FALSIFY-MH-006)
pass_criteria: All 13 falsification tests pass, including the two in-band negative controls (FALSIFY-MH-002, FALSIFY-MH-006)
falsification: Substitute lambda*W for 2*lambda*W in the gradient, or 1/(C*n) for 1/(2*C*n) in the relation
26 changes: 26 additions & 0 deletions crates/apr-cli/src/commands/hex_06.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,30 @@ mod tests {
include!("hex_options_detect.rs");
include!("make.rs");
include!("tests_blocks_and_slices.rs");

/// FALSIFY-OPS-012: `hex --json` on an APR file lists each filtered tensor,
/// with stats only when asked, and silently skips names that are not in the file.
#[test]
fn output_json_v2_lists_filtered_tensors_with_and_without_stats() {
use aprender::format::v2::{AprV2Metadata, AprV2Writer};

let mut writer = AprV2Writer::new(AprV2Metadata::new("hex-json"));
let data: Vec<u8> = [1.0f32, 2.0, 3.0, 4.0]
.iter()
.flat_map(|f| f.to_le_bytes())
.collect();
writer.add_tensor("a.weight", TensorDType::F32, vec![2, 2], data);
let mut bytes = Vec::new();
writer.write_to(&mut bytes).expect("write APR");
let reader = AprV2Reader::from_bytes(&bytes).expect("read APR");

assert!(output_json_v2(&reader, &["a.weight"], 2, true).is_ok());
assert!(output_json_v2(&reader, &["a.weight"], 0, false).is_ok());
assert!(output_json_v2(&reader, &["missing"], 4, true).is_ok());
assert!(output_json_v2(&reader, &[], 4, false).is_ok());
// the statistics the stats branch serialises
let (min, max, mean, _std) = compute_stats(&[1.0, 2.0, 3.0, 4.0]);
assert!((min - 1.0).abs() < f32::EPSILON && (max - 4.0).abs() < f32::EPSILON);
assert!((mean - 2.5).abs() < 1e-6);
}
}
35 changes: 35 additions & 0 deletions crates/apr-cli/src/commands/parity_admission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,38 @@ mod sentinel_tests {
}
}
}

#[cfg(test)]
mod on_cuda_load_error_tests {
use super::*;

const GATE_MSG: &str = "PARITY-GATE FAILED: GPU computes a DIFFERENT function than CPU.\n\
Cosine similarity: 0.950800 (required: \u{2265}0.98)";

#[test]
fn unrelated_cuda_error_is_not_ours_whether_forced_or_not() {
assert_eq!(on_cuda_load_error("OOM: out of VRAM", true), Ok(false));
assert_eq!(on_cuda_load_error("OOM: out of VRAM", false), Ok(false));
}

#[test]
fn forced_gate_failure_is_refused_with_the_measured_cosine() {
let err = on_cuda_load_error(GATE_MSG, true).expect_err("forced + gate fail must refuse");
assert!(err.starts_with("parity gate refused the GPU: "), "{err}");
assert!(err.contains("cosine=0.9508"), "{err}");
assert!(err.contains("threshold=0.98"), "{err}");
}

#[test]
fn unforced_gate_failure_is_admitted_for_cpu_fallback() {
assert_eq!(on_cuda_load_error(GATE_MSG, false), Ok(true));
}

#[test]
fn unparseable_gate_message_still_refuses_when_forced() {
// Marker present but no cosine line: NaN verdict must not read as a pass.
let err = on_cuda_load_error("PARITY-GATE FAILED: details lost", true)
.expect_err("a gate failure with no numbers is still a failure");
assert!(err.contains("parity FAILED"), "{err}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -688,3 +688,6 @@ fn falsify_multinomial_001_fixture_fit_fails_loudly_without_budget() {
"expected NotConverged, got {err:?}"
);
}

#[path = "tests_multinomial_head_edges.rs"]
mod tests_multinomial_head_edges;
Loading
Loading