#!/usr/bin/env python3 # -*- coding: utf-8 -*- from __future__ import annotations from pathlib import Path EXPECTED_PROJECT_VERSION = "0.4.7" EXPECTED_RUNTIME_VERSION = "0.4.7-production-audited-nav-name-conflict-omission" EXPECTED_BUILDER = "cm95pbf-builder/0.4.6-spatial-candidate-query" def fail(msg: str) -> None: print(f"FAIL: {msg}") raise SystemExit(2) def main() -> None: root = Path.cwd() pyproject = root / "pyproject.toml" init_py = root / "src" / "cm95pbf" / "__init__.py" release_py = root / "src" / "cm95pbf" / "release.py" builder_py = root / "src" / "cm95pbf" / "builder.py" for path in (pyproject, init_py, release_py, builder_py): if not path.exists(): fail(f"缺少文件: {path}") if f'version = "{EXPECTED_PROJECT_VERSION}"' not in pyproject.read_text(encoding="utf-8"): fail("project version 不正确") init_text = init_py.read_text(encoding="utf-8") if EXPECTED_RUNTIME_VERSION not in init_text: fail("runtime version 不正确") if EXPECTED_BUILDER not in init_text: fail("builder contract 被意外改变") release_text = release_py.read_text(encoding="utf-8") required = [ "AMBIGUOUS_DIRECT_NAMES_OMIT_LABEL_FAIL_CLOSED", "_collect_nav_name_conflict_expectations", "_observe_nav_name_conflict_feature", "_finalize_nav_name_conflict_audit", "ambiguous_conflict_was_labeled", 'failures.append("nav_name_conflict_audit")', '"nav_name_conflict_omissions"', '"nav_name_conflict_unique_outputs"', ] for fragment in required: if fragment not in release_text: fail(f"release gate 缺少: {fragment}") # Critical invariant: old unconditional nav_name_conflicts hard failure must be gone. if 'failures.append("nav_name_conflicts")' in release_text: fail("仍存在旧 nav_name_conflicts unconditional hard-fail") # Critical invariant: PBF builder stays byte-semantics compatible with v1.4.6 contract. builder_text = builder_py.read_text(encoding="utf-8") for fragment in [ '"POINT": ("chart_point_geometry", "spx_point_geom")', '"LINE": ("chart_line_geometry", "spx_line_geom")', '"AREA": ("chart_area_geometry", "spx_area_geom")', "FORCE INDEX ({spatial_index})", "STRAIGHT_JOIN chart_feature f ON f.id=g.feature_id", ]: if fragment not in builder_text: fail(f"v1.4.6 builder contract 缺少: {fragment}") try: import cm95pbf except Exception as exc: fail(f"无法 import cm95pbf: {exc}") if getattr(cm95pbf, "__version__", None) != EXPECTED_RUNTIME_VERSION: fail(f"installed runtime={getattr(cm95pbf, '__version__', None)!r}") if getattr(cm95pbf, "BUILDER_CONTRACT_VERSION", None) != EXPECTED_BUILDER: fail(f"installed builder={getattr(cm95pbf, 'BUILDER_CONTRACT_VERSION', None)!r}") print("CM95 PBF v1.4.7 preflight") print("=" * 72) print(f"Project version : {EXPECTED_PROJECT_VERSION} PASS") print(f"Runtime version : {EXPECTED_RUNTIME_VERSION} PASS") print(f"Builder contract REUSED : {EXPECTED_BUILDER} PASS") print("Existing v1.4.6 plan reusable : PASS") print("Ambiguous name policy : OMIT LABEL / FAIL CLOSED PASS") print("Trace/report count gate : PASS") print("PBF label-absence gate : PASS") print("No PBF rebuild required : PASS") print("OVERALL : PASS") if __name__ == "__main__": main()