feat(admin): profile freshness panel in data-quality (#81 phase B.4)

Adds a per-feature freshness summary to /admin/data-quality so the admin
can spot features that are systematically stale or never computed:

  totalEligible — distinct users with tip_views in the last 30 days
  missing       — eligible users with no row stored for the feature
  stale         — eligible users whose stored row is past its TTL

Backend exposes summarizeProfileFreshness() in profile/builder.ts; one
query per feature joins eligible users LEFT JOIN profile rows.
Coverage = (eligible − missing − stale) / eligible, colored
green/yellow/red via the new PctGood helper (high-is-good, opposite of
the existing Pct used for missing-feature/stale-token rates).

Refs #81.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-25 00:34:46 +00:00
parent 9e96540bcc
commit 4a42a6aabf
6 changed files with 167 additions and 3 deletions

View File

@@ -199,6 +199,14 @@ export function getRewardAnalytics(days = 30) {
}>(`/admin/reward-analytics?days=${days}`);
}
export interface FeatureFreshnessRow {
feature: string;
ttlSec: number;
totalEligible: number;
missing: number;
stale: number;
}
export function getDataQuality() {
return apiFetch<{
scoringCallsLast30d: number;
@@ -207,6 +215,7 @@ export function getDataQuality() {
totalTokens: number;
staleTokens: number;
dailyQuality: { date: string; total: number; withFeatures: number; avgCandidates: number }[];
profileFreshness: FeatureFreshnessRow[];
}>('/admin/data-quality');
}