CoolFace
Apppublic

utk7rsh/Arbiter_Gen1

sourceHugging Facemitupdated 5mo agoView on Hugging Face
1likes
validate.py156 linesDownload Raw Back to root
1"""Manual validation of 10 hand-crafted ARBITER episodes.2 3Confirms:4  1. Correct causal claims earn reward.5  2. Counterfactual claims pay double reward.6  3. Defender obfuscation is detectable but harder to claim correctly.7  4. Meta-Overseer flags genuine contradictions only.8  5. Auto-advancement triggers correctly.9 10Usage:11    python validate.py12"""13import sys14from pathlib import Path15sys.path.insert(0, str(Path(__file__).parent))16 17from arbiter.env.environment import ArbiterEnv18 19PASS = "[PASS]"20FAIL = "[FAIL]"21 22def check(label: str, condition: bool):23    status = PASS if condition else FAIL24    print(f"  {status}  {label}")25    return condition26 27 28def run_validation():29    print("=" * 60)30    print("ARBITER — Manual Validation (10 Episodes)")31    print("=" * 60)32 33    results = []34    for episode_idx in range(10):35        seed = episode_idx * 736        anomaly_type = (episode_idx % 3) + 137        print(f"\nEpisode {episode_idx+1:02d}  |  Anomaly Type {anomaly_type}  |  Seed {seed}")38        print("-" * 40)39 40        env = ArbiterEnv(level=1, seed=seed)41        obs = env.reset(seed=seed)42        ep  = env._ep43        ainfo = env._anomaly_info44 45        # ── Test 1: Query returns records ────────────────────────────────────46        obs2, r, done, info = env.step({"type": "QUERY_RECORDS", "feature_filter": {}})47        t1 = check("QUERY_RECORDS returns records",48                   len(info.get("query_result", [])) > 0)49 50        # ── Test 2: Correct causal claim earns reward ────────────────────────51        chain = ainfo.get("causal_chain", [])52        if len(chain) >= 2:53            claim = {54                "cause_feature":  chain[0],55                "effect_outcome": chain[-1],56                "mechanism":      chain[1] if len(chain) > 2 else chain[0],57                "direction":      "positive",58                "confidence":     "HIGH",59                "basis_records":  ["rec_0000"],60                "anomaly_type":   {1:"proxy_discrimination", 2:"adversarial_injection", 3:"model_drift"}[anomaly_type],61            }62            _, reward, _, vinfo = env.step({"type": "CLAIM_CAUSAL", "claim": claim})63            t2 = check(f"Correct causal claim earns reward (got {reward:.3f})", reward > 0)64        else:65            t2 = True  # skip if no chain66 67        # ── Test 3: Counterfactual query works ───────────────────────────────68        rec0 = ep["records"][0]69        proxy_feat = ainfo.get("proxy_feature", "zip_code_cluster")70        _, _, _, cf_info = env.step({71            "type":                "QUERY_COUNTERFACTUAL",72            "record_id":           rec0["id"],73            "feature_id":          proxy_feat,74            "counterfactual_value": "cluster_3",75        })76        cf_res = cf_info.get("cf_result", {})77        t3 = check("QUERY_COUNTERFACTUAL returns a valid result",78                   "original_outcome" in cf_res and "counterfactual_outcome" in cf_res)79 80        # ── Test 4: CF claim pays double ──────────────────────────────────────81        cf_claim = {82            "subject_record":           rec0["id"],83            "counterfactual_feature":   proxy_feat,84            "predicted_outcome_change": cf_res.get("counterfactual_outcome", "approved"),85            "confidence":               "HIGH",86            "basis":                    "causal_structure_inference",87        }88        env._last_cf_result = cf_res89        _, cf_reward, _, _ = env.step({"type": "CLAIM_COUNTERFACTUAL", "claim": cf_claim})90        t4 = check(f"Counterfactual claim reward <= 2.0 (got {cf_reward:.3f})", cf_reward <= 2.01)91 92        # ── Test 5: Meta-Overseer catches contradiction ───────────────────────93        from arbiter.env.meta_overseer import check_consistency94        contradictory_claims = [95            {"claim_type": "causal", "cause_feature": "A", "effect_outcome": "B",96             "confidence": "HIGH", "anomaly_type": "proxy_discrimination"},97            {"claim_type": "causal", "cause_feature": "B", "effect_outcome": "A",98             "confidence": "HIGH", "anomaly_type": "proxy_discrimination"},99        ]100        consistency = check_consistency(contradictory_claims)101        t5 = check(f"Meta-Overseer flags directional contradiction",102                   consistency["num_violations"] > 0)103 104        # ── Test 6: No false positive on non-contradictory claims ─────────────105        clean_claims = [106            {"claim_type": "causal", "cause_feature": "zip_code_cluster",107             "effect_outcome": "denial_rate_overall", "confidence": "HIGH",108             "anomaly_type": "proxy_discrimination"},109            {"claim_type": "causal", "cause_feature": "credit_score",110             "effect_outcome": "approval_rate_overall", "confidence": "MEDIUM",111             "anomaly_type": "proxy_discrimination"},112        ]113        clean_check = check_consistency(clean_claims)114        t6 = check("Meta-Overseer: no false positive on valid claims",115                   clean_check["num_violations"] == 0)116 117        # ── Test 7: SUBMIT_REPORT ends episode ────────────────────────────────118        _, _, done, ep_info = env.step({119            "type":                     "SUBMIT_REPORT",120            "anomaly_type":             {1:"proxy_discrimination", 2:"adversarial_injection", 3:"model_drift"}[anomaly_type],121            "primary_evidence_chain":   chain,122            "affected_demographic":     ainfo.get("affected_demographic", "unknown"),123            "recommended_action":       ainfo.get("recommended_action", "retrain"),124        })125        t7 = check("SUBMIT_REPORT ends episode", done)126        total_ep_reward = ep_info.get("episode_reward", {}).get("total", 0)127        print(f"       Episode total reward: {total_ep_reward:.2f}")128 129        passed = sum([t1, t2, t3, t4, t5, t6, t7])130        results.append(passed)131 132    # ── Summary ───────────────────────────────────────────────────────────────133    print("\n" + "=" * 60)134    total_checks = len(results) * 7135    total_passed = sum(results)136    pct = total_passed / total_checks * 100137    print(f"Results: {total_passed}/{total_checks} checks passed ({pct:.1f}%)")138 139    # ── Test 8: Curriculum auto-advancement ──────────────────────────────────140    print("\nTesting curriculum auto-advancement...")141    from arbiter.env.curriculum import Curriculum142    from config import LEVEL_THRESHOLDS, ADVANCE_WINDOW143    curriculum = Curriculum(start_level=1)144    threshold = LEVEL_THRESHOLDS[1]145    new_level = None146    for _ in range(ADVANCE_WINDOW):147        new_level = curriculum.record(threshold + 1.0)  # above threshold148    check(f"Curriculum advances from Level 1 after {ADVANCE_WINDOW} episodes above threshold",149          curriculum.level == 2 or new_level == 2)150 151    print("\nValidation complete.")152 153 154if __name__ == "__main__":155    run_validation()156