#!/usr/bin/env python3
from pathlib import Path
import json,re,sys
root=Path(__file__).resolve().parents[1]
def J(rel): return json.loads((root/rel).read_text(encoding='utf-8'))
contract=J('model-contract.json'); msgs=J('data/review-messages.json'); glossary=J('data/glossary.json'); rules=J('data/qa-rules.json'); transfer=J('transfer/changed-context.json')
issues=[]; detected=[]
def issue(code,detail): issues.append({'code':code,'detail':detail})
def vars_of(s): return set(re.findall(r'\{([A-Za-z0-9_]+)\}',s))
for m in msgs:
    expected=set(m.get('required_variables',[])); actual=vars_of(m.get('candidate',''))
    if expected-actual:
        detected.append('MISSING_VARIABLE_TOKEN')
        if m.get('human_decision')=='ACCEPT': issue('MISSING_VARIABLE_TOKEN_UNACKNOWLEDGED',m['id'])
    if m.get('terminology_scope')=='Alpha/de-DE':
        for e in glossary.get('entries',[]):
            if e['source']=='workspace' and any(x.lower() in m.get('candidate','').lower() for x in e.get('forbidden',[])):
                detected.append('TERMINOLOGY_VIOLATION')
                if m.get('human_decision')=='ACCEPT': issue('TERMINOLOGY_VIOLATION_UNACKNOWLEDGED',m['id'])
    if m.get('locale_format',{}).get('status')=='FAIL':
        detected.append('LOCALE_FORMAT_MISMATCH')
        if m.get('human_decision')=='ACCEPT': issue('LOCALE_FORMAT_MISMATCH_UNACKNOWLEDGED',m['id'])
    if m.get('context_review',{}).get('status')=='FAIL':
        detected.append('CONTEXT_MEANING_MISMATCH')
        if m.get('human_decision')=='ACCEPT': issue('HUMAN_CONTEXT_REVIEW_REQUIRED',m['id'])
    ld=m.get('language_direction',{})
    if m.get('target_locale') in rules.get('rtl_locales',[]) and ld.get('dir')!=ld.get('expected_dir'):
        detected.append('RTL_METADATA_MISSING')
        if m.get('human_decision')=='ACCEPT': issue('RTL_METADATA_MISSING_UNACKNOWLEDGED',m['id'])
    if not m.get('reviewer_role'): issue('HUMAN_DECISION_PROVENANCE_REQUIRED',m['id'])
if contract.get('automated_checks_prove_linguistic_adequacy') is not False: issue('AUTOMATION_LINGUISTIC_OVERCLAIM','contract')
if contract.get('glossary_proves_whole_sentence_correctness') is not False: issue('GLOSSARY_OVERCLAIM','contract')
if contract.get('ai_output_is_authority') is not False: issue('AI_AUTHORITY_OVERCLAIM','contract')
if contract.get('human_accept_edit_reject_required') is not True: issue('HUMAN_DECISION_REQUIRED','contract')
if transfer.get('independent') is not True or transfer.get('decisive_solution_supplied_by_ai') is not False: issue('TRANSFER_INDEPENDENCE','changed context')
out={'schema':'WEB022_AUDIT_OUTPUT_v1','issues':issues,'issue_count':len(issues),'detected_fixture_codes':sorted(set(detected)),'status':'PASS' if not issues else 'FAIL'}
(root/'evidence/audit-output.json').write_text(json.dumps(out,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
print(json.dumps(out,ensure_ascii=False,indent=2)); sys.exit(0 if not issues else 1)
