CRITICAL = ['workload_id','business_value','work_unit','resource_plane','arrival_pattern','concurrency','service_time','latency_target','human_minutes','cost_driver','failure_mode','queue_class','observability_signal','evidence_ref']
ALLOWED={'CATALOG_READY','PARTIAL','DISPUTED','STALE','HOLD','BLOCKED'}

def evaluate(case):
    ws=case.get('workloads') or []
    missing=[]
    for i,w in enumerate(ws):
        for k in CRITICAL:
            if w.get(k) in (None,'',[]): missing.append(f'{i}:{k}')
    units={str(w.get('work_unit')) for w in ws if w.get('work_unit') not in (None,'')}
    generic=bool(case.get('generic_job_collapse')) or (len(ws)>1 and len(units)==1 and next(iter(units)).lower() in {'job','task'})
    traceable=all(w.get('evidence_ref') not in (None,'') for w in ws)
    stale=any(w.get('evidence_age_days',0)>w.get('max_evidence_age_days',30) for w in ws)
    retry_visible=True
    for w in ws:
        rr=float(w.get('retry_rate',0) or 0); base=float(w.get('daily_native_units',0) or 0); eff=float(w.get('effective_daily_units',base) or 0)
        if rr>0 and eff + 1e-9 < base*(1+rr): retry_visible=False
    state='CATALOG_READY'; reason='PASS'
    if case.get('blocked_by_owner_policy'):
        state='BLOCKED'; reason='OWNER_OR_POLICY_BLOCK'
    elif missing or not traceable:
        state='HOLD'; reason='CRITICAL_EVIDENCE_MISSING'
    elif generic:
        state='DISPUTED'; reason='HETEROGENEOUS_UNITS_COLLAPSED'
    elif stale:
        state='STALE'; reason='EVIDENCE_STALE'
    elif case.get('recompute_required') and not case.get('recomputed'):
        state='PARTIAL'; reason='MATERIAL_CHANGE_NOT_RECOMPUTED'
    elif case.get('requires_segmented_human_review') and not case.get('human_review_segmented'):
        state='PARTIAL'; reason='HUMAN_REVIEW_SCOPE_NOT_SEGMENTED'
    elif not retry_visible:
        state='PARTIAL'; reason='RETRY_AMPLIFICATION_HIDDEN'
    return {'decision_state':state,'reason_code':reason,'workload_count':len(ws),'native_unit_count':len(units),'generic_job_collapse':generic,'missing_critical_count':len(missing),'retry_amplification_visible':retry_visible,'evidence_traceable':traceable,'missing_fields':missing}
