tools(verify): fast/medium/full verification tiers with a compiled-in source stamp (L39); research R6
BuildLinux.sh hashes a sorted manifest of compiled inputs into VOXELFORGE_SOURCE_STAMP, printed first by every executable; Standalone/Tools/verify/verify.py checks it before and after each tier and records binary/input hashes and the resolved recipe, style map and layout. Fast (163 s) runs on the canonical owner world only and asserts FI Style 2 / SW Style 1; medium (8 min) and full (26 min) add the style matrix, GCC, determinism and cost. Controls: stale source, mislabelled style-0 owner, all-black capture, L30/L31, L35/L36 and the L38 step are all rejected. No geometry change; owner hashes identical to L37. Research R6: leak table, generator contract and a 10-step metre-native migration plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
88c54eab44
commit
753cc9c259
22 files changed
+1831
-163
No files matched your search
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reject empty and nearly black captures by decoding pixels and measuring coverage."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import math
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"]
|
||||
|
||||
|
||||
def inspect(path: Path) -> tuple[bool, str]:
|
||||
probe = subprocess.run([*LIMIT, "timeout", "30s", "ffmpeg", "-nostdin",
|
||||
"-hide_banner", "-loglevel", "error", "-i", str(path), "-frames:v", "1",
|
||||
"-f", "rawvideo", "-pix_fmt", "rgb24", "pipe:1"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30, check=False)
|
||||
if probe.returncode != 0 or not probe.stdout or len(probe.stdout) % 3:
|
||||
return False, f"decode_failed exit={probe.returncode} bytes={len(probe.stdout)}"
|
||||
raw = probe.stdout
|
||||
count = len(raw) // 3
|
||||
total = 0
|
||||
square_total = 0
|
||||
covered = 0
|
||||
for index in range(0, len(raw), 3):
|
||||
luminance = (77 * raw[index] + 150 * raw[index + 1] + 29 * raw[index + 2]) >> 8
|
||||
total += luminance
|
||||
square_total += luminance * luminance
|
||||
covered += luminance > 12
|
||||
mean = total / count
|
||||
variance = max(0.0, square_total / count - mean * mean)
|
||||
deviation = math.sqrt(variance)
|
||||
coverage = covered / count
|
||||
passed = deviation >= 2.0 and coverage >= 0.001
|
||||
return passed, (f"pixels={count} mean_luma={mean:.3f} stddev_luma={deviation:.3f} "
|
||||
f"coverage_luma_gt12={coverage:.5f} thresholds=(stddev>=2.0,coverage>=0.001)")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("image", type=Path)
|
||||
args = parser.parse_args()
|
||||
if not args.image.is_file():
|
||||
print(f"[CaptureQuality] image={args.image} status=FAIL reason=missing")
|
||||
return 1
|
||||
passed, detail = inspect(args.image)
|
||||
print(f"[CaptureQuality] image={args.image} {detail} status={'PASS' if passed else 'FAIL'}")
|
||||
return 0 if passed else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user