Index: trunk/BNC/src/combination/bnccomb.cpp
===================================================================
--- trunk/BNC/src/combination/bnccomb.cpp	(revision 10953)
+++ trunk/BNC/src/combination/bnccomb.cpp	(revision 10954)
@@ -1189,10 +1189,40 @@
     corr->_eph->setClkCorr(dynamic_cast<const t_clkCorr*>(&clkCorr));
     corr->_eph->setOrbCorr(dynamic_cast<const t_orbCorr*>(&orbCorr));
+
+    /* TEMPORARY DIAGNOSTIC: dump the exact orbit/clock correction content
+    // being used for this PRN right before getCrd() applies it - adjust
+    // the PRN below to whichever satellite is showing the anomaly.
+    if (corr->_prn.startsWith("R08")) {
+      const t_orbCorr* oc = corr->_eph->orbCorr();
+      const t_clkCorr* cc = corr->_eph->clkCorr();
+      emit newMessage(QString().asprintf(
+        "bncComb: DIAG %s Mjd=%.6f IOD=%u TOC=%.3f bcepAge=%.2f orbT=%.3f orbAge=%.2f xr=%.4f/%.4f/%.4f"
+        " dotXr=%.6f/%.6f/%.6f clkT=%.3f clkAge=%.2f dClk=%.6f dotDClk=%.6f",
+        corr->_prn.toLatin1().data(),
+        epoTime.mjd() + epoTime.daysec()/86400.0,
+        corr->_eph->IOD(), corr->_eph->TOC().daysec(), epoTime - corr->_eph->TOC(),
+        oc->_time.daysec(), epoTime - oc->_time,
+        oc->_xr[0], oc->_xr[1], oc->_xr[2],
+        oc->_dotXr[0], oc->_dotXr[1], oc->_dotXr[2],
+        cc->_time.daysec(), epoTime - cc->_time,
+        cc->_dClk, cc->_dotDClk).toLatin1(), false);
+    }
+  */
     if (corr->_eph->getCrd(epoTime, xc, vv, true) != success) {
+      /*
+      if (corr->_prn.startsWith("R08")) {
+        emit newMessage(("bncComb: DIAG " + corr->_prn.mid(0,3) + " getCrd FAILED").toLatin1(), false);
+      }
+      */
       delete corr;
       it.remove();
       continue;
     }
-
+    /*
+    else if (corr->_prn.startsWith("R08")) {
+      emit newMessage(("bncComb: DIAG " + corr->_prn.mid(0,3) + " getCrd OK").toLatin1(), false);
+    }
+    
+    */
     // TEMPORARY DIAGNOSTIC: how far is this epoch from the GLONASS broadcast
     // ephemeris reference time? t_ephGlo::position() numerically integrates
Index: trunk/BNC/src/ephemeris.cpp
===================================================================
--- trunk/BNC/src/ephemeris.cpp	(revision 10953)
+++ trunk/BNC/src/ephemeris.cpp	(revision 10954)
@@ -73,4 +73,23 @@
   if (useCorr) {
     if (_orbCorr && _clkCorr) {
+      // Refuse to extrapolate a correction far beyond its own declared
+      // update interval - without this, a single missed/dropped
+      // correction message (network blip, encoder hiccup, ...) gets
+      // extrapolated via its rate term (_dotXr/_dotDClk) forever, with no
+      // warning, producing an unbounded, silently growing position error.
+      // ----------------------------------------------------------------
+      // _updateInt defaults to 0 (1s) when not explicitly set by the
+      // source stream, so a pure multiple of it would be far too strict -
+      // floor it at MIN_STALE_BOUND so normal, slightly slower-than-1Hz
+      // streams are not falsely flagged.
+      const double MAX_STALE_FACTOR = 3.0;
+      const double MIN_STALE_BOUND  = 60.0; // [s]
+      double maxAgeO = max(MIN_STALE_BOUND, MAX_STALE_FACTOR * ssrUpdateInt[_orbCorr->_updateInt]);
+      double maxAgeC = max(MIN_STALE_BOUND, MAX_STALE_FACTOR * ssrUpdateInt[_clkCorr->_updateInt]);
+      if (fabs(tt - _orbCorr->_time) > maxAgeO ||
+          fabs(tt - _clkCorr->_time) > maxAgeC) {
+        return failure;
+      }
+
       double dtO = tt - _orbCorr->_time;
       if (_orbCorr->_updateInt) {
@@ -1424,5 +1443,6 @@
   memset(vv, 0, 3 * sizeof(double));
 
-  double dtPos = bncTime(GPSweek, GPSweeks) - _tt;
+  bncTime tt(GPSweek, GPSweeks);
+  double dtPos = tt - _TOC;
 
   if (fabs(dtPos) > 24 * 3600.0) {
@@ -1438,22 +1458,41 @@
   acc[2] = _z_acc * 1.e3;
 
+  // Always integrate fresh from the pristine, decoded TOC state rather
+  // than rolling _tt/_xv forward across repeated calls. position() can be
+  // called very frequently (multiple times per epoch, from multiple call
+  // sites) - chaining many short integration steps across those calls,
+  // instead of one direct integration to the requested time, lets small
+  // per-call numerical error accumulate over wall-clock time independent
+  // of how far the request actually is from TOC, producing a slow but
+  // steady drift (observed: ~0.5-0.7 mm/s along-track for a GLONASS
+  // satellite whose broadcast message was barely a few minutes old).
+  // ----------------------------------------------------------------
+  ColumnVector xv(6);
+  xv(1) = _x_pos * 1.e3;
+  xv(2) = _y_pos * 1.e3;
+  xv(3) = _z_pos * 1.e3;
+  xv(4) = _x_vel * 1.e3;
+  xv(5) = _y_vel * 1.e3;
+  xv(6) = _z_vel * 1.e3;
+
+  bncTime ttLocal = _TOC;
   for (int ii = 1; ii <= nSteps; ii++) {
-    _xv = rungeKutta4(_tt.gpssec(), _xv, step, acc, glo_deriv);
-    _tt = _tt + step;
+    xv = rungeKutta4(ttLocal.gpssec(), xv, step, acc, glo_deriv);
+    ttLocal = ttLocal + step;
   }
 
   // Position and Velocity
   // ---------------------
-  xc[0] = _xv(1);
-  xc[1] = _xv(2);
-  xc[2] = _xv(3);
-
-  vv[0] = _xv(4);
-  vv[1] = _xv(5);
-  vv[2] = _xv(6);
+  xc[0] = xv(1);
+  xc[1] = xv(2);
+  xc[2] = xv(3);
+
+  vv[0] = xv(4);
+  vv[1] = xv(5);
+  vv[2] = xv(6);
 
   // Clock Correction
   // ----------------
-  double dtClk = bncTime(GPSweek, GPSweeks) - _TOC;
+  double dtClk = tt - _TOC;
   xc[3] = -_tau + _gamma * dtClk;
 
Index: trunk/BNC/src/ephemeris.h
===================================================================
--- trunk/BNC/src/ephemeris.h	(revision 10953)
+++ trunk/BNC/src/ephemeris.h	(revision 10954)
@@ -48,4 +48,6 @@
   void setOrbCorr(const t_orbCorr* orbCorr);
   void setClkCorr(const t_clkCorr* clkCorr);
+  const t_orbCorr* orbCorr() const {return _orbCorr;}
+  const t_clkCorr* clkCorr() const {return _clkCorr;}
   const QDateTime& receptDateTime() const {return _receptDateTime;}
   const QString receptStaID() const {return _receptStaID;}
