docs(accuracy): refresh governed scan and training evidence
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
@@ -51,11 +52,27 @@ def _write_report(path: Path, *, promotion_status: str = "promote_candidate") ->
|
||||
)
|
||||
|
||||
|
||||
def _write_governed_release_gate(path: Path, model_file: Path, **overrides: object) -> None:
|
||||
payload: dict[str, object] = {
|
||||
"status": "pass",
|
||||
"product_benchmark_status": "pass",
|
||||
"promotion_allowed": True,
|
||||
"phase_decision": "ready",
|
||||
"candidate_key": CANDIDATE_KEY,
|
||||
"candidate_model_sha256": hashlib.sha256(model_file.read_bytes()).hexdigest(),
|
||||
"benchmark_manifest_sha256": "b" * 64,
|
||||
}
|
||||
payload.update(overrides)
|
||||
path.write_text(json.dumps(payload), encoding="utf-8")
|
||||
|
||||
|
||||
def _run_activation(tmp_path: Path, *extra_args: str) -> subprocess.CompletedProcess[str]:
|
||||
models_dir = tmp_path / "models"
|
||||
_write_model(models_dir)
|
||||
model_file = _write_model(models_dir)
|
||||
report_path = tmp_path / "promotion_report.json"
|
||||
_write_report(report_path)
|
||||
release_gate_path = tmp_path / "phase4-release-gate.json"
|
||||
_write_governed_release_gate(release_gate_path, model_file)
|
||||
env_file = tmp_path / ".env"
|
||||
env_file.write_text("GEOINTEL_ENV=production\nYOLO_ENABLED=false\n", encoding="utf-8")
|
||||
|
||||
@@ -67,6 +84,8 @@ def _run_activation(tmp_path: Path, *extra_args: str) -> subprocess.CompletedPro
|
||||
str(report_path),
|
||||
"--candidate-key",
|
||||
CANDIDATE_KEY,
|
||||
"--phase4-release-gate-report",
|
||||
str(release_gate_path),
|
||||
"--models-dir",
|
||||
str(models_dir),
|
||||
"--container-model-dir",
|
||||
@@ -94,6 +113,9 @@ def test_promoted_yolo_activation_dry_run_validates_report_and_model(tmp_path: P
|
||||
assert payload["will_download_models"] is False
|
||||
assert payload["candidate"]["candidate_key"] == CANDIDATE_KEY
|
||||
assert payload["candidate"]["threshold"] == 0.35
|
||||
assert payload["selected_model_sha256"] == hashlib.sha256(
|
||||
(tmp_path / "models" / "geointel-building-yolov8s-aoi1024bg512r3e50.pt").read_bytes()
|
||||
).hexdigest()
|
||||
assert payload["env_updates"]["YOLO_ENABLED"] == "true"
|
||||
assert payload["env_updates"]["YOLO_MODEL_PATH"] == "/app/models/geointel-building-yolov8s-aoi1024bg512r3e50.pt"
|
||||
|
||||
@@ -114,9 +136,11 @@ def test_promoted_yolo_activation_apply_updates_env_file(tmp_path: Path) -> None
|
||||
|
||||
def test_promoted_yolo_activation_rejects_non_promoted_report(tmp_path: Path) -> None:
|
||||
models_dir = tmp_path / "models"
|
||||
_write_model(models_dir)
|
||||
model_file = _write_model(models_dir)
|
||||
report_path = tmp_path / "promotion_report.json"
|
||||
_write_report(report_path, promotion_status="reject")
|
||||
release_gate_path = tmp_path / "phase4-release-gate.json"
|
||||
_write_governed_release_gate(release_gate_path, model_file)
|
||||
|
||||
result = subprocess.run(
|
||||
[
|
||||
@@ -126,6 +150,8 @@ def test_promoted_yolo_activation_rejects_non_promoted_report(tmp_path: Path) ->
|
||||
str(report_path),
|
||||
"--candidate-key",
|
||||
CANDIDATE_KEY,
|
||||
"--phase4-release-gate-report",
|
||||
str(release_gate_path),
|
||||
"--models-dir",
|
||||
str(models_dir),
|
||||
"--env-file",
|
||||
@@ -145,6 +171,52 @@ def test_promoted_yolo_activation_rejects_non_promoted_report(tmp_path: Path) ->
|
||||
assert "rejection_reasons" in payload
|
||||
|
||||
|
||||
def test_promoted_yolo_activation_rejects_failed_or_unbound_phase4_gate(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
models_dir = tmp_path / "models"
|
||||
model_file = _write_model(models_dir)
|
||||
report_path = tmp_path / "promotion_report.json"
|
||||
_write_report(report_path)
|
||||
release_gate_path = tmp_path / "phase4-release-gate.json"
|
||||
_write_governed_release_gate(
|
||||
release_gate_path,
|
||||
model_file,
|
||||
status="fail",
|
||||
promotion_allowed=False,
|
||||
candidate_model_sha256="0" * 64,
|
||||
)
|
||||
|
||||
result = subprocess.run(
|
||||
[
|
||||
"python",
|
||||
str(SCRIPT),
|
||||
"--promotion-report",
|
||||
str(report_path),
|
||||
"--phase4-release-gate-report",
|
||||
str(release_gate_path),
|
||||
"--candidate-key",
|
||||
CANDIDATE_KEY,
|
||||
"--models-dir",
|
||||
str(models_dir),
|
||||
"--env-file",
|
||||
str(tmp_path / ".env"),
|
||||
"--json",
|
||||
],
|
||||
cwd=ROOT,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
check=False,
|
||||
)
|
||||
|
||||
assert result.returncode == 3
|
||||
payload = json.loads(result.stdout)
|
||||
assert payload["status"] == "governed_release_not_approved"
|
||||
assert "phase4_release_gate_not_passed" in payload["rejection_reasons"]
|
||||
assert "governed_candidate_model_sha256_mismatch" in payload["rejection_reasons"]
|
||||
|
||||
|
||||
def test_readiness_gate_compiles_promoted_activation_script() -> None:
|
||||
readiness = (ROOT / "scripts" / "run_readiness_check.sh").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user