"""Re-evaluate every retained answer without models or edits to the original evidence. Write output to a separate file; never replace result.json. """ from pathlib import Path import json,sys,datetime,hashlib root=Path(__file__).resolve().parent import verify as original import verify_v2 as revised report=root/'result.json' result=json.loads(report.read_text()) retained=json.loads((root/'final-answers.json').read_text()) if hashlib.sha256(report.read_bytes()).hexdigest()!=retained['originalResultSha256']: raise ValueError('Original result hash mismatch') outputs={a['trialId']:a for a in retained['answers']} if not len(outputs)==len(retained['answers'])==len(result['trials'])==8: raise ValueError('Expected exactly eight distinct retained answers and trials') if set(outputs)!={t['id'] for t in result['trials']}: raise ValueError('Retained answer trial identities differ from the original report') answers=[] for trial in result['trials']: item=outputs[trial['id']] if not hashlib.sha256(item['output'].encode()).hexdigest()==item['outputHash']==trial['outputHash']: raise ValueError('Retained output hash mismatch: '+trial['id']) answers.append({'trial':trial,'output':item['output']}) rows=[] for entry in answers: t=entry['trial'];output=entry['output'] first=original.verify(output) if output is not None else None second=revised.verify(output) if output is not None else None if t['verification'] is not None: if first['passed']!=t['verification']['passed']: raise ValueError('Original verifier result mismatch: '+t['id']) eligible=t['status'] in {'passed','failed'} changed=bool(eligible and first is not None and second is not None and first['passed']!=second['passed']) parsed=None if output is not None: text=output.strip() if text.startswith('```json\n') and text.endswith('\n```'):text=text[8:-4] try:parsed=json.loads(text) except ValueError:pass scope=None if isinstance(parsed,dict) and isinstance(parsed.get('sources'),list): scope=next((x for x in parsed['sources'] if isinstance(x,dict) and x.get('claim')=='scope'),None) rows.append({'trialId':t['id'],'variant':t['variant'],'order':t['order'],'originalStatus':t['status'],'originalReason':t['reason'],'postHocOutcomeStatus':('passed' if second and second['passed'] else 'failed') if eligible else t['status'],'originalVerifier':first,'postHocVerifierV2':second,'changedByScopeRepair':changed,'classification':'verifier-false-negative' if changed else 'retained-verifier-failure' if second and not second['passed'] else 'unchanged-pass' if second else 'execution-incomplete','agentDurationMs':t['agentDurationMs'],'usage':t['usage'],'diagnostics':t['diagnostics'],'scopeSource':scope,'outputHash':t['outputHash']}) counts={variant:{'planned':4,'originalPassed':sum(r['originalStatus']=='passed' for r in rows if r['variant']==variant),'postHocAccepted':sum(r['postHocOutcomeStatus']=='passed' for r in rows if r['variant']==variant),'repairedFalseNegatives':sum(r['changedByScopeRepair'] for r in rows if r['variant']==variant)} for variant in ['baseline','candidate']} artifact={'schemaVersion':'1','kind':'post-hoc-verifier-sensitivity','recordedAt':datetime.datetime.now(datetime.timezone.utc).isoformat(),'originalResultId':result['id'],'originalResultSha256':hashlib.sha256(report.read_bytes()).hexdigest(),'originalManifestHash':result['manifestHash'],'originalSourceCommit':'8d86dda1be42db57df4c8b82cecd1749ad04bc42','verifierVersions':{'original':'1','sensitivity':'2'},'defect':'Version 1 required the word inconclusive in a scope quotation. It rejected source-grounded statements that explicitly denied generalization using different wording. A failed original verdict is therefore not automatically an agent failure.','repair':'Version 2 accepts three equivalent statements found in the frozen source while preserving all other checks. Original verdicts and source files are unchanged. Every retained answer was assessed under both versions, including failures.','inference':'This is a post-hoc verifier diagnosis and sensitivity analysis, not a preregistered success comparison. Neither the flawed original predicate nor the repaired counts establish that the navigation index improves agent performance.','productionBoundary':'Real agent execution on frozen production response files, prepared for production-platform upload. No per-trial HTTP, authenticated account operations, browser or assistive-technology coverage.','counts':counts,'trials':rows} artifact['verifierFingerprints']={name:hashlib.sha256((root/name).read_bytes()).hexdigest() for name in ['verify.py','verify_v2.py']} print(json.dumps(artifact,indent=2))