def evaluate(c):
    required=['gate_id','campaign_id','creative_id','relationship_type','material_connection_state','rights_clearance_ref','license_scope','platform','placement_type','platform_policy_version','brand_suitability_profile','jurisdiction_scope','reviewer_role','evidence_ref']
    complete=all(str(c.get(k,'')).strip() for k in required)
    changed=bool(c.get('changed_context'))
    preserved=bool(c.get('unchanged_evidence_preserved',True))
    legal_review=False
    if not str(c.get('evidence_ref','')).strip():
        state='HOLD_EVIDENCE'
    elif c.get('jurisdiction_ambiguity') or c.get('jurisdiction_scope') in ('','UNKNOWN'):
        state='LEGAL_REVIEW_HOLD'; legal_review=True
    elif not str(c.get('rights_clearance_ref','')).strip() or not c.get('license_covers_usage',True):
        state='HOLD_RIGHTS'
    elif c.get('material_connection_state')=='PRESENT' and (not str(c.get('disclosure_text_ref','')).strip() or not c.get('disclosure_visibility_check',False)):
        state='HOLD_DISCLOSURE'
    elif c.get('platform_policy_stale'):
        state='STALE'
    elif not c.get('platform_suitable',True):
        state='HOLD_PLATFORM_POLICY'
    elif not c.get('brand_suitable',True):
        state='HOLD_BRAND_SUITABILITY'
    else:
        state='READY_FOR_RELEASE'
    return {'state':state,'release':state=='READY_FOR_RELEASE','legal_review':legal_review,'recheck_changed_gates':changed,'evidence_complete':complete,'preserved_unchanged':preserved}
