diff --git a/screen_locker/_runnerup_db.py b/screen_locker/_runnerup_db.py index afc5b32..cb016d8 100644 --- a/screen_locker/_runnerup_db.py +++ b/screen_locker/_runnerup_db.py @@ -57,7 +57,14 @@ class RunnerUpDbMixin: root=True, ) if not ok: - _logger.info("Failed to copy RunnerUp DB to sdcard: %s", err) + _logger.warning( + "Root DB pull failed for %s (%s) — this device likely has no " + "root/su access, so this fallback path cannot work here. " + "RunnerUp workouts can only be verified via TCX export files; " + "enable RunnerUp's File Synchronizer auto-export on-device.", + pkg, + err, + ) shutil.rmtree(tmp_dir, ignore_errors=True) return None @@ -142,7 +149,12 @@ class RunnerUpDbMixin: """Verify today's run via root DB pull (fallback path).""" db_path = self._pull_runnerup_db() if db_path is None: - return "not_verified", "Could not retrieve RunnerUp database from phone" + return ( + "not_verified", + "No TCX export found and root DB access is unavailable on this " + "device — enable RunnerUp's File Synchronizer auto-export so " + "runs land in /sdcard/Documents/RunnerUp/", + ) try: run_data = self._query_todays_run(db_path) diff --git a/screen_locker/_runnerup_verification.py b/screen_locker/_runnerup_verification.py index b3e7f1b..aef33af 100644 --- a/screen_locker/_runnerup_verification.py +++ b/screen_locker/_runnerup_verification.py @@ -138,6 +138,14 @@ class RunnerUpVerificationMixin(RunnerUpDbMixin): today = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d") exports = self._find_runnerup_exports_for_date(today) if not exports: + _logger.warning( + "No RunnerUp TCX export found for %s in %s — a run today will " + "not be verified unless RunnerUp's File Synchronizer " + "auto-export is enabled and the app stays enabled long enough " + "to sync (check it isn't disabled by focus mode).", + today, + RUNNERUP_EXPORT_DIRS, + ) return None # Try each file; return the best result (verified > validation error). @@ -174,6 +182,13 @@ class RunnerUpVerificationMixin(RunnerUpDbMixin): continue status, msg = self._validate_runnerup_data(data) if status != "verified": + _logger.warning( + "RunnerUp export %s for %s did not qualify (%s): %s", + remote, + date_str, + status, + msg, + ) continue workout_data = { "type": "runnerup_verified", @@ -285,5 +300,6 @@ class RunnerUpVerificationMixin(RunnerUpDbMixin): return file_result # Path 2: root DB pull (fallback when no export files found yet). - _logger.info("No TCX exports found today; trying root DB pull...") + # On a non-rooted device this path cannot succeed; _verify_runnerup_via_db + # reports that plainly rather than as a generic failure. return self._verify_runnerup_via_db() diff --git a/screen_locker/screen_lock.py b/screen_locker/screen_lock.py index 0dab4ae..e020f46 100755 --- a/screen_locker/screen_lock.py +++ b/screen_locker/screen_lock.py @@ -234,8 +234,15 @@ class ScreenLocker( ``workout-sync.timer`` unit calls. Sync used to happen only inside the locker's startup path, so a workout finished after login stayed invisible until the next login. + + Also re-runs the RunnerUp TCX backfill here, not just at login: the + login-time scan gets exactly one shot, and if the phone isn't + adb-visible at that instant (e.g. USB debugging not yet + authorized), a same-day run stays uncredited until the next login. + Repeating it every 15 minutes closes that gap. """ self._ingest_synced_manual_workouts() + self._auto_fill_week_runnerup_bonus() def _ingest_synced_manual_workouts(self) -> None: """Sync manual workouts: publish this PC's, ingest everyone else's.