docs(accuracy): refresh governed scan and training evidence

This commit is contained in:
Jens
2026-08-30 06:00:57 +02:00
parent c272220277
commit 0e3c1b20e9
27 changed files with 88787 additions and 318 deletions
@@ -1,6 +1,7 @@
from __future__ import annotations
import argparse
import hashlib
import json
import os
import re
@@ -13,6 +14,14 @@ SUPPORTED_MODEL_SUFFIXES = {".pt", ".onnx", ".engine"}
ENV_KEYS = ("GEOINTEL_INSTALL_AI", "YOLO_ENABLED", "YOLO_MODELS_DIR", "YOLO_MODEL_PATH")
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def _asset_id(path: Path) -> str:
raw = f"{path.stem}-{path.suffix.lower().lstrip('.')}"
normalized = re.sub(r"[^a-z0-9]+", "-", raw.lower()).strip("-")
@@ -116,6 +125,36 @@ def _gate_failures(report: dict[str, Any], candidate: dict[str, Any]) -> list[st
return failures
def _governed_release_failures(
release_gate: dict[str, Any],
*,
candidate_key: str,
model_sha256: str,
) -> list[str]:
"""Require the Phase-4/5 product decision that the legacy gate never had."""
failures: list[str] = []
if release_gate.get("status") != "pass":
failures.append("phase4_release_gate_not_passed")
if release_gate.get("product_benchmark_status") != "pass":
failures.append("product_benchmark_not_passed")
if release_gate.get("promotion_allowed") is not True:
failures.append("governed_promotion_not_allowed")
if release_gate.get("phase_decision") not in {"done", "ready", "complete"}:
failures.append("phase5_not_ready")
if release_gate.get("candidate_key") != candidate_key:
failures.append("governed_candidate_key_mismatch")
recorded_sha256 = str(release_gate.get("candidate_model_sha256") or "").lower()
if not re.fullmatch(r"[0-9a-f]{64}", recorded_sha256):
failures.append("governed_candidate_model_sha256_missing")
elif recorded_sha256 != model_sha256:
failures.append("governed_candidate_model_sha256_mismatch")
benchmark_sha256 = str(release_gate.get("benchmark_manifest_sha256") or "").lower()
if not re.fullmatch(r"[0-9a-f]{64}", benchmark_sha256):
failures.append("governed_benchmark_manifest_sha256_missing")
return failures
def _resolve_model_asset(models_dir: Path, model_asset_id: str) -> Path | None:
for path in _candidate_paths(models_dir):
if _asset_id(path) == model_asset_id:
@@ -126,6 +165,7 @@ def _resolve_model_asset(models_dir: Path, model_asset_id: str) -> Path | None:
def _base_payload(args: argparse.Namespace) -> dict[str, Any]:
return {
"promotion_report": str(Path(args.promotion_report).resolve()),
"phase4_release_gate_report": str(Path(args.phase4_release_gate_report).resolve()),
"candidate_key": args.candidate_key,
"models_dir": str(Path(args.models_dir).resolve()),
"env_file": str(Path(args.env_file).resolve()),
@@ -188,6 +228,33 @@ def activate(args: argparse.Namespace) -> tuple[int, dict[str, Any]]:
)
return 2, payload
model_sha256 = _sha256(selected_model)
try:
release_gate_path = Path(args.phase4_release_gate_report)
release_gate = _load_report(release_gate_path)
except (OSError, ValueError, json.JSONDecodeError) as exc:
payload.update({"status": "invalid_phase4_release_gate", "message": str(exc)})
return 2, payload
governance_failures = _governed_release_failures(
release_gate,
candidate_key=args.candidate_key,
model_sha256=model_sha256,
)
if governance_failures:
payload.update(
{
"status": "governed_release_not_approved",
"message": (
"Candidate passed the legacy diagnostic gates but lacks a matching "
"successful governed product benchmark and Phase-4/5 release decision."
),
"rejection_reasons": governance_failures,
"selected_host_model_path": str(selected_model),
"selected_model_sha256": model_sha256,
}
)
return 3, payload
selected_container_path = _container_path(selected_model, models_dir, args.container_model_dir)
updates = {
"GEOINTEL_INSTALL_AI": "true",
@@ -200,7 +267,9 @@ def activate(args: argparse.Namespace) -> tuple[int, dict[str, Any]]:
"status": "ready_to_apply",
"message": "Promoted YOLO candidate validated. Re-run with --apply to update the environment file.",
"selected_host_model_path": str(selected_model),
"selected_model_sha256": model_sha256,
"selected_container_model_path": selected_container_path,
"phase4_release_gate_sha256": _sha256(release_gate_path),
"env_updates": updates,
"docker_restart_required": True,
}
@@ -241,6 +310,14 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
description="Activate an existing local YOLO model only after a promotion report recommends the exact candidate key."
)
parser.add_argument("--promotion-report", required=True, help="Path to detection_model_promotion_report.json.")
parser.add_argument(
"--phase4-release-gate-report",
required=True,
help=(
"Path to the governed Phase-4/5 release-gate report. It must bind the exact "
"candidate key and model SHA-256 and explicitly allow promotion."
),
)
parser.add_argument("--candidate-key", required=True, help="Exact promoted candidate key from the report.")
parser.add_argument(
"--models-dir",