|
254 | 254 | SUPPLEMENT_MANIFEST = "anonymous_supplement_manifest.csv" |
255 | 255 | SUPPLEMENT_ROOT = "diffaudit-evidence-paper" |
256 | 256 | REVIEW_SNAPSHOT_MANIFEST = "data/review_snapshot_manifest.csv" |
| 257 | +PHASE_G_LOCAL_AUDIT_EXCLUDED_PATHS = [ |
| 258 | + "data/manuscript_claim_audit.csv", |
| 259 | + "data/citation_context_audit.csv", |
| 260 | + "data/reference_integrity_audit.csv", |
| 261 | + "data/source_provenance.csv", |
| 262 | + "data/review_snapshot_manifest.csv", |
| 263 | +] |
257 | 264 | REVIEW_SNAPSHOT_FIELDS = [ |
258 | 265 | "schema_version", |
259 | 266 | "snapshot_kind", |
@@ -1987,6 +1994,37 @@ def validate_phase_g_manifest_inputs(paper: Path, manifest: dict, errors: list[s |
1987 | 1994 | require(not re.search(pattern, text, flags=re.IGNORECASE), f"{rel} contains private-surface pattern: {pattern}", errors) |
1988 | 1995 |
|
1989 | 1996 |
|
| 1997 | +def validate_phase_g_anonymous_exclusions(paper: Path, manifest: dict, errors: list[str]) -> None: |
| 1998 | + raw_excluded = manifest.get("anonymous_supplement_excluded", []) |
| 1999 | + require(isinstance(raw_excluded, list), "manifest.anonymous_supplement_excluded must be a list", errors) |
| 2000 | + if not isinstance(raw_excluded, list): |
| 2001 | + return |
| 2002 | + |
| 2003 | + excluded = {normalize_manifest_relpath(str(path), errors) for path in raw_excluded} |
| 2004 | + required = set(PHASE_G_LOCAL_AUDIT_EXCLUDED_PATHS) |
| 2005 | + missing = sorted(required - excluded) |
| 2006 | + require(not missing, f"Phase G anonymous supplement must exclude local/stale audit sidecars: {', '.join(missing)}", errors) |
| 2007 | + |
| 2008 | + build_dir = paper / "build" |
| 2009 | + manifest_path = build_dir / SUPPLEMENT_MANIFEST |
| 2010 | + if manifest_path.exists(): |
| 2011 | + rows = read_csv(manifest_path) |
| 2012 | + packaged_sources = {row.get("source_path", "") for row in rows} |
| 2013 | + packaged_archives = {row.get("archive_name", "") for row in rows} |
| 2014 | + for rel in PHASE_G_LOCAL_AUDIT_EXCLUDED_PATHS: |
| 2015 | + archive_name = f"{SUPPLEMENT_ROOT}/{rel}" |
| 2016 | + require(rel not in packaged_sources, f"{SUPPLEMENT_MANIFEST} packages excluded Phase G sidecar: {rel}", errors) |
| 2017 | + require(archive_name not in packaged_archives, f"{SUPPLEMENT_MANIFEST} packages excluded Phase G archive entry: {archive_name}", errors) |
| 2018 | + |
| 2019 | + zip_path = build_dir / SUPPLEMENT_ZIP |
| 2020 | + if zip_path.exists(): |
| 2021 | + with zipfile.ZipFile(zip_path, "r") as archive: |
| 2022 | + archive_entries = set(archive.namelist()) |
| 2023 | + for rel in PHASE_G_LOCAL_AUDIT_EXCLUDED_PATHS: |
| 2024 | + archive_name = f"{SUPPLEMENT_ROOT}/{rel}" |
| 2025 | + require(archive_name not in archive_entries, f"{SUPPLEMENT_ZIP} contains excluded Phase G sidecar: {archive_name}", errors) |
| 2026 | + |
| 2027 | + |
1990 | 2028 | def validate_phase_g_pdf(paper: Path, errors: list[str]) -> None: |
1991 | 2029 | pdf_path = paper / "paper.pdf" |
1992 | 2030 | require(pdf_path.exists(), "paper.pdf is missing", errors) |
@@ -2022,6 +2060,8 @@ def validate_phase_g_release_packet(paper: Path, errors: list[str]) -> None: |
2022 | 2060 | manifest = validate_manifest(paper, errors) |
2023 | 2061 | if manifest: |
2024 | 2062 | validate_phase_g_manifest_inputs(paper, manifest, errors) |
| 2063 | + validate_phase_g_anonymous_exclusions(paper, manifest, errors) |
| 2064 | + validate_optional_supplement_zip(paper, manifest, errors) |
2025 | 2065 | validate_phase_g_pdf(paper, errors) |
2026 | 2066 | validate_phase_g_latex_log(paper, errors) |
2027 | 2067 | validate_bibliography(paper, errors) |
|
0 commit comments