mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-30 17:16:16 +00:00
Includes: - n-dimensional generic modules (BraidStateN, MatrixN, SpectralN, ClassifyN, FisherRigidityN, FixedPointBridge) - Feasible Set Theorem proofs + QUBO relaxation - Anti-smuggle protocol (seedlock, mutation testing, cross_validate, qc_flag, symbol verification) - Q16_16 bridge with quad matrix representation - Infrastructure scripts (entry gate, determinism checks) - Test suites for Lean modules, scripts, and QUBO pipeline - FixedPoint migration and HachimojiN8 updates - Documentation updates (ARCHITECTURE, GLOSSARY, DOCUMENT_SETS) - QUBO conflict sweep and FSR validation - GitHub Actions anti-smuggle workflow Build: 3307 jobs, 0 errors
187 lines
7 KiB
Python
187 lines
7 KiB
Python
#!/usr/bin/env python3
|
|
"""check_determinism.py — Layer 0: verify reproducibility chain.
|
|
|
|
Checks:
|
|
1. Every artifact in extraction/ has a content_sha256 field that matches a
|
|
re-computation of the canonical JSON (sorted keys, no whitespace).
|
|
2. No Python shim calls unseeded RNG (np.random.default_rng() with no seed).
|
|
3. All --seed parameters default to 0.
|
|
|
|
Exit codes:
|
|
0 = All hash chains match (deterministic)
|
|
1 = Content hash mismatch
|
|
2 = Missing receipt or source file
|
|
3 = Seed-lock violation detected
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
def compute_file_sha256(path: Path) -> str:
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def compute_json_sha256(data: dict | list) -> str:
|
|
"""Compute SHA-256 of canonical JSON, excluding self-referential content_sha256 field."""
|
|
if isinstance(data, dict):
|
|
data = {k: v for k, v in data.items() if k not in ("content_sha256", "receipt_hash")}
|
|
canonical = json.dumps(data, sort_keys=True, separators=(",", ":"))
|
|
return hashlib.sha256(canonical.encode()).hexdigest()
|
|
|
|
|
|
def check_artifact_chain(receipt_dir: Path) -> dict[str, Any]:
|
|
"""Verify SHA-256 chain for all JSON artifacts in receipt_dir."""
|
|
results = {"checked": 0, "passed": 0, "failed": 0, "missing": 0, "artifacts": []}
|
|
|
|
for path in sorted(receipt_dir.glob("*.json")):
|
|
results["checked"] += 1
|
|
try:
|
|
data = json.loads(path.read_text())
|
|
except (json.JSONDecodeError, IOError):
|
|
results["failed"] += 1
|
|
results["artifacts"].append({"path": str(path), "status": "parse_error"})
|
|
continue
|
|
|
|
stored_hash = data.get("content_sha256") or data.get("receipt", {}).get("receipt_hash")
|
|
if not stored_hash:
|
|
results["missing"] += 1
|
|
results["artifacts"].append({"path": str(path), "status": "no_hash"})
|
|
continue
|
|
|
|
computed = compute_json_sha256(data)
|
|
if computed == stored_hash:
|
|
results["passed"] += 1
|
|
results["artifacts"].append({"path": str(path), "status": "match"})
|
|
else:
|
|
results["failed"] += 1
|
|
results["artifacts"].append({
|
|
"path": str(path), "status": "mismatch",
|
|
"stored": stored_hash[:16],
|
|
"computed": computed[:16],
|
|
})
|
|
|
|
return results
|
|
|
|
|
|
def scan_seed_violations(root_dirs: list[Path]) -> list[dict[str, Any]]:
|
|
"""Find unseeded RNG calls in Python shims."""
|
|
violations: list[dict[str, Any]] = []
|
|
pattern = re.compile(r"np\.random\.default_rng\(\s*\)")
|
|
|
|
for root in root_dirs:
|
|
for py_file in root.rglob("*.py"):
|
|
if ".lake" in str(py_file) or "__pycache__" in str(py_file):
|
|
continue
|
|
text = py_file.read_text()
|
|
# Check for unseeded numpy RNG
|
|
for match in pattern.finditer(text):
|
|
violations.append({
|
|
"file": str(py_file.relative_to(REPO_ROOT)),
|
|
"line": text[:match.start()].count("\n") + 1,
|
|
"code": match.group(),
|
|
"fix": "np.random.default_rng(seed) # where seed comes from --seed arg",
|
|
})
|
|
return violations
|
|
|
|
|
|
def check_shim_seed_params(root_dirs: list[Path]) -> list[dict[str, Any]]:
|
|
"""Verify all CLI entry points accept --seed parameter."""
|
|
issues: list[dict[str, Any]] = []
|
|
seed_arg_pattern = re.compile(r'"--seed"')
|
|
|
|
for root in root_dirs:
|
|
for py_file in root.rglob("*.py"):
|
|
if ".lake" in str(py_file) or "__pycache__" in str(py_file):
|
|
continue
|
|
text = py_file.read_text()
|
|
# Only check files that have argparse
|
|
if "argparse" not in text and "ArgumentParser" not in text:
|
|
continue
|
|
# Check if they have random/numpy RNG usage but no --seed
|
|
has_rng = "np.random" in text or "random.Random" in text
|
|
has_seed_arg = bool(seed_arg_pattern.search(text))
|
|
if has_rng and not has_seed_arg:
|
|
issues.append({
|
|
"file": str(py_file.relative_to(REPO_ROOT)),
|
|
"has_rng": True,
|
|
"has_seed_arg": False,
|
|
"fix": "Add parser.add_argument('--seed', type=int, default=0)",
|
|
})
|
|
return issues
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Layer 0: Deterministic Reproducibility Chain")
|
|
parser.add_argument("--seed", type=int, default=0, help="Seed for verification (default: 0)")
|
|
parser.add_argument("--receipt-dir", type=Path,
|
|
default=REPO_ROOT / "extraction",
|
|
help="Directory containing JSON artifacts")
|
|
parser.add_argument("--check-all", action="store_true", help="Run all checks")
|
|
parser.add_argument("--output", type=Path, default=None, help="Output receipt path")
|
|
args = parser.parse_args()
|
|
|
|
exit_code = 0
|
|
|
|
# Check 1: Hash chain integrity
|
|
print(f"[check] Verifying hash chain in {args.receipt_dir}")
|
|
chain = check_artifact_chain(args.receipt_dir)
|
|
if chain["failed"] > 0:
|
|
print(f" FAILED: {chain['failed']}/{chain['checked']} artifacts have hash mismatches")
|
|
exit_code = 1
|
|
else:
|
|
print(f" PASSED: {chain['passed']}/{chain['checked']} artifacts verified")
|
|
if chain["missing"] > 0:
|
|
print(f" WARNING: {chain['missing']} artifacts have no content_sha256 field")
|
|
|
|
# Check 2: Seed violations
|
|
print(f"[check] Scanning for unseeded RNG calls")
|
|
scan_dirs = [REPO_ROOT / "python", REPO_ROOT / "qubo"]
|
|
violations = scan_seed_violations([d for d in scan_dirs if d.exists()])
|
|
if violations:
|
|
print(f" FAILED: {len(violations)} unseeded RNG calls found")
|
|
for v in violations[:5]:
|
|
print(f" {v['file']}:{v['line']} {v['code']}")
|
|
exit_code = 3
|
|
else:
|
|
print(f" PASSED: No unseeded RNG calls")
|
|
|
|
# Check 3: Shims missing --seed
|
|
print(f"[check] Scanning for shims missing --seed parameter")
|
|
issues = check_shim_seed_params([d for d in scan_dirs if d.exists()])
|
|
if issues:
|
|
print(f" WARNING: {len(issues)} shims use RNG but lack --seed")
|
|
for i in issues:
|
|
print(f" {i['file']}")
|
|
else:
|
|
print(f" PASSED: All RNG-using shims have --seed")
|
|
|
|
# Generate output receipt if requested
|
|
if args.output:
|
|
receipt = {
|
|
"schema": "anti_smuggle_layer0_receipt_v1",
|
|
"seed": args.seed,
|
|
"hash_chain": chain,
|
|
"seed_violations": len(violations),
|
|
"missing_seed_params": len(issues),
|
|
"exit_code": exit_code,
|
|
}
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
args.output.write_text(json.dumps(receipt, indent=2))
|
|
print(f"[check] Receipt written to {args.output}")
|
|
|
|
sys.exit(exit_code)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|