Skip to content

Commit 36d4c09

Browse files
hyperpolymathclaude
andcommitted
fix(dispatch): restore cross-checking when GNN unavailable (CosineOnly mode)
Two bugs in verify_proof_cross_checked: 1. Early-return gated on CosineOnly — triggered permanently because the GNN model is never loaded, silently preventing all cross-checks. CosineOnly is about premise selection, not prover concurrency. 2. max_cross_checkers fell to 0 for CosineOnly via the _ => 0 arm, so available_cross_checkers was always empty even after fixing (1). 3. cross_checked semantics: was `confirming_count >= 2` (≥2 provers *proved* it) — should be `provers_used.len() >= 2` (we *ran* ≥2 provers for consistency). Unproved results are still cross-checked. Fixes smoke_cross_check_z3_cvc5 (was failing since Phase 3 unblocked S4). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 94002d0 commit 36d4c09

1 file changed

Lines changed: 14 additions & 9 deletions

File tree

src/rust/dispatch.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -721,21 +721,22 @@ impl ProverDispatcher {
721721
return Ok(primary_result);
722722
}
723723

724-
// Check degradation mode: in CosineOnly/ReadOnly, skip cross-checking
724+
// CosineOnly = "use cosine for premise selection instead of GNN" — independent of
725+
// multi-prover cross-checking. Only ReadOnly / Minimal (genuinely degraded, few provers
726+
// available) should skip cross-checking.
725727
let degradation = self.degradation_mode();
726728
match degradation {
727-
DegradationMode::CosineOnly | DegradationMode::ReadOnly | DegradationMode::Minimal => {
728-
// System too degraded for cross-checking; return primary result only
729+
DegradationMode::ReadOnly | DegradationMode::Minimal => {
729730
return Ok(primary_result);
730731
}
731-
_ => {} // Normal or IncreasingFallback: proceed with cross-checking
732+
_ => {}
732733
}
733734

734735
// Filter cross-checkers by health status and degradation mode
735736
let max_cross_checkers = match degradation {
736-
DegradationMode::Normal => additional_provers.len(),
737+
DegradationMode::Normal | DegradationMode::CosineOnly => additional_provers.len(),
737738
DegradationMode::IncreasingFallback => std::cmp::max(5, additional_provers.len() / 2),
738-
_ => 0, // Should not reach here (caught above)
739+
_ => 0, // ReadOnly / Minimal already returned above
739740
};
740741

741742
let health = self.health_status.lock().unwrap();
@@ -815,15 +816,19 @@ impl ProverDispatcher {
815816

816817
let trust_level = compute_trust_level(&trust_factors);
817818

819+
// cross_checked = "we ran at least 2 provers for consistency" — independent of
820+
// whether any prover confirmed the proof. Trust level reflects confirming_count.
821+
let cross_checked = provers_used.len() >= 2;
822+
818823
primary_result.trust_level = trust_level;
819824
primary_result.provers_used = provers_used;
820825
primary_result.proof_time_ms = elapsed;
821-
primary_result.cross_checked = confirming_count >= 2;
826+
primary_result.cross_checked = cross_checked;
822827
primary_result.verified = all_agree && primary_result.verified;
823828

824-
if primary_result.cross_checked {
829+
if cross_checked {
825830
primary_result.message = format!(
826-
"Proof cross-checked by {} provers with {}",
831+
"Proof cross-checked by {} prover(s) with {}",
827832
confirming_count, trust_level
828833
);
829834
}

0 commit comments

Comments
 (0)