Index: trunk/BNC/src/bncantex.cpp
===================================================================
--- trunk/BNC/src/bncantex.cpp	(revision 10948)
+++ trunk/BNC/src/bncantex.cpp	(revision 10951)
@@ -356,12 +356,13 @@
   const double MAX_YAW_RATE = 0.25 * M_PI / 180.0; // [rad/s], approximate
 
-  // A genuine yaw-fixed window (gapless data) only ever lasts a few
-  // minutes around the orbit noon/midnight point - see the width
-  // estimate in the comment above. If the stored frozen value is much
-  // older than that, it is more likely stale (e.g. a stream outage, a
-  // maneuver-flagged-unhealthy period, or a brief eclipse passage spanned
-  // the gap) than a still-valid freeze, so fall back to the current
-  // nominal value instead of trusting it indefinitely.
-  const double MAX_FREEZE_AGE = 1800.0 / 86400.0; // 30 minutes, in days
+  // This bounds the gap BETWEEN CONSECUTIVE CALLS for a given satellite
+  // (not how long the freeze itself has lasted - a real low-beta passage
+  // can legitimately stay frozen far longer than this). If there was no
+  // call for longer than this, something else interrupted normal epoch-by-
+  // epoch processing (a stream outage, a maneuver-flagged-unhealthy
+  // period, ...), so the stored frozen value is more likely stale than a
+  // still-valid freeze, and we fall back to the current nominal value
+  // instead of trusting it indefinitely.
+  const double MAX_CALL_GAP = 1800.0 / 86400.0; // 30 minutes, in days
 
   // Inertial-consistent velocity (xSat, vSat are Earth-fixed; remove the
@@ -406,18 +407,17 @@
 
   t_glonassYaw& st = _glonassYaw[prn];
+  double callGap = st.valid ? (Mjd - st.lastCallMjd) : 0.0;
   double psiEff;
   if (psiRate > MAX_YAW_RATE) {
-    if (!st.valid || (Mjd - st.lastMjd) > MAX_FREEZE_AGE) {
-      if (st.valid) { // i.e. it was the staleness bound, not cold-start
+    if (!st.valid || callGap > MAX_CALL_GAP) {
+      if (st.valid) { // i.e. it was a genuine gap, not cold-start
         _glonassYawLog += QString().asprintf(
           "%s glonassYaw STALE-RESET  Mjd=%.6f beta=%6.3f mu=%7.2f rate=%6.3f"
-          " old=%7.2f new=%7.2f age=%.1fmin\n",
+          " old=%7.2f new=%7.2f gap=%.1fmin\n",
           prn.toLatin1().data(), Mjd, beta*180.0/M_PI, mu*180.0/M_PI,
           psiRate*180.0/M_PI, st.yaw*180.0/M_PI, psiNom*180.0/M_PI,
-          (Mjd-st.lastMjd)*1440.0);
-      }
-      st.yaw     = psiNom; // no prior history, or it is too old to trust
-      st.lastMjd = Mjd;
-      st.valid   = true;
+          callGap*1440.0);
+      }
+      st.yaw = psiNom; // no prior history, or the gap is too long to trust it
     }
     if (!st.fixed) {
@@ -439,9 +439,9 @@
       st.fixed = false;
     }
-    st.yaw     = psiNom;
-    st.lastMjd = Mjd;
-    st.valid   = true;
-    psiEff     = psiNom;
-  }
+    st.yaw = psiNom;
+    psiEff = psiNom;
+  }
+  st.lastCallMjd = Mjd; // update on every call, fixed or not, to detect gaps
+  st.valid       = true;
 
   return psiEff;
