REQUIRED=['content_object_id', 'revision_hash', 'change_set_hash', 'contributor_ref', 'reviewer_ref', 'editor_ref', 'publisher_ref', 'authority_scope', 'approval_state', 'approval_revision', 'stale_approval', 'required_review_count', 'owner_review_required', 'conflict_of_interest_state', 'recusal_state', 'exception_ref', 'exception_expiry', 'provenance_entity', 'provenance_activity', 'provenance_agent', 'review_comment_ref', 'publish_gate_state', 'rollback_ref', 'audit_event_id']

def missing(x):
    return [k for k in REQUIRED if k not in x or x[k] is None]

def expected(x):
    if missing(x): return 'HOLD_INSUFFICIENT_EVIDENCE'
    if x.get('current_role') != x.get('capability_snapshot_role'): return 'HOLD_AUTHORITY_RECOMPUTE'
    # An expired exception is evidence of a failed bypass before generic self-review handling.
    if x.get('exception_ref') not in (None,'','NONE') and not x.get('exception_active',False): return 'HOLD_EXCEPTION_EXPIRED'
    if x.get('conflict_of_interest_state') == 'ACTIVE' and x.get('recusal_state') not in ('RECUSAL_COMPLETE','RECUSED'): return 'HOLD_CONFLICT_REVIEW'
    if x.get('self_review') and x.get('reviewer_ref') == x.get('contributor_ref') and x.get('exception_ref') in (None,'','NONE'): return 'HOLD_SELF_APPROVAL'
    if x.get('stale_approval') or (x.get('approval_state')=='APPROVED' and x.get('approval_revision') != x.get('revision_hash')) or (x.get('material_change') and x.get('approval_revision') != x.get('revision_hash')): return 'HOLD_STALE_APPROVAL'
    if int(x.get('review_count',0)) < int(x.get('required_review_count',0)): return 'HOLD_REVIEW_COUNT'
    if x.get('owner_review_required') and not x.get('owner_review_present'): return 'HOLD_OWNER_REVIEW'
    if not x.get('provenance_entity') or not x.get('provenance_activity') or not x.get('provenance_agent'): return 'HOLD_PROVENANCE'
    if not x.get('rollback_ref') or not x.get('audit_event_id'): return 'HOLD_AUDIT_ROLLBACK'
    if x.get('approval_state') != 'APPROVED': return 'REVIEW_REQUIRED'
    return 'PUBLISH_REVIEW_REQUIRED'

def inspect_transfer(x):
    notes=[]
    if x.get('baseline_oracle_label'): notes.append('BASELINE_ORACLE_REUSE_FORBIDDEN')
    if x.get('prior_approval_carryover_attempt'): notes.append('PRIOR_APPROVAL_CARRYOVER_FORBIDDEN')
    if x.get('current_role') != x.get('capability_snapshot_role'): notes.append('AUTHORITY_RECOMPUTE_REQUIRED')
    return notes

def expected_transfer(x):
    notes=inspect_transfer(x)
    if 'PRIOR_APPROVAL_CARRYOVER_FORBIDDEN' in notes: return 'HOLD_PRIOR_APPROVAL_CARRYOVER'
    return expected(x)
