from pathlib import Path
import json,ast
P=Path(__file__).resolve().parent
cases=json.loads((P/'fixtures/cases.json').read_text(encoding='utf-8'))['cases']
assert len(cases)==8 and len({c['id'] for c in cases})==8
ast.parse((P/'starter.py').read_text(encoding='utf-8'))
required=['human_subject_id','human_account_id','node_id','device_record_id','installation_state','enrollment_state','credential_state','human_binding_state','node_record_state','hostname','os_user','hardware_signal','observed_hardware_signal','same_physical_device','disk_replaced','reinstall','old_credential_reused','assignment_changed']
for c in cases:
    for k in required: assert k in c,(c['id'],k)
assert any(c.get('mutation')=='OS_ACCOUNT_RENAMED' for c in cases)
assert any(c.get('new_human_subject_id') for c in cases)
assert any(c.get('old_credential_state')=='REVOKED' for c in cases)
assert any(c.get('credential_state')=='REVOKED' for c in cases)
assert any(c.get('installation_state')=='UNBOUND' for c in cases)
assert any(c.get('cloned_state') for c in cases)
assert any(c.get('transfer') for c in cases)
print('PASS learner structural checks: 8 synthetic cases, account rename, second-admin binding, reinstall, revoked reuse, unbound enrollment, clone collision, reassignment transfer')
