feat(governance): implement publication eligibility gates, proportional dynamic redistribution, CI workflow, and 20/20 QA suite
HIFFI QA & Governance Pipeline / governance-tests (push) Successful in 1m43s
HIFFI QA & Governance Pipeline / governance-tests (push) Successful in 1m43s
This commit is contained in:
1 parent
05da5050df
commit
0b36fff7b1
12 files changed
+1325
-806
No files matched your search
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
scripts/audit_weights.py
|
||||
Audits dynamic weight allocation, platform presence tiers, and high-rank evidence.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
DATASET_PATH = Path("data/hiffi_multiplatform_500.csv")
|
||||
|
||||
if not DATASET_PATH.exists():
|
||||
raise FileNotFoundError(f"Master cohort not found at {DATASET_PATH}")
|
||||
|
||||
df = pd.read_csv(DATASET_PATH)
|
||||
|
||||
# Explicitly define platform presence (YouTube, Spotify presence, Instagram presence)
|
||||
df["has_youtube"] = df["production_hiffi_score"].notna()
|
||||
df["has_spotify"] = df["spotify_monthly_listeners"].notna()
|
||||
df["has_instagram"] = df["instagram_followers"].notna()
|
||||
|
||||
df["verified_platform_count"] = (
|
||||
df["has_youtube"].astype(int) +
|
||||
df["has_spotify"].astype(int) +
|
||||
df["has_instagram"].astype(int)
|
||||
)
|
||||
|
||||
print("=" * 70)
|
||||
print("1. VERIFIED PLATFORM PRESENCE TIERS")
|
||||
print("=" * 70)
|
||||
tier_summary = df.groupby("verified_platform_count")["hiffi_xp_score"].agg(
|
||||
count="count",
|
||||
mean="mean",
|
||||
std="std",
|
||||
min="min",
|
||||
max="max"
|
||||
).round(2)
|
||||
print(tier_summary)
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("2. TOP 50 PLATFORM EVIDENCE DISTRIBUTION")
|
||||
print("=" * 70)
|
||||
top_50 = df[df["hiffi_xp_rank"] <= 50]
|
||||
top_50_dist = top_50["verified_platform_count"].value_counts().sort_index(ascending=False)
|
||||
for tier, count in top_50_dist.items():
|
||||
print(f"Tier {tier} Platforms Verified: {count:2d} artists ({count / len(top_50) * 100:4.1f}%)")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("3. TOP 10 PLATFORM EVIDENCE DISTRIBUTION")
|
||||
print("=" * 70)
|
||||
top_10 = df[df["hiffi_xp_rank"] <= 10]
|
||||
top_10_dist = top_10["verified_platform_count"].value_counts().sort_index(ascending=False)
|
||||
for tier, count in top_10_dist.items():
|
||||
print(f"Tier {tier} Platforms Verified: {count:2d} artists ({count / len(top_10) * 100:4.1f}%)")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("4. RANK DELTA EXTREMES & AUDIT TRAIL")
|
||||
print("=" * 70)
|
||||
cols = ["name", "production_hiffi_rank", "hiffi_xp_rank", "rank_delta", "verified_platform_count"]
|
||||
top_gainers = df.sort_values(by="rank_delta", ascending=False).head(3)[cols]
|
||||
top_fallers = df.sort_values(by="rank_delta", ascending=True).head(3)[cols]
|
||||
|
||||
print("Top 3 Gainers:")
|
||||
print(top_gainers.to_string(index=False))
|
||||
print("\nTop 3 Fallers:")
|
||||
print(top_fallers.to_string(index=False))
|
||||
print("=" * 70)
|
||||
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
scripts/verify_publication_gates.py
|
||||
Verifies raw score immutability, evidence gates (Top 10/Top 50),
|
||||
consecutive published ranks, and missing data retention.
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to sys.path so 'core' and other local packages resolve
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
if str(PROJECT_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(PROJECT_ROOT))
|
||||
|
||||
import pandas as pd
|
||||
from core.ranking_engine import HIFFIRankingEngine
|
||||
|
||||
DATASET_PATH = PROJECT_ROOT / "data" / "hiffi_multiplatform_500.csv"
|
||||
|
||||
# 1. Load dataset & apply publication eligibility gates
|
||||
df = pd.read_csv(DATASET_PATH)
|
||||
orig_scores = df["hiffi_xp_score"].copy()
|
||||
orig_ranks = df["hiffi_xp_rank"].copy()
|
||||
|
||||
engine = HIFFIRankingEngine()
|
||||
gated_df = engine.apply_publication_eligibility_gates(df)
|
||||
|
||||
# Check 1: Raw scores & raw ranks unchanged
|
||||
score_match = (gated_df["hiffi_xp_score"].fillna(-999) == orig_scores.fillna(-999)).all()
|
||||
rank_match = (gated_df["hiffi_xp_rank"].fillna(-999) == orig_ranks.fillna(-999)).all()
|
||||
print("=== 1. RAW SCORE & RANK IMMUTABILITY ===")
|
||||
print(f"Raw hiffi_xp_score Unaltered: {score_match}")
|
||||
print(f"Original hiffi_xp_rank Unaltered: {rank_match}")
|
||||
|
||||
# Check 2: Published rank bounds, uniqueness, and completeness
|
||||
pub_ranks = gated_df["hiffi_xp_published_rank"].sort_values().tolist()
|
||||
is_consecutive_500 = pub_ranks == list(range(1, 501))
|
||||
print("\n=== 2. PUBLISHED RANK STRUCTURE ===")
|
||||
print(f"Unique, consecutive 1 to 500: {is_consecutive_500}")
|
||||
print(f"Total cohort count: {len(gated_df)}")
|
||||
|
||||
# Check 3: Evidence Gates
|
||||
top_10 = gated_df[gated_df["hiffi_xp_published_rank"] <= 10]
|
||||
top_50 = gated_df[gated_df["hiffi_xp_published_rank"] <= 50]
|
||||
t10_all_tier3 = (top_10["platform_evidence_tier"] == 3).all()
|
||||
t50_all_tier2plus = (top_50["platform_evidence_tier"] >= 2).all()
|
||||
|
||||
t10_tiers = top_10["platform_evidence_tier"].unique().tolist()
|
||||
t50_tiers = top_50["platform_evidence_tier"].unique().tolist()
|
||||
|
||||
print("\n=== 3. EVIDENCE GATES VALIDATION ===")
|
||||
print(f"Top 10 strictly Tier 3 (3 platforms): {t10_all_tier3} (Tiers present: {t10_tiers})")
|
||||
print(f"Top 50 strictly Tier >= 2: {t50_all_tier2plus} (Tiers present: {t50_tiers})")
|
||||
|
||||
# Check 4: Missing data preservation
|
||||
missing_sp = gated_df["spotify_monthly_listeners"].isna().sum()
|
||||
missing_ig = gated_df["instagram_followers"].isna().sum()
|
||||
zero_sp = (gated_df["spotify_monthly_listeners"] == 0).sum()
|
||||
zero_ig = (gated_df["instagram_followers"] == 0).sum()
|
||||
print("\n=== 4. DATA INTEGRITY & ZERO-IMPUTATION ===")
|
||||
print(f"Spotify Missing (NaN): {missing_sp} | Literal Zeroes: {zero_sp}")
|
||||
print(f"Instagram Missing (NaN): {missing_ig} | Literal Zeroes: {zero_ig}")
|
||||
|
||||
# Persist gated dataset with publication rank column
|
||||
gated_df.to_csv(DATASET_PATH, index=False)
|
||||
print("\nSaved updated cohort with hiffi_xp_published_rank to data/hiffi_multiplatform_500.csv.")
|
||||
Reference in new issue
Block a user