From f9f4d263af703cb1bd58d9f3a504226e8f1f15c8 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Sun, 8 Nov 2026 23:17:55 +0800 Subject: [PATCH] Expose independent event keys in integrated coverage reports --- docs/research-runtime.md | 5 +++++ paper_atlas/audits/coverage.py | 6 ++++-- tests/test_research_runtime.py | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/docs/research-runtime.md b/docs/research-runtime.md index 16bfac2..0959f7e 100644 --- a/docs/research-runtime.md +++ b/docs/research-runtime.md @@ -42,3 +42,8 @@ The production event-key migration and optional annotation activation have not o at preparation time. Existing migration/import/repair acceptance remains valid; do not rerun those jobs to install source code. Cross-feature tests use disposable fixtures and PostgreSQL schemas, never the production research tables. + +Coverage output also returns event_key for each independent edition ID. Two same-year +main events keep their own status/source counts; venue paper totals remain distinct +work counts rather than sums across events. Legacy datasets without the event column +return an empty event key and remain read-only compatible. diff --git a/paper_atlas/audits/coverage.py b/paper_atlas/audits/coverage.py index 42db2b8..0f7bf8d 100644 --- a/paper_atlas/audits/coverage.py +++ b/paper_atlas/audits/coverage.py @@ -45,6 +45,8 @@ def report(db, registry, *, pg_service=None, pg_schema=None): database, schema = identity[0], identity[1] else: database, schema = str(Path(db).resolve()), None + from paper_atlas.db.events import has_event_key + event = 'e.event_key' if has_event_key(connection) else "''" latest = _status_counts(connection, latest=True) observations = _status_counts(connection, latest=False) # Aggregate the paper join once for the whole snapshot. Repeating it @@ -73,9 +75,9 @@ def report(db, registry, *, pg_service=None, pg_schema=None): params = (acronym, acronym) editions = [] for row in connection.execute('''SELECT e.id,v.id AS venue_id,v.acronym AS canonical_venue, - e.year,e.track FROM editions e JOIN venues v ON v.id=e.venue_id + e.year,e.track,''' + event + ''' AS event_key FROM editions e JOIN venues v ON v.id=e.venue_id WHERE ''' + scope + ''' - ORDER BY e.year,e.track,v.acronym''', params): + ORDER BY e.year,e.track,event_key,v.acronym,e.id''', params): edition = dict(row) edition.update(edition_counts.get(row['id'], { 'submissions': 0, 'papers': 0, 'papers_without_abstract_text': 0})) diff --git a/tests/test_research_runtime.py b/tests/test_research_runtime.py index c451278..b5b96fc 100644 --- a/tests/test_research_runtime.py +++ b/tests/test_research_runtime.py @@ -10,6 +10,7 @@ import unittest import uuid from paper_atlas import querying +from paper_atlas.audits.coverage import report as coverage_report from paper_atlas.collectors.dblp import XML_SHA from paper_atlas.curation.annotations import initialize, assert_annotation, retract_annotation, observations from paper_atlas.db.backend import open_store @@ -88,6 +89,23 @@ class RuntimeCases: with redirect_stdout(io.StringIO()): ingest_file(self.target.get('db'),path,**{k:v for k,v in self.target.items() if k != 'db'}) + def test_coverage_labels_both_same_year_events_and_keeps_legacy_readable(self): + registry=self.root/'registry.json' + registry.write_text(json.dumps({'scope_note':'Fixture only','venues':[{'acronym':'WWW','field':'web'}]})) + def snapshot(): + return coverage_report(self.target.get('db'),registry,**{k:v for k,v in self.target.items() if k!='db'})['venues'][0] + self.assertEqual([e['event_key']for e in snapshot()['editions']],['']) + upgrade(plan(**self.target),**self.target) + with self.store() as s: + add(s,'spring','www-1995-spring','rejected');s.conn.commit() + result=snapshot();events={e['event_key']:e for e in result['editions']} + self.assertEqual(set(events),{'www-1995-fall','www-1995-spring'}) + self.assertEqual((result['imported_submissions'],result['distinct_papers']),(2,1)) + self.assertEqual(events['www-1995-fall']['latest_observed_status_counts']['accepted'],1) + self.assertEqual(events['www-1995-spring']['latest_observed_status_counts']['rejected'],1) + self.assertEqual(events['www-1995-fall']['source_record_counts'][0]['source'],'dblp') + self.assertEqual(events['www-1995-spring']['source_record_counts'][0]['source'],'fixture') + def test_incremental_parent_is_scoped_to_exact_event(self): upgrade(plan(**self.target), **self.target) self.ingest(self.collected('spring','www-1995-spring','spring-one'))