import importlib.util
import json
from pathlib import Path

here = Path(__file__).resolve().parent
control = here.parents[2]
spec = importlib.util.spec_from_file_location('strict', control / 'work/2026-09-28-smart-canteen-dm8-poc/http-harness/strict_response_compare.py')
strict = importlib.util.module_from_spec(spec)
spec.loader.exec_module(strict)
b, c = [strict.load_json(here / ('green-' + lane + '.json')) for lane in ('B', 'C')]
expected_cases = {f'{kind}_{i}' for kind in ('detail', 'list') for i in range(5)}
expected_responses = {f'detail_{i}' for i in range(5)} | {'list'}
rule = {'$["trace_id"]': {'type': 'string', 'pattern': '[0-9a-f]{13}',
    'reason': 'ThinkPHP request uniqid; exact shape validated on both sides', 'require_distinct': True}}
differences = []
for report in (b, c):
    assert report['exact_failures'] == 0 and report['case_count'] == 10
    assert set(report['cases']) == expected_cases and all(x['exact'] for x in report['cases'].values())
    assert report['ledger_rows_after'] == 0 and report['user_balances_and_mapping_unchanged'] is True
    assert set(report['responses']) == expected_responses
assert b['model_sha256'] == c['model_sha256'] == 'fc28131f940b8c0e925a94158394506998a124329e81b4473932e205c6c26810'
for name in sorted(expected_responses):
    left, right = b['responses'][name], c['responses'][name]
    assert left['http_status'] == right['http_status'] == 200
    assert left['body']['status'] == right['body']['status'] == 200
    assert isinstance(left['body'].get('trace_id'), str) and isinstance(right['body'].get('trace_id'), str)
    differences.extend((name, p, a, z) for p, a, z, _, _ in strict.compare(left['body'], right['body'], rules=rule))
result = {'http_pairs': 6, 'exact_identifier_checks_per_engine': 10,
    'strict_differences': len(differences), 'differences': differences,
    'cleanup': 'owned ledgers and token zero; users/mappings/balances unchanged',
    'scope': 'gift.Log detail/list wide-identifier reads only; global precision P0 remains open'}
print(json.dumps(result, ensure_ascii=False))
raise SystemExit(bool(differences))
