"""Public arithmetic checks for learner_results.json; no automatic narrative grade."""
import json, math, sys
from pathlib import Path
EXPECTED={'late_count':(51,0),'late_denominator':(240,0),'actual_mean':(62.79416666666667,.005),
'actual_median':(62.2,.005),'satisfaction_missing':(41,0),
'trial_difference':(-3.2015,.005),'trial_ci_low':(-5.849601316500556,.005),
'trial_ci_high':(-0.5533986834994424,.005),'trial_p':(0.019120112692739923, .00005)}
def check_payload(data):
errors=[]
if not isinstance(data,dict):return ['Top-level JSON must be an object.']
for key,(expected,tolerance) in EXPECTED.items():
value=data.get(key)
if isinstance(value,bool) or not isinstance(value,(int,float)) or not math.isfinite(value):errors.append(f'{key}: supply a finite number, not {value!r}')
elif abs(value-expected)>tolerance:errors.append(f'{key}: revisit the source, denominator or contrast; expected {expected:g} within {tolerance:g}')
if data.get('synthetic') is not True:errors.append('Label the evidence synthetic: synthetic must be true.')
if data.get('contrast')!='checklist_minus_control':errors.append('contrast must be checklist_minus_control; negative means faster.')
if not isinstance(data.get('limitations'),str) or len(data['limitations'].strip())<20:errors.append('Write a meaningful limitations note; a human must review its content.')
return errors
def main():
path=Path(sys.argv[1]) if len(sys.argv)>1 else Path(__file__).resolve().parent/'learner_results.json'
try:data=json.loads(path.read_text())
except (OSError,ValueError) as e:print(f'Could not read learner result: {e}');return 1
errors=check_payload(data)
if errors:print('\n'.join(errors));return 1
print('12 public arithmetic/label checks passed. This is not a capstone grade. Review methods, charts, limitations and recommendation with the rubric.');return 0
if __name__=='__main__':raise SystemExit(main())