Reject contradictory submission identities and correct snapshot fixtures
Metadata integrity checks / metadata (push) Successful in 4s

This commit is contained in:
2026-11-06 16:32:09 +08:00
parent 53a83a85a6
commit 8bfe52df68
4 changed files with 18 additions and 2 deletions
+1 -1
View File
@@ -182,7 +182,7 @@ python3 -B collect_openreview_snapshot.py \
--out /data/paper-index/collected --year 2024 --year 2025 --year 2026
```
解析器先核验固定 SHA-256,再流式读取 tar,以临时 SQLite 按年份和 forum 关联投稿及决定,兼容回复先于投稿的归档顺序。只接受明确对 everyone 公开的投稿和具有会议主席签名的 Decision;保留原始决定值、note ID、决定日期、invitation 和签名证据。无明确决定的投稿保留 unknown,不产生拒稿推断。无法关联到公开投稿元数据的公开决定另存 unmatched-decisions 文件,供复核,不擅自创建论文。输出清单分别统计投稿状态、决定事件、缺失摘要和排除原因;重复副本去重,内容冲突会中止。
解析器先核验固定 SHA-256,再流式读取 tar,以临时 SQLite 按年份和 forum 关联投稿及决定,兼容回复先于投稿的归档顺序。只接受明确对 everyone 公开的投稿和具有会议主席签名的 Decision;保留原始决定值、note ID、决定日期、invitation 和签名证据。无明确决定的投稿保留 unknown,不产生拒稿推断。无法关联到公开投稿元数据的公开决定另存 unmatched-decisions 文件,供复核,不擅自创建论文。输出清单分别统计投稿状态、决定事件、缺失摘要和排除原因;重复副本去重,内容冲突会中止。导入时若同一编号指向不同 forum,或同一 forum 指向不同投稿编号,会报冲突并回滚,不强制合并。
该版本是 2026-05-08 发布的第三方历史副本,不代表平台当前状态或全部投稿;缺失决定及公开性筛选均需核验。采集成功也不等于主库已更新,后续应通过单写入协调器导入,并核对同届官方程序与公开决定的差异。
+5
View File
@@ -80,6 +80,11 @@ def attach_submission(store,edition,paper,record,external_id,identities):
for scheme,value in identities:
found=c.execute('SELECT submission_id FROM submission_identifiers WHERE edition_id=? AND scheme=? AND value=?',(edition,scheme,value)).fetchone()
if found:matches.add(found[0])
for scheme in ('openreview','iclr_number'):
values={value for kind,value in identities if kind==scheme}
for sid in matches:
values.update(value for value, in c.execute('SELECT value FROM submission_identifiers WHERE submission_id=? AND scheme=?',(sid,scheme)))
if len(values)>1:raise ValueError('Conflicting authoritative submission identities: '+scheme)
if matches:
papers={paper}|{c.execute('SELECT paper_id FROM submissions WHERE id=?',(sid,)).fetchone()[0] for sid in matches}
surviving=min(papers)
+2 -1
View File
@@ -20,7 +20,8 @@ class SnapshotTests(unittest.TestCase):
content={'title':'A public paper','abstract':'A public abstract','authors':['Jane Doe'],
'authorids':['private@example.org'],'keywords':['learning']}
if v2:content={key:{'value':value} for key,value in content.items()}
return {'id':forum,'forum':forum,'number':42,'readers':['everyone'],'cdate':1760000000000,
number=int(forum[-1]) if forum[-1].isdigit() else 42
return {'id':forum,'forum':forum,'number':number,'readers':['everyone'],'cdate':1760000000000,
'invitations':['ICLR.cc/2026/Conference/-/Submission'],'content':content}
def decision(self,forum='paper1',identifier='decision1',value='Reject'):
+10
View File
@@ -55,6 +55,16 @@ class SubmissionTests(unittest.TestCase):
self.decision(paper,two,'forum2',[('openreview','forum2'),('iclr_number','2')])
self.assertEqual(self.store.conn.execute('SELECT count(*) FROM submissions').fetchone()[0],2)
def test_conflicting_forums_cannot_be_bridged_by_one_submission_number(self):
paper,one=self.record('snapshot','realForum',['Jane Doe'])
other,two=self.record('snapshot','differentForum',['Other Author'])
self.decision(paper,one,'realForum',[('openreview','realForum'),('iclr_number','42')])
with self.assertRaisesRegex(ValueError,'Conflicting authoritative submission identities'):
self.decision(other,two,'differentForum',[('openreview','differentForum'),('iclr_number','42')])
self.assertEqual(self.store.conn.execute('SELECT count(*) FROM papers').fetchone()[0],2)
self.assertEqual(self.store.conn.execute('SELECT count(*) FROM submissions').fetchone()[0],1)
self.assertEqual(self.store.conn.execute('SELECT count(*) FROM submission_merges').fetchone()[0],0)
def test_late_identity_bridge_preserves_decisions_and_does_not_reuse_merged_ids(self):
first,one=self.record('iclr_program','number-42',['Jane Doe','John Smith'])
second,two=self.record('openreview_snapshot','realForum',['Anonymous'])