import pathlib, re, sys, ast, json
ROOT=pathlib.Path(__file__).resolve().parents[2]
checks=[]
def chk(name,cond): checks.append((name,bool(cond)))
# Inspect executable learner Python other than this checker; do not self-match its denylist literals.
pyfiles=[p for p in ROOT.rglob('*.py') if p.name!='static_preflight.py']
forbidden_modules={'requests','socket','paramiko','selenium','urllib','httpx','aiohttp'}
seen=set()
for p in pyfiles:
    try: tree=ast.parse(p.read_text())
    except Exception: continue
    for node in ast.walk(tree):
        if isinstance(node,ast.Import):
            for n in node.names: seen.add(n.name.split('.')[0])
        elif isinstance(node,ast.ImportFrom) and node.module: seen.add(node.module.split('.')[0])
for mod in sorted(forbidden_modules): chk('forbidden_import_'+mod,mod not in seen)
# URL literals are forbidden in executable learner code.
runtime_text='\\n'.join(p.read_text(errors='ignore') for p in pyfiles)
chk('no_http_url_literal',not re.search(r'https?://',runtime_text))
# Parse JSON safety declarations instead of matching checker source text.
json_files=list(ROOT.rglob('*.json'))
real_true=False
for p in json_files:
    try: obj=json.loads(p.read_text())
    except Exception: continue
    def walk(x):
        nonlocal_box=[False]
        def rec(v):
            if isinstance(v,dict):
                for k,val in v.items():
                    if k=='real_credentials' and val is True: nonlocal_box[0]=True
                    rec(val)
            elif isinstance(v,list):
                for q in v: rec(q)
        rec(x); return nonlocal_box[0]
    real_true=real_true or walk(obj)
chk('no_real_credentials_true',not real_true)
all_text='\\n'.join(p.read_text(errors='ignore') for p in ROOT.rglob('*') if p.is_file() and p.suffix in {'.py','.json','.md'})
chk('synthetic_fixture','SEC005-SYNTHETIC-MFA-1' in all_text)
chk('rfc_vector','94287082' in all_text)
chk('attempt_limit','max_attempts' in all_text)
chk('recovery_single_use','RECOVERY_CODE_REUSED_OR_INVALID' in all_text)
chk('regeneration','RECOVERY_SET_REGENERATED' in all_text)
chk('evidence_template',(ROOT/'learner/evidence/MFA_Recovery_Control_Record_v1.template.json').exists())
chk('transfer_template',(ROOT/'learner/transfer/changed-context.template.json').exists())
for name,ok in checks: print(('PASS' if ok else 'FAIL'),name)
print(f'SUMMARY {sum(x[1] for x in checks)}/{len(checks)} PASS')
raise SystemExit(0 if all(x[1] for x in checks) else 1)
