Gate filtered YOLO candidate and harden provenance
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-07-12 23:03:55 +02:00
parent c9b22f8f8b
commit 8daaa071b0
10 changed files with 112 additions and 7 deletions
+3 -1
View File
@@ -337,7 +337,9 @@ docker exec \
The training wrapper is intentionally outside the product UI. It runs
Ultralytics from the existing runtime, copies the best trained artifact to
`TRAIN_MODEL_OUTPUT_PATH` and writes `training_summary.json`. Afterward, treat
`TRAIN_MODEL_OUTPUT_PATH` and writes `training_summary.json`. The summary records
SHA256 provenance for `dataset.yaml`, the available YOLO dataset summary, the
local base model and the copied trained model. Afterward, treat
the resulting `.pt` file like any other local model asset: verify preflight,
run the real-data matrix and compare persisted QA/QC metrics before activating
it as a useful default.
+25
View File
@@ -82,12 +82,21 @@ mkdir -p "${TRAIN_OUTPUT_DIR}" "$(dirname "${TRAIN_MODEL_OUTPUT_PATH}")"
"${PYTHON_BIN}" - <<'PY'
from __future__ import annotations
import hashlib
import json
import os
import shutil
from pathlib import Path
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def seed_ultralytics_font() -> None:
font_candidates = [
Path("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"),
@@ -141,6 +150,17 @@ if not best_path.exists():
raise SystemExit(f"Expected trained model artifact was not created: {best_path}")
shutil.copy2(best_path, trained_model_output_path)
dataset_summary_path = next(
(
candidate
for candidate in (
dataset_yaml.parent / "yolo_tile_dataset_summary.json",
dataset_yaml.parent / "yolo_dataset_summary.json",
)
if candidate.is_file()
),
None,
)
summary = {
"status": "ok",
"dataset_yaml": str(dataset_yaml),
@@ -149,6 +169,11 @@ summary = {
"train_run_name": run_name,
"trained_model_path": str(trained_model_output_path),
"best_artifact_path": str(best_path),
"dataset_yaml_sha256": sha256_file(dataset_yaml),
"dataset_summary_path": str(dataset_summary_path) if dataset_summary_path else None,
"dataset_summary_sha256": sha256_file(dataset_summary_path) if dataset_summary_path else None,
"base_model_sha256": sha256_file(base_model_path),
"trained_model_sha256": sha256_file(trained_model_output_path),
"epochs": epochs,
"image_size": image_size,
"batch_size": batch_size,