diff --git a/crates/jc/examples/w5_trigger_check.rs b/crates/jc/examples/w5_trigger_check.rs index ec95ff95b..01dc8268f 100644 --- a/crates/jc/examples/w5_trigger_check.rs +++ b/crates/jc/examples/w5_trigger_check.rs @@ -68,11 +68,20 @@ fn main() { ); // The longest path this workspace's own certification legs construct. - let longest_in_tree = 4609usize; // W2 triangle at 1536 pts/segment, 3 segments - println!( - "\n longest path constructed anywhere in-tree today: {longest_in_tree} \ - (the W2 depth-infinity converse leg)" - ); + // DERIVED, never retyped. Each battery exports the length of the longest + // path it builds, so raising a resolution anywhere re-arms this check + // automatically. The previous revision hardcoded 4609 with a comment + // explaining where it came from — which is exactly how a measurement + // that later moves keeps reporting its old value, and a trigger that + // reports a stale value is worse than no trigger. + let longest_in_tree = + jc::hambly_lyons::LONGEST_PATH_POINTS.max(jc::solver_order::LONGEST_PATH_POINTS); + let owner = if jc::hambly_lyons::LONGEST_PATH_POINTS >= jc::solver_order::LONGEST_PATH_POINTS { + "the W2 depth-infinity converse leg" + } else { + "the W3 solver-order battery" + }; + println!("\n longest path constructed anywhere in-tree today: {longest_in_tree} ({owner})"); let fired = longest_in_tree as f64 >= mem_len.min(time_len); println!(" TRIGGER FIRED: {fired}"); if !fired { diff --git a/crates/jc/src/hambly_lyons.rs b/crates/jc/src/hambly_lyons.rs index 90773288b..2f399c271 100644 --- a/crates/jc/src/hambly_lyons.rs +++ b/crates/jc/src/hambly_lyons.rs @@ -146,6 +146,12 @@ mod active { // sweeps: `examples/w2_refinement_sweep.rs` (convergence) and // `examples/w2_area_edge.rs` (the converse law and its edge). const PER_SEG: usize = 1536; + /// Points in the longest path this leg constructs: the converse triangle + /// is three resampled segments plus the closing point. Exported so the W5 + /// trigger check DERIVES the in-tree maximum instead of restating it — + /// a measured value retyped into a second file is one that goes stale + /// silently, and the trigger's whole job is to notice when it has not. + pub const LONGEST_PATH_POINTS: usize = 3 * PER_SEG + 1; /// Forward pairs. The forward statistic is population-stable — the /// refinement sweep measured max deviation 5.005e-6 at both 12 and 25 /// pairs — so a small sample is a faithful one here. @@ -415,6 +421,11 @@ mod active { } } +/// Points in the longest path this module constructs — see the constant's +/// own doc in the gated implementation. +#[cfg(feature = "hambly-lyons")] +pub use active::LONGEST_PATH_POINTS; + #[cfg(feature = "hambly-lyons")] pub fn prove() -> PillarResult { active::prove() diff --git a/crates/jc/src/solver_order.rs b/crates/jc/src/solver_order.rs index b7c7cbae9..134ff8eba 100644 --- a/crates/jc/src/solver_order.rs +++ b/crates/jc/src/solver_order.rs @@ -49,6 +49,9 @@ mod active { type P2 = [f64; 2]; const M: usize = 2048; + /// Points in the longest path this battery constructs (see the sibling + /// constant in `hambly_lyons` for why it is exported rather than retyped). + pub const LONGEST_PATH_POINTS: usize = M + 1; /// Super-period windows for these fixtures (period ~ 2π·M/ω micro-steps). const WINDOWS: [usize; 3] = [32, 48, 64]; /// Area-register bit depths for the carrier-fidelity leg. @@ -276,6 +279,11 @@ mod active { } } +/// Points in the longest path this module constructs — see the constant's +/// own doc in the gated implementation. +#[cfg(feature = "hambly-lyons")] +pub use active::LONGEST_PATH_POINTS; + #[cfg(feature = "hambly-lyons")] pub fn prove() -> PillarResult { active::prove()