import json from pathlib import Path import tempfile import unittest from paper_atlas.audits.iclr import audit class SnapshotAuditTests(unittest.TestCase): def setUp(self): self.tmp=tempfile.TemporaryDirectory();self.addCleanup(self.tmp.cleanup);self.root=Path(self.tmp.name) def write(self,source,rows): prefix='iclr-program' if source=='iclr_program' else 'openreview-snapshot' path=self.root/f'{prefix}-2026-main.jsonl' path.write_text(''.join(json.dumps({'source':source,'venue':'ICLR','year':2026,'track':'main',**row})+'\n' for row in rows)) manifest={'source':source,'venue':'ICLR','year':2026,'track':'main','parser_version':2,'count':len(rows),'missing_abstract_count':0} if source=='openreview_snapshot': manifest['submission_status_counts']={status:sum(r['status']==status for r in rows) for status in set(r['status'] for r in rows)} path.with_suffix('.manifest.json').write_text(json.dumps(manifest));return path def row(self,forum,status='accepted',number=None): ids=[{'scheme':'openreview','value':forum}] if number:ids.append({'scheme':'iclr_number','value':str(number)}) return {'external_id':forum,'identifiers':{'openreview':forum},'submission_identifiers':ids, 'title':'Title '+forum,'abstract':'Abstract','authors':['Jane Doe'],'status':status, 'metadata':{'public_readers_verified':True},'decision_events':[] if status=='unknown' else [ {'status':status,'source_decision_id':'note-'+forum,'authority':{'public_readers_verified':True}}]} def test_gaps_and_historical_status_differences_are_explicit_not_inferred(self): self.write('iclr_program',[self.row('shared'),self.row('programOnly')]) self.write('openreview_snapshot',[self.row('shared','rejected',1),self.row('snapshotOnly','accepted',2),self.row('unknown','unknown',3)]) result=audit(self.root,[2026],self.root/'audit.json');report=result['years'][0] self.assertEqual(report['program_only_forums'],['programOnly']) self.assertEqual(report['snapshot_accepted_not_in_program'],['snapshotOnly']) self.assertEqual(report['program_snapshot_status_differences'][0]['snapshot_status'],'rejected') self.assertEqual(report['snapshot_status_counts']['rejected'],1) self.assertTrue((self.root/'audit-backfill-queue.json').is_file()) def test_conflicting_numbers_fail_before_publishing_a_queue(self): self.write('iclr_program',[self.row('one')]) self.write('openreview_snapshot',[self.row('one',number=1),self.row('two',number=1)]) with self.assertRaisesRegex(ValueError,'different forums'):audit(self.root,[2026],self.root/'audit.json') self.assertFalse((self.root/'audit-backfill-queue.json').exists()) def test_missing_public_decision_evidence_is_rejected(self): self.write('iclr_program',[self.row('one')]) row=self.row('one');row['decision_events'][0]['authority']={} self.write('openreview_snapshot',[row]) with self.assertRaisesRegex(ValueError,'public decision authority'):audit(self.root,[2026],self.root/'audit.json') def test_manifest_counts_cannot_silently_hide_missing_records(self): path=self.write('iclr_program',[self.row('one')]);path.write_text('') self.write('openreview_snapshot',[self.row('one')]) with self.assertRaisesRegex(ValueError,'count mismatch'):audit(self.root,[2026],self.root/'audit.json') if __name__=='__main__':unittest.main()