From bd6a9e84d68054be8a1ad391b6d6c9b9f5d35c39 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Tue, 14 Jul 2026 19:57:46 +0800 Subject: [PATCH] add strict external parity release gate --- docs/research/pre_work_error_ledger.md | 1 + scripts/run_quality_gate.py | 10 +++++++--- scripts/three_engine_parity_replay_validator.py | 6 ++++-- tests/test_release_hygiene_contract.py | 2 ++ .../test_three_engine_parity_replay_validator.py | 15 +++++++++++++++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/research/pre_work_error_ledger.md b/docs/research/pre_work_error_ledger.md index 8bd0643d..fa21b4bd 100644 --- a/docs/research/pre_work_error_ledger.md +++ b/docs/research/pre_work_error_ledger.md @@ -92,6 +92,7 @@ For large architecture or release work, also read: | ERR-059 | Gulika was either an approximate fallback or falsely implied as a chart module output. | mitigated 2026-07-14 | `scripts/gulika.py` computes Prasna Marga Ghatika segment Ascendant with Swiss sunrise/sunset and Lahiri sidereal houses. It is exposed only as `prashna_context.supporting_indicators.gulika`, remains `partial`, and cannot unlock Sphuta or verdict layers until external numeric parity exists. | | ERR-060 | Legacy Sphuta functions combined approximate Gulika with interpretive signals, while the exact formula could not be inspected in the production question context. | mitigated 2026-07-14 | `prashna_sphuta.py` exposes formula-only Trisphuta/Catusphuta/Pancasphuta from the partial Gulika evidence. It is supporting-only; Kunda, life-sensitive Sphutas and Prashna verdicts remain blocked pending external numeric parity. | | ERR-061 | Full-reading passed longitude-only data to the Tajika layer, permanently blocking its speed-dependent seven-planet interaction evidence. | mitigated 2026-07-14 | Pass actual Swiss longitude/speed pairs. The output may expose only partial Ithasala/Easarapha candidates; named chains and event verdicts stay blocked pending golden cases. | +| ERR-062 | A release gate could validate a parity manifest's shape without requiring all external engines to actually match, allowing “contract valid” to be mistaken for “oracle verified.” | mitigated 2026-07-14 | `three_engine_parity_replay_validator.py --require-pass` fails unless parity status is pass; `run_quality_gate.py --require-external-parity` exposes this as an explicit high-standard release requirement. | ## Fragment Sweep Command Set diff --git a/scripts/run_quality_gate.py b/scripts/run_quality_gate.py index e6a2faaa..8a420f51 100644 --- a/scripts/run_quality_gate.py +++ b/scripts/run_quality_gate.py @@ -378,7 +378,7 @@ def git_untracked_files() -> set[str]: return {line.strip() for line in completed.stdout.splitlines() if line.strip()} -def release_hygiene_check() -> None: +def release_hygiene_check(require_external_parity: bool = False) -> None: print("\n== Release hygiene check ==") untracked = git_untracked_files() critical = [path for path in RELEASE_CRITICAL_UNTRACKED_PATHS if path in untracked] @@ -393,7 +393,10 @@ def release_hygiene_check() -> None: raise SystemExit(1) run([PYTHON, "scripts/public_release_privacy_scan.py", "--json"]) run([PYTHON, "scripts/report_renderer_isolation_poc.py", "--strict"]) - run([PYTHON, "scripts/three_engine_parity_replay_validator.py", "references/oracle/three_engine_parity_replay_manifest.json"]) + parity_command = [PYTHON, "scripts/three_engine_parity_replay_validator.py", "references/oracle/three_engine_parity_replay_manifest.json"] + if require_external_parity: + parity_command.append("--require-pass") + run(parity_command) print("release_hygiene_check ok: no release-critical product files are untracked") @@ -496,6 +499,7 @@ def main() -> int: parser.add_argument("--frontend-click-mode", choices=["core", "mobile", "offline", "pdf", "workspace", "mobile-trust", "import-files", "all"], default=None, help="Browser click smoke mode for browser/release profiles") parser.add_argument("--frontend-click-timeout", type=int, default=240, help="Timeout seconds for browser click smoke") parser.add_argument("--all-tests", action="store_true", help="Run every pytest file, including optional-dependency suites") + parser.add_argument("--require-external-parity", action="store_true", help="Fail the release gate unless the three-engine raw parity manifest passes.") args = parser.parse_args() profile = run_profile(args) @@ -525,7 +529,7 @@ def main() -> int: run([PYTHON, "scripts/character_level_inventory_manifest.py", "--scope", "project", "--no-write", "--summary-only"]) run([PYTHON, "scripts/deployment_preflight.py"]) if profile["check_release_hygiene"]: - release_hygiene_check() + release_hygiene_check(require_external_parity=args.require_external_parity) run([PYTHON, "scripts/validate_bphs_invariants.py"]) if args.all_tests: pytest_targets = ["tests"] diff --git a/scripts/three_engine_parity_replay_validator.py b/scripts/three_engine_parity_replay_validator.py index 74b18b42..39081435 100644 --- a/scripts/three_engine_parity_replay_validator.py +++ b/scripts/three_engine_parity_replay_validator.py @@ -119,9 +119,11 @@ def validate_manifest(path: str | Path) -> dict[str, Any]: def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("manifest", nargs="?", default="references/oracle/three_engine_parity_replay_manifest.json") + parser.add_argument("--require-pass", action="store_true", help="Return nonzero unless all comparison rows pass.") args = parser.parse_args(argv) - print(json.dumps(validate_manifest(args.manifest), ensure_ascii=False, indent=2, sort_keys=True)) - return 0 + report = validate_manifest(args.manifest) + print(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)) + return 0 if not args.require_pass or report["status"] == "pass" else 1 if __name__ == "__main__": diff --git a/tests/test_release_hygiene_contract.py b/tests/test_release_hygiene_contract.py index 7203f5f2..d66e7bcd 100644 --- a/tests/test_release_hygiene_contract.py +++ b/tests/test_release_hygiene_contract.py @@ -6,3 +6,5 @@ def test_release_profile_requires_privacy_and_renderer_probes() -> None: assert '"scripts/public_release_privacy_scan.py", "--json"' in source assert '"scripts/report_renderer_isolation_poc.py", "--strict"' in source assert '"scripts/three_engine_parity_replay_validator.py"' in source + assert '"--require-external-parity"' in source + assert 'parity_command.append("--require-pass")' in source diff --git a/tests/test_three_engine_parity_replay_validator.py b/tests/test_three_engine_parity_replay_validator.py index a42c65d0..b7c9a266 100644 --- a/tests/test_three_engine_parity_replay_validator.py +++ b/tests/test_three_engine_parity_replay_validator.py @@ -2,6 +2,9 @@ from __future__ import annotations import hashlib import json +import subprocess +import sys +from pathlib import Path from pathlib import Path from scripts.three_engine_parity_replay_validator import validate_manifest @@ -54,3 +57,15 @@ def test_three_engine_parity_validator_accepts_one_same_chart_row(tmp_path: Path assert result["tested"] is True assert result["comparison_row_count"] == 1 assert result["match_count"] == 1 + + +def test_validator_require_pass_rejects_blocked_manifest() -> None: + root = Path(__file__).resolve().parents[1] + completed = subprocess.run( + [sys.executable, "scripts/three_engine_parity_replay_validator.py", "--require-pass"], + cwd=root, + capture_output=True, + text=True, + check=False, + ) + assert completed.returncode == 1