diff --git a/docs/PREDICTIVE_RESOURCE_ALLOCATION.md b/docs/PREDICTIVE_RESOURCE_ALLOCATION.md index a16e7f5..f6d8a6c 100644 --- a/docs/PREDICTIVE_RESOURCE_ALLOCATION.md +++ b/docs/PREDICTIVE_RESOURCE_ALLOCATION.md @@ -12,8 +12,8 @@ The predictor reads two data sources: 2. **Heartbeat logs** (`heartbeat/ticks_*.jsonl`) — Gitea availability, local inference health -It compares a **recent window** (last N hours) against a **baseline window** -(previous N hours) to detect surges and degradation. +It compares a **recent window** (last N hours of activity) against the **previous active window** +(previous N hours ending at the most recent event before the current window) so sparse telemetry still yields a meaningful baseline. ## Output Contract diff --git a/scripts/predictive_resource_allocator.py b/scripts/predictive_resource_allocator.py index 29df0c5..4546dd2 100644 --- a/scripts/predictive_resource_allocator.py +++ b/scripts/predictive_resource_allocator.py @@ -90,13 +90,19 @@ def compute_rates( latest = max(_parse_ts(r["timestamp"]) for r in rows) recent_cutoff = latest - timedelta(hours=horizon_hours) - baseline_cutoff = latest - timedelta(hours=horizon_hours * 2) recent = [r for r in rows if _parse_ts(r["timestamp"]) >= recent_cutoff] - baseline = [ - r for r in rows - if baseline_cutoff <= _parse_ts(r["timestamp"]) < recent_cutoff - ] + + earlier = [r for r in rows if _parse_ts(r["timestamp"]) < recent_cutoff] + if earlier: + previous_latest = max(_parse_ts(r["timestamp"]) for r in earlier) + previous_cutoff = previous_latest - timedelta(hours=horizon_hours) + baseline = [ + r for r in earlier + if _parse_ts(r["timestamp"]) >= previous_cutoff + ] + else: + baseline = [] recent_rate = len(recent) / max(horizon_hours, 1) baseline_rate = (