feat(sales): implement Phase 1 & 2 commercial sales telemetry and dashboard analytics
HIFFI Multi-Platform CI / test (3.11) (push) Successful in 23s
HIFFI Multi-Platform CI / test (3.12) (push) Successful in 23s

This commit is contained in:
Srilekha committed 2026-10-28 17:07:19 +05:30
1 parent 6b567df015
commit 8f77295de9
7 files changed
+1371 -575

No files matched your search

+158 -15
View File
@@ -2,7 +2,8 @@
test_multiplatform_ranking.py
Comprehensive QA & Data Governance Test Suite for HIFFI Multi-Platform Pipeline.
Enforces zero-imputation policy, score bounding, identity resolution,
fallbacks, strict null retention, and publication eligibility gates.
fallbacks, strict null retention, publication eligibility gates,
and ChartMasters record sales governance.
"""
import inspect
@@ -175,7 +176,6 @@ def test_spotify_fallback_null_safety(monkeypatch):
"""Verify Spotify embed fallback safely returns structured null dictionary on unindexed items."""
from collectors.spotify_fallback_collector import SpotifyFallbackCollector
# Mock unindexed response to avoid brittle offline network failures
class MockResponse:
status_code = 404
text = "Not Found"
@@ -353,12 +353,10 @@ def test_publication_eligibility_gates(dataset):
engine = HIFFIRankingEngine()
gated = engine.apply_publication_eligibility_gates(dataset, reference_time=DATASET_ANCHOR_TIME)
# 1. Raw scores must remain unchanged
assert (gated["hiffi_xp_score"] == dataset["hiffi_xp_score"]).all(), (
"Publication gates altered the underlying raw composite scores."
)
# 2. Check Top 10 requires all 3 platforms
top_10 = gated[gated["hiffi_xp_published_rank"] <= 10]
assert len(top_10) == 10
assert (top_10["platform_evidence_tier"] == 3).all(), (
@@ -366,7 +364,6 @@ def test_publication_eligibility_gates(dataset):
f"{top_10[top_10['platform_evidence_tier'] < 3][['name', 'platform_evidence_tier']]}"
)
# 3. Check Top 50 requires at least 2 platforms
top_50 = gated[gated["hiffi_xp_published_rank"] <= 50]
assert len(top_50) == 50
assert (top_50["platform_evidence_tier"] >= 2).all(), (
@@ -374,7 +371,6 @@ def test_publication_eligibility_gates(dataset):
f"{top_50[top_50['platform_evidence_tier'] < 2][['name', 'platform_evidence_tier']]}"
)
# 4. Check ranks are strictly unique and consecutive 1 to N
ranks = gated["hiffi_xp_published_rank"].sort_values().tolist()
expected_ranks = list(range(1, len(gated) + 1))
assert ranks == expected_ranks, "Published ranks contain gaps or duplicates."
@@ -404,7 +400,6 @@ def test_publication_gate_blocks_failed_youtube_lookup():
gated = engine.apply_publication_eligibility_gates(test_df, reference_time=DATASET_ANCHOR_TIME)
row = gated.iloc[0]
# Blocked from YouTube -> only Spotify + IG valid -> Tier 2
assert row["platform_evidence_tier"] == 2
assert "FAILED_YOUTUBE_LOOKUP" in row["evidence_exclusions"]
@@ -515,12 +510,12 @@ def test_freshness_gate_stale_timestamps_demote_tier():
"name": "Artist Stale Telemetry",
"status_flag": "COMPLETE",
"production_hiffi_score": 90.0,
"youtube_updated_at": "2026-10-25T12:00:00Z", # 1 day old (Fresh)
"youtube_updated_at": "2026-10-25T12:00:00Z",
"spotify_monthly_listeners": 25_000_000,
"spotify_updated_at": "2026-10-15T12:00:00Z", # 11 days old (Stale)
"spotify_updated_at": "2026-10-15T12:00:00Z",
"instagram_followers": 10_000_000,
"instagram_verification_status": "AUTOMATED_VERIFIED",
"instagram_updated_at": "2026-10-01T12:00:00Z", # 25 days old (Stale)
"instagram_updated_at": "2026-10-01T12:00:00Z",
"hiffi_xp_score": 88.5,
"hiffi_xp_rank": 5
}])
@@ -548,7 +543,7 @@ def test_freshness_gate_missing_or_malformed_timestamp():
"spotify_updated_at": None,
"instagram_followers": 5_000_000,
"instagram_verification_status": "AUTOMATED_VERIFIED",
"instagram_updated_at": "2026-10-25T12:00:00Z", # Fresh
"instagram_updated_at": "2026-10-25T12:00:00Z",
"hiffi_xp_score": 82.0,
"hiffi_xp_rank": 10
}])
@@ -600,8 +595,8 @@ def test_anomaly_detection_flags_suspicious_patterns():
},
{
"name": "Inorganic IG Artist",
"lifetime_views": 100_000, # 100k views
"instagram_followers": 5_000_000, # 5M followers (50x ratio > 10x)
"lifetime_views": 100_000,
"instagram_followers": 5_000_000,
"spotify_monthly_listeners": 500_000,
"spotify_daily_change": 1_000,
"hiffi_xp_score": 70.0
@@ -611,7 +606,7 @@ def test_anomaly_detection_flags_suspicious_patterns():
"lifetime_views": 50_000_000,
"instagram_followers": 1_000_000,
"spotify_monthly_listeners": 100_000,
"spotify_daily_change": 40_000, # 40k daily change on 100k monthly (40% > 25%)
"spotify_daily_change": 40_000,
"hiffi_xp_score": 65.0
}
])
@@ -621,4 +616,152 @@ def test_anomaly_detection_flags_suspicious_patterns():
assert flagged.loc[0, "anomaly_flags"] == "CLEAN"
assert "SUSPICIOUS_IG_TO_YT_RATIO" in flagged.loc[1, "anomaly_flags"]
assert "EXTREME_SPOTIFY_VELOCITY_RATIO" in flagged.loc[2, "anomaly_flags"]
assert flagged.loc[1, "hiffi_xp_score"] == 70.0
assert flagged.loc[1, "hiffi_xp_score"] == 70.0
# ==============================================================================
# CHARTMASTERS RECORD SALES GOVERNANCE & INTEGRITY TESTS
# ==============================================================================
MOCK_CHARTMASTERS_HTML = """
<html>
<body>
<table>
<thead>
<tr>
<th>Rank</th>
<th>Artist</th>
<th>Album Sales</th>
<th>Physical Singles</th>
<th>Digital Singles</th>
<th>Streaming EAS</th>
<th>Total EAS</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>The Beatles</td>
<td>162,000,000</td>
<td>33,000,000</td>
<td>28,000,000</td>
<td>10,000,000</td>
<td>233,000,000</td>
</tr>
<tr>
<td>2</td>
<td>Michael Jackson</td>
<td>135,000,000</td>
<td>26,000,000</td>
<td>24,000,000</td>
<td>12,000,000</td>
<td>197,000,000</td>
</tr>
<tr>
<td>3</td>
<td>Eminem</td>
<td>63,000,000</td>
<td>9,000,000</td>
<td>45,000,000</td>
<td>60,000,000</td>
<td>177,000,000</td>
</tr>
<tr>
<td>4</td>
<td>A$AP Rocky</td>
<td>2,500,000</td>
<td>100,000</td>
<td>15,000,000</td>
<td>20,000,000</td>
<td>37,600,000</td>
</tr>
</tbody>
</table>
</body>
</html>
"""
def test_chartmasters_parser_schema_and_types():
"""Validates HTML table parsing, column typing, and metrics conversion."""
from collectors.chartmasters_collector import ChartMastersSalesCollector
collector = ChartMastersSalesCollector()
count = collector.load_sales_table(html_content=MOCK_CHARTMASTERS_HTML)
assert count == 4
beatles = collector.get_artist_sales_metrics("The Beatles")
assert beatles["sales_data_status"] == "VERIFIED_CSPC"
assert beatles["chartmasters_sales_rank"] == 1
assert beatles["total_eas_cspc"] == 233_000_000
assert beatles["pure_album_sales"] == 162_000_000
assert isinstance(beatles["streaming_eas"], int)
def test_chartmasters_stage_alias_resolution():
"""Validates stylized name alias resolution (e.g. A$AP Rocky -> asap rocky)."""
from collectors.chartmasters_collector import ChartMastersSalesCollector
collector = ChartMastersSalesCollector()
collector.load_sales_table(html_content=MOCK_CHARTMASTERS_HTML)
asap = collector.get_artist_sales_metrics("A$AP Rocky")
assert asap["sales_data_status"] == "VERIFIED_CSPC"
assert asap["chartmasters_sales_rank"] == 4
assert asap["total_eas_cspc"] == 37_600_000
def test_chartmasters_zero_imputation_null_retention():
"""Ensures uncataloged artists strictly return None and are never imputed with 0."""
from collectors.chartmasters_collector import ChartMastersSalesCollector
collector = ChartMastersSalesCollector()
collector.load_sales_table(html_content=MOCK_CHARTMASTERS_HTML)
unindexed = collector.get_artist_sales_metrics("Emerging Underground Artist 123")
assert unindexed["sales_data_status"] == "NOT_CATALOGED_YET"
assert unindexed["chartmasters_sales_rank"] is None
assert unindexed["total_eas_cspc"] is None
assert unindexed["pure_album_sales"] is None
def test_chartmasters_rank_monotonicity():
"""Higher sales rank (1 vs 2) must strictly correspond to higher or equal Total EAS."""
from collectors.chartmasters_collector import ChartMastersSalesCollector
collector = ChartMastersSalesCollector()
collector.load_sales_table(html_content=MOCK_CHARTMASTERS_HTML)
beatles = collector.get_artist_sales_metrics("The Beatles")
mj = collector.get_artist_sales_metrics("Michael Jackson")
eminem = collector.get_artist_sales_metrics("Eminem")
assert beatles["chartmasters_sales_rank"] < mj["chartmasters_sales_rank"] < eminem["chartmasters_sales_rank"]
assert beatles["total_eas_cspc"] >= mj["total_eas_cspc"] >= eminem["total_eas_cspc"]
def test_chartmasters_enrich_cohort_dataframe():
"""Tests zero-imputation cohort enrichment over a pandas DataFrame."""
from collectors.chartmasters_collector import ChartMastersSalesCollector
collector = ChartMastersSalesCollector()
collector.load_sales_table(html_content=MOCK_CHARTMASTERS_HTML)
cohort_df = pd.DataFrame([
{"name": "Eminem", "production_hiffi_score": 92.0},
{"name": "Non-Indexed Indie Artist", "production_hiffi_score": 45.0}
])
enriched = collector.enrich_cohort(cohort_df, name_column="name")
assert "total_eas_cspc" in enriched.columns
assert "chartmasters_sales_rank" in enriched.columns
# Row 0 (Eminem) has valid numeric metrics
assert enriched.loc[0, "total_eas_cspc"] == 177_000_000
assert enriched.loc[0, "chartmasters_sales_rank"] == 3
# Row 1 (Non-indexed) must be None/NaN, not 0
assert pd.isna(enriched.loc[1, "total_eas_cspc"])
assert pd.isna(enriched.loc[1, "chartmasters_sales_rank"])
assert enriched.loc[1, "sales_data_status"] == "NOT_CATALOGED_YET"