"""Visible deterministic rules for the synthetic MKN-024 profile compiler lab."""
import hashlib,json

def inspect_case(f):
    issues=[]
    if not isinstance(f,dict) or f.get("evidence_kind")!="SYNTHETIC": return ["INPUT_INVALID"]
    comp=f.get("compiler") or {}; src=f.get("source_records") or []; out=f.get("compiled_claims") or []
    if comp.get("writes_to_source"): issues.append("CANONICAL_SOURCE_MUTATION_FORBIDDEN")
    if not comp.get("source_snapshot_hash"): issues.append("SOURCE_SNAPSHOT_HASH_MISSING")
    byid={r.get("source_record_ref"):r for r in src}
    for c in out:
        s=byid.get(c.get("source_record_ref"))
        if not s: issues.append("SOURCE_RECORD_BINDING_MISSING"); continue
        if not c.get("provenance_ref") or not c.get("evidence_ref"): issues.append("EVIDENCE_OR_PROVENANCE_MISSING")
        if c.get("evidence_ref")!=s.get("evidence_ref"): issues.append("DETACHED_EVIDENCE_REFERENCE")
        if s.get("credential_status")=="EXPIRED" and c.get("public_status")=="CURRENT": issues.append("EXPIRED_CREDENTIAL_LAUNDERED_CURRENT")
        if s.get("revocation_state")=="REVOKED" and c.get("public_status")=="CURRENT": issues.append("REVOKED_CREDENTIAL_LAUNDERED_CURRENT")
        if s.get("claim_type")=="SELF_ASSERTED" and c.get("claim_type")=="VERIFIED" and not s.get("bound_verification_evidence"): issues.append("SELF_ASSERTION_UNBOUND_VERIFICATION_UPGRADE")
        if s.get("claim_type")=="ENDORSED" and c.get("claim_type")=="VERIFIED_MASTERY": issues.append("ENDORSEMENT_CONVERTED_TO_MASTERY")
        if s.get("visibility")=="PRIVATE" and c.get("visibility")=="PUBLIC" and not s.get("authorized_visibility_change_ref"): issues.append("PRIVATE_TO_PUBLIC_WITHOUT_AUTHORIZATION")
        if s.get("claim_type")=="SELF_ASSERTED" and c.get("visibility")=="PUBLIC" and not c.get("unverified_label"): issues.append("UNVERIFIED_LABEL_MISSING")
        if s.get("project_artifact_ref") and s.get("artifact_hash")!=c.get("artifact_hash"): issues.append("ARTIFACT_HASH_MISMATCH")
    return sorted(set(issues))

def expected_case(f):
    issues=inspect_case(f)
    if issues:
        return "INSUFFICIENT_EVIDENCE" if issues==["EVIDENCE_OR_PROVENANCE_MISSING"] else "HOLD"
    return "COMPILED_BOUNDED"

def inspect_transfer(f):
    issues=inspect_case(f)
    if f.get("baseline_projection_copied"): issues.append("BASELINE_ORACLE_REUSE_FORBIDDEN")
    d=f.get("diff") or {}
    if not d.get("removed_public_claims"): issues.append("TRANSFER_REMOVAL_DIFF_MISSING")
    if not d.get("added_or_upgraded_claims"): issues.append("TRANSFER_ADDITION_DIFF_MISSING")
    if not f.get("previous_profile_hash") or not f.get("current_profile_hash"): issues.append("PROFILE_VERSION_HASHES_MISSING")
    if f.get("previous_profile_hash")==f.get("current_profile_hash"): issues.append("TRANSFER_PROFILE_HASH_NOT_CHANGED")
    return sorted(set(issues))

def expected_transfer(f): return "HOLD" if inspect_transfer(f) else "COMPILED_BOUNDED"
