Skip to content

feat: historical TPP backfill (Story 20.5)#106

Merged
rajish merged 2 commits intomasterfrom
feature/story-20-5-historical-tpp-backfill
Mar 28, 2026
Merged

feat: historical TPP backfill (Story 20.5)#106
rajish merged 2 commits intomasterfrom
feature/story-20-5-historical-tpp-backfill

Conversation

@rajish
Copy link
Copy Markdown
Owner

@rajish rajish commented Mar 28, 2026

Summary

  • Adds HistoricalTPPBackfillService that runs a one-time background backfill on app launch
  • Computes approximate TPP from existing raw poll history (source = "passive-backfill", confidence = "medium")
  • Optional rollup-based backfill using peak-min spread approximation (source = "rollup-backfill", confidence = "low")
  • Two-layer idempotency: preference fast path + DB query fallback
  • "Re-run TPP Backfill" button in Settings for manual reprocessing
  • Extends TPPStorageService with deleteBackfillRecords() for clean re-runs
  • 10 new unit tests covering all acceptance criteria

Story

20.5: Historical TPP Backfill (Nice-to-Have)

Test plan

  • All XCTest unit tests pass
  • Code review findings addressed
  • Build succeeds with xcodebuild

Summary by CodeRabbit

  • New Features

    • Automatic backfill of historical TPP measurements now runs on app startup (idempotent; runs only once).
    • Added manual "Re-run TPP Backfill" option in Settings for users to trigger backfill reprocessing.
  • Tests

    • Comprehensive test suite for backfill functionality covering multiple scenarios and edge cases.

rajish added 2 commits March 28, 2026 01:06
Add HistoricalTPPBackfillService that computes approximate TPP values
from existing raw poll history and rollup data on first launch.

- Raw poll backfill: pairs consecutive polls from last 24h, applies
  same delta/reset/confidence logic as PassiveTPPEngine
- Rollup backfill: approximates delta from peak-min spread in hourly
  buckets for older data (week/month ranges)
- Delta-only records for periods with utilization changes but no tokens
- Two-layer idempotency: preference fast-path + DB slow-path
- Force re-run via Settings "Re-run TPP Backfill" button
- Fire-and-forget wiring in AppDelegate after log parser scan
- 10 test cases covering all acceptance criteria
- Remove duplicate .week rollup query in processRollups — .month already
  includes all .week data (raw <24h + 5min 1-7d + hourly 7-30d), so
  iterating both produced duplicate DB records for the 0-7d window
- Always set tppBackfillCompleted=true after runBackfill completes,
  even when force=true and totalMeasurements=0 (prevents repeated
  launch-path backfill attempts when no historical data exists)
- DB slow-path idempotency check now queries both .passiveBackfill and
  .rollupBackfill sources; previously only checked .passiveBackfill,
  which would miss installs where only rollup records were stored
- Change backfillServiceRef to private in AppDelegate (was internal,
  inconsistent with all other service refs)
- Add 2 regression tests covering the force+empty preference fix and
  the rollup-only slow-path DB detection
@rajish rajish merged commit 62baa86 into master Mar 28, 2026
0 of 2 checks passed
@rajish rajish deleted the feature/story-20-5-historical-tpp-backfill branch March 28, 2026 00:06
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 28, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2afe50dd-ecb8-416a-8241-7c772cb6c2e5

📥 Commits

Reviewing files that changed from the base of the PR and between 8e87326 and cd48627.

📒 Files selected for processing (18)
  • _bmad-output/implementation-artifacts/20-5-historical-tpp-backfill.md
  • _bmad-output/implementation-artifacts/deferred-work.md
  • _bmad-output/implementation-artifacts/sprint-status.yaml
  • cc-hdrm/App/AppDelegate.swift
  • cc-hdrm/Services/HistoricalTPPBackfillService.swift
  • cc-hdrm/Services/HistoricalTPPBackfillServiceProtocol.swift
  • cc-hdrm/Services/PreferencesManager.swift
  • cc-hdrm/Services/PreferencesManagerProtocol.swift
  • cc-hdrm/Services/TPPStorageService.swift
  • cc-hdrm/Services/TPPStorageServiceProtocol.swift
  • cc-hdrm/Views/GearMenuView.swift
  • cc-hdrm/Views/PopoverFooterView.swift
  • cc-hdrm/Views/PopoverView.swift
  • cc-hdrm/Views/SettingsView.swift
  • cc-hdrmTests/Mocks/MockPreferencesManager.swift
  • cc-hdrmTests/Services/BenchmarkServiceTests.swift
  • cc-hdrmTests/Services/HistoricalTPPBackfillServiceTests.swift
  • cc-hdrmTests/Services/PassiveTPPEngineTests.swift

📝 Walkthrough

Walkthrough

This PR implements historical TPP (token throughput) backfill functionality, adding a new service that processes raw polls and rollup data to generate historical TPP measurements, tracks completion state via preferences, and wires the service through the app's UI hierarchy with a force re-run button in Settings.

Changes

Cohort / File(s) Summary
Documentation & Status
_bmad-output/implementation-artifacts/20-5-historical-tpp-backfill.md, _bmad-output/implementation-artifacts/deferred-work.md, _bmad-output/implementation-artifacts/sprint-status.yaml
Marked Epic 20.5 story as complete with task checklists, review findings, and file inventory. Added deferred-work entry noting missing progress UI in auto-launch path. Updated sprint status to reflect completion and backlog status changes.
Backfill Service Implementation
cc-hdrm/Services/HistoricalTPPBackfillService.swift, cc-hdrm/Services/HistoricalTPPBackfillServiceProtocol.swift
Added new HistoricalTPPBackfillService with two-phase backfill (raw polls + rollups), idempotent execution via preference flag, reset detection, and per-model TPP measurement generation. Protocol defines runBackfillIfNeeded() and runBackfill(force:) async entry points.
Preference Tracking
cc-hdrm/Services/PreferencesManager.swift, cc-hdrm/Services/PreferencesManagerProtocol.swift
Added tppBackfillCompleted: Bool property to persist backfill state, enabling idempotent fast-path behavior and supporting forced re-runs via Settings.
Storage Layer
cc-hdrm/Services/TPPStorageService.swift, cc-hdrm/Services/TPPStorageServiceProtocol.swift
Added deleteBackfillRecords() async method to remove passive-backfill and rollup-backfill measurement records, supporting force re-run workflows.
AppDelegate Wiring
cc-hdrm/App/AppDelegate.swift
Instantiated HistoricalTPPBackfillService during bootstrap, stored as backfillServiceRef, and added call to runBackfillIfNeeded() after initial log scan in startup Task.
View Hierarchy Wiring
cc-hdrm/Views/PopoverView.swift, cc-hdrm/Views/PopoverFooterView.swift, cc-hdrm/Views/GearMenuView.swift
Threaded backfillService dependency from PopoverView through PopoverFooterView and GearMenuView to SettingsView; no control flow changes.
Settings UI
cc-hdrm/Views/SettingsView.swift
Added "Re-run TPP Backfill" button (visible when backfill is complete) that triggers runBackfill(force: true), displays running state, and shows measurement count result.
Test Mocks
cc-hdrmTests/Mocks/MockPreferencesManager.swift, cc-hdrmTests/Services/BenchmarkServiceTests.swift, cc-hdrmTests/Services/PassiveTPPEngineTests.swift
Updated mock preferences and storage implementations to support tppBackfillCompleted and deleteBackfillRecords() for test coverage.
Backfill Service Tests
cc-hdrmTests/Services/HistoricalTPPBackfillServiceTests.swift
Comprehensive test suite with custom mocks for log parser and storage, covering idempotent fast-paths, forced reruns, raw poll delta computation, reset detection, rollup processing, multi-model handling, and database pre-population scenarios.

Sequence Diagram

sequenceDiagram
    participant App as AppDelegate
    participant BFS as HistoricalTPPBackfillService
    participant Prefs as PreferencesManager
    participant HDS as HistoricalDataService
    participant LP as ClaudeCodeLogParser
    participant Storage as TPPStorageService

    App->>BFS: runBackfillIfNeeded()
    BFS->>Prefs: tppBackfillCompleted
    alt Already completed
        BFS-->>App: return early
    else First run or force=true
        BFS->>Storage: getMeasurements (check existing)
        alt Has existing records
            BFS->>Prefs: set tppBackfillCompleted=true
            BFS-->>App: return
        else Empty or force=true
            Note over BFS: Phase 1: Raw Polls
            BFS->>HDS: getRecentPolls()
            BFS->>LP: queryTokenAggregates(window)
            BFS->>Storage: storeMeasurements(models + deltas)
            Note over BFS: Phase 2: Rollups
            BFS->>HDS: getHistoricalRollups()
            BFS->>LP: queryTokenAggregates(window)
            BFS->>Storage: storeMeasurements(rollup-backed)
            BFS->>Prefs: set tppBackfillCompleted=true
            BFS-->>App: return measurement count
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰✨ Hoppy hops through polls and rollups bright,
Delta deltas dance with token light,
Backfill complete, the preference set,
Historical TPP—no regrets! 🎉

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/story-20-5-historical-tpp-backfill

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant