diff --git a/docs/aamas-proceedings.md b/docs/aamas-proceedings.md index aa730db..04ed984 100644 --- a/docs/aamas-proceedings.md +++ b/docs/aamas-proceedings.md @@ -9,7 +9,7 @@ 排除 3 个 keynote;research 的 p238 明确标注 `Retracted June 8, 2026`,完整题名、作者、栏目、日期、原文和来源回执保存在采集报告 `held_publications` 中,**不会输出 accepted 或 withdrawn 投稿记录**。当前决定模型没有独立 retracted 状态,后续须单独建模和核验;原始证据不能删除。任何新增或改变的撤稿标记都会停止采集,等待人工核查。 -另一个 extended abstract p3178 明确标注 `Withdrawn June 8, 2026`,输出 `withdrawn` 和日期 `2026-06-08`,不补造其此前的接受决定或 PDF 链接。因此 639 个输出条目是 **638 accepted、1 withdrawn**,按六个 track 分组:`proceedings_unspecified` 522、`aaai_transfer` 19、`blue_sky` 17、`doctoral` 34、`demo` 44、`jaamas` 3。全文/扩展摘要是发表形式,不是研究类型;research 栏目不能证明每篇原始 main/special 投稿轨道。JAAMAS 保留期刊展示语义,不制造另一次独立审稿录用。 +另一个 extended abstract p3178 明确标注 `Withdrawn June 8, 2026`,输出 `withdrawn`,在 metadata 保留日期 `2026-06-08` 和日精度;原网页没有时区/时刻,不能伪造决定 timestamp,不补造其此前的接受决定或 PDF 链接。因此 639 个输出条目是 **638 accepted、1 withdrawn**,按六个 track 分组:`proceedings_unspecified` 522、`aaai_transfer` 19、`blue_sky` 17、`doctoral` 34、`demo` 44、`jaamas` 3。全文/扩展摘要是发表形式,不是研究类型;research 栏目不能证明每篇原始 main/special 投稿轨道。JAAMAS 保留期刊展示语义,不制造另一次独立审稿录用。 [AAAI 转投详细政策](https://cyprusconferences.org/aamas2026/call-for-papers-aaai-track/) 要求基于 AAAI-26 rejected 稿件;[总览](https://cyprusconferences.org/aamas2026/calls/) 却写 AAAI-25,须保留冲突。采集器保留 AAAI 栏目归属,不据此生成原 AAAI 投稿 ID、年份或逐篇拒稿决定。目录不是原始决定 note,未来关联仍需逐篇证据。 diff --git a/paper_atlas/collectors/aamas2026.py b/paper_atlas/collectors/aamas2026.py index 02be581..c8f908f 100644 --- a/paper_atlas/collectors/aamas2026.py +++ b/paper_atlas/collectors/aamas2026.py @@ -143,8 +143,6 @@ def parse_contents(html, evidence): 'raw_decision': retractions[0] if withdrawn else 'listed in official AAMAS 2026 published proceedings '+heading, 'metadata': metadata, 'tags': [{'namespace': 'aamas_proceedings:publication_format', 'value': publication_format}]}) - if withdrawn: - records[-1]['decision_date'] = '2026-06-08' if headers != list(SECTIONS) or dict(counts) != {k: v[3] for k, v in SECTIONS.items()}: raise ValueError('Publisher section inventory differs from reviewed 2026 layout') if (len(records), len(excluded), len(held)) != (639, 3, 1): diff --git a/tests/test_aamas2026.py b/tests/test_aamas2026.py index 0508b88..09e923b 100644 --- a/tests/test_aamas2026.py +++ b/tests/test_aamas2026.py @@ -3,10 +3,12 @@ import hashlib import json from pathlib import Path import tempfile +import sqlite3 import unittest from unittest.mock import patch from paper_atlas.collectors import aamas, aamas2026 +from paper_atlas.ingestion.records import ingest_file FIXTURE = json.loads(gzip.decompress((Path(__file__).parent/'fixtures/aamas2026-fixture.json.gz').read_bytes())) @@ -47,12 +49,33 @@ class Aamas2026Tests(unittest.TestCase): rows, _, _ = self.parse() row, = [r for r in rows if r['external_id'] == '2026/p3178'] self.assertEqual(row['status'], 'withdrawn') - self.assertEqual(row['decision_date'], '2026-06-08') + self.assertEqual(row['metadata']['withdrawal_date'], '2026-06-08') + self.assertNotIn('decision_date', row) self.assertEqual(row['raw_decision'], 'Withdrawn June 8, 2026') self.assertNotIn('paper_url', row['metadata']) self.assertEqual(row['metadata']['publication_state'], 'withdrawn') self.assertEqual(sum(r['status'] == 'accepted' for r in rows), 638) + def test_withdrawal_ingestion_retains_date_precision_without_invented_acceptance(self): + rows, _, _ = self.parse() + row, = [r for r in rows if r['external_id'] == '2026/p3178'] + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp); path = root/'withdrawn.jsonl'; db = root/'sample.sqlite' + path.write_text(json.dumps(row, ensure_ascii=False)+'\n') + path.with_suffix('.manifest.json').write_text(json.dumps({ + 'source': 'aamas_proceedings', 'list_url': aamas2026.URL, + 'venue': 'AAMAS', 'year': 2026, 'track': row['track'], + 'count': 1, 'status': 'partial', 'missing_abstract_count': 1, + 'file_sha256': hashlib.sha256(path.read_bytes()).hexdigest()})) + ingest_file(db, path) + with sqlite3.connect(db) as c: + self.assertEqual(c.execute('SELECT status,raw_value,decision_date FROM decisions').fetchall(), + [('withdrawn', 'Withdrawn June 8, 2026', None)]) + metadata = json.loads(c.execute('SELECT metadata_json FROM source_records').fetchone()[0]) + self.assertEqual(metadata['withdrawal_date'], '2026-06-08') + self.assertEqual(metadata['decision_date_precision'], 'day') + self.assertEqual(c.execute('PRAGMA foreign_key_check').fetchall(), []) + def test_retraction_is_not_accepted_or_withdrawn_and_retains_date(self): rows, _, held = self.parse() self.assertNotIn('2026/p238', {r['external_id'] for r in rows})