106 lines
4.2 KiB
Python
106 lines
4.2 KiB
Python
import sqlite3
|
|||
|
|
import pandas as pd
|
||
|
|
import numpy as np
|
||
|
|
|
||
|
|
def run_telemetry_drift_audit(
|
||
|
|
db_path: str = "data/hiffi_catalog.db",
|
||
|
|
max_daily_listener_drop_pct: float = 25.0,
|
||
|
|
max_growth_spike_pct: float = 500.0
|
||
|
|
) -> dict:
|
||
|
|
"""
|
||
|
|
Evaluates cohort telemetry against operational drift thresholds:
|
||
|
|
1. Catastrophic Drops (>25% daily decline on high-tier artists).
|
||
|
|
2. Anomalous Surges (>500% daily velocity requiring corroboration).
|
||
|
|
3. Governance Violations (Hak non-null regressions).
|
||
|
|
4. Null Velocity Drift on populated accounts.
|
||
|
|
"""
|
||
|
|
con = sqlite3.connect(db_path)
|
||
|
|
query = """
|
||
|
|
SELECT
|
||
|
|
r.catalog_rank,
|
||
|
|
a.artist_id,
|
||
|
|
a.artist_name,
|
||
|
|
a.youtube_url,
|
||
|
|
a.spotify_url,
|
||
|
|
a.instagram_url,
|
||
|
|
t.subscribers_count,
|
||
|
|
t.spotify_monthly_listeners,
|
||
|
|
t.instagram_followers,
|
||
|
|
t.daily_view_velocity,
|
||
|
|
t.growth_velocity_7d,
|
||
|
|
t.momentum_score,
|
||
|
|
t.spotify_daily_change
|
||
|
|
FROM rankings r
|
||
|
|
JOIN artists a ON r.artist_id = a.artist_id
|
||
|
|
JOIN telemetry_metrics t ON a.artist_id = t.artist_id
|
||
|
|
WHERE r.catalog_rank BETWEEN 1 AND 500
|
||
|
|
ORDER BY r.catalog_rank ASC
|
||
|
|
"""
|
||
|
|
df = pd.read_sql_query(query, con)
|
||
|
|
con.close()
|
||
|
|
|
||
|
|
anomalies = []
|
||
|
|
|
||
|
|
print("=" * 80)
|
||
|
|
print("HIFFI AUTOMATED DRIFT & VELOCITY AUDIT")
|
||
|
|
print("=" * 80)
|
||
|
|
|
||
|
|
# 1. Governance Drift Check (Hak Tier-1)
|
||
|
|
hak = df[df["artist_id"] == "@haknyc"]
|
||
|
|
if not hak.empty:
|
||
|
|
hak_row = hak.iloc[0]
|
||
|
|
if pd.notna(hak_row["spotify_url"]) or pd.notna(hak_row["spotify_monthly_listeners"]) or \
|
||
|
|
pd.notna(hak_row["instagram_url"]) or pd.notna(hak_row["instagram_followers"]):
|
||
|
|
anomalies.append({
|
||
|
|
"artist": "Hak",
|
||
|
|
"type": "GOVERNANCE_BREACH",
|
||
|
|
"detail": "Hak has non-null values imputed for Spotify/Instagram"
|
||
|
|
})
|
||
|
|
|
||
|
|
# 2. Daily Spotify Velocity Drift
|
||
|
|
# Calculate % delta: (daily_change / (monthly_listeners - daily_change)) * 100
|
||
|
|
active_sp = df[df["spotify_monthly_listeners"].notna() & (df["spotify_monthly_listeners"] > 0)].copy()
|
||
|
|
prev_listeners = active_sp["spotify_monthly_listeners"] - active_sp["spotify_daily_change"]
|
||
|
|
active_sp["pct_daily_change"] = (active_sp["spotify_daily_change"] / prev_listeners.replace(0, np.nan)) * 100
|
||
|
|
|
||
|
|
severe_drops = active_sp[active_sp["pct_daily_change"] < -max_daily_listener_drop_pct]
|
||
|
|
for _, row in severe_drops.iterrows():
|
||
|
|
anomalies.append({
|
||
|
|
"artist": row["artist_name"],
|
||
|
|
"type": "CATASTROPHIC_DROP",
|
||
|
|
"detail": f"Daily listener drop of {row['pct_daily_change']:.2f}% (Loss: {int(row['spotify_daily_change'])})"
|
||
|
|
})
|
||
|
|
|
||
|
|
anomalous_spikes = active_sp[active_sp["pct_daily_change"] > max_growth_spike_pct]
|
||
|
|
for _, row in anomalous_spikes.iterrows():
|
||
|
|
anomalies.append({
|
||
|
|
"artist": row["artist_name"],
|
||
|
|
"type": "UNVERIFIED_SPIKE",
|
||
|
|
"detail": f"Daily listener surge of {row['pct_daily_change']:.2f}% (Gain: {int(row['spotify_daily_change'])})"
|
||
|
|
})
|
||
|
|
|
||
|
|
# 3. Canonical Schema Drift (Broken URL formats)
|
||
|
|
yt_bad = df[~df["youtube_url"].fillna("").str.contains(r"^https://www\.youtube\.com/channel/UC[a-zA-Z0-9_-]{22}$", regex=True)]
|
||
|
|
for _, row in yt_bad.iterrows():
|
||
|
|
anomalies.append({
|
||
|
|
"artist": row["artist_name"],
|
||
|
|
"type": "SCHEMA_DRIFT_YOUTUBE",
|
||
|
|
"detail": f"Non-canonical YouTube URL: {row['youtube_url']}"
|
||
|
|
})
|
||
|
|
|
||
|
|
print(f"Total Cohort Size Audited: {len(df)}")
|
||
|
|
print(f"Total Drift Anomalies Flagged: {len(anomalies)}")
|
||
|
|
|
||
|
|
if anomalies:
|
||
|
|
print("\n[CIRCUIT BREAKER TRIGGERED] Anomalies detected:")
|
||
|
|
for idx, a in enumerate(anomalies, 1):
|
||
|
|
print(f" {idx}. [{a['type']}] {a['artist']}: {a['detail']}")
|
||
|
|
print("\nAction: Synchronization to production aborted.")
|
||
|
|
return {"circuit_breaker": "TRIPPED", "anomalies": anomalies}
|
||
|
|
else:
|
||
|
|
print("[CIRCUIT BREAKER: CLEAR] No drift detected. Telemetry velocities healthy.")
|
||
|
|
print("Action: Safe to synchronize with live production API.")
|
||
|
|
return {"circuit_breaker": "PASS", "anomalies": []}
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
run_telemetry_drift_audit()
|