Initial public release
GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s

This commit is contained in:
Jens
2026-08-31 21:56:53 +02:00
commit faeb58ef6d
1386 changed files with 263203 additions and 0 deletions
View File
View File
View File
+11
View File
@@ -0,0 +1,11 @@
# Test Fixtures
Fixtures should be tiny, deterministic and safe to commit.
Planned fixtures:
- geospatial/project_area.geojson
- vectors/reference_buildings.geojson
- vectors/predicted_buildings.geojson
- rasters/tiny_raster.tif or generated raster fixture in tests
See `docs/FIXTURE_STRATEGY.md`.
+9
View File
@@ -0,0 +1,9 @@
[
{
"class_id": 2,
"x_center": 0.95,
"y_center": 0.5,
"width": 0.2,
"height": -0.1
}
]
+9
View File
@@ -0,0 +1,9 @@
[
{
"class_id": 0,
"x_center": 0.5,
"y_center": 0.5,
"width": 0.2,
"height": 0.3
}
]
@@ -0,0 +1,24 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"native_id": "GRB-GBG-001",
"feature_status": "active"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[4.8470, 51.1550],
[4.8480, 51.1550],
[4.8480, 51.1560],
[4.8470, 51.1560],
[4.8470, 51.1550]
]
]
}
}
]
}
@@ -0,0 +1,24 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"native_id": "GRB-GBG-002",
"feature_status": "active"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[193277.5, 205708.3],
[193377.5, 205708.3],
[193377.5, 205808.3],
[193277.5, 205808.3],
[193277.5, 205708.3]
]
]
}
}
]
}
+3
View File
@@ -0,0 +1,3 @@
# tests/fixtures/geojson
Reserved for GeoIntel development assets. Do not commit large real datasets unless explicitly approved.
+13
View File
@@ -0,0 +1,13 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"name": "Demo AOI"},
"geometry": {
"type": "Polygon",
"coordinates": [[[5.0,51.0],[5.01,51.0],[5.01,51.01],[5.0,51.01],[5.0,51.0]]]
}
}
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "FeatureCollection",
"features": [
{"type":"Feature","properties":{"id":"det_1","class":"building","confidence":0.92},"geometry":{"type":"Polygon","coordinates":[[[5.0011,51.0011],[5.0031,51.0011],[5.0031,51.0031],[5.0011,51.0031],[5.0011,51.0011]]]}},
{"type":"Feature","properties":{"id":"det_fp","class":"building","confidence":0.61},"geometry":{"type":"Polygon","coordinates":[[[5.004,51.004],[5.005,51.004],[5.005,51.005],[5.004,51.005],[5.004,51.004]]]}}
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"type": "FeatureCollection",
"features": [
{"type":"Feature","properties":{"id":"ref_1","class":"building"},"geometry":{"type":"Polygon","coordinates":[[[5.001,51.001],[5.003,51.001],[5.003,51.003],[5.001,51.003],[5.001,51.001]]]}},
{"type":"Feature","properties":{"id":"ref_2","class":"building"},"geometry":{"type":"Polygon","coordinates":[[[5.006,51.006],[5.008,51.006],[5.008,51.008],[5.006,51.008],[5.006,51.006]]]}}
]
}
View File
View File
+3
View File
@@ -0,0 +1,3 @@
# tests/fixtures/rasters
Reserved for GeoIntel development assets. Do not commit large real datasets unless explicitly approved.
View File
+3
View File
@@ -0,0 +1,3 @@
# tests/fixtures/vectors
Reserved for GeoIntel development assets. Do not commit large real datasets unless explicitly approved.
View File
+72
View File
@@ -0,0 +1,72 @@
from __future__ import annotations
import importlib.util
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "scripts" / "run_accuracy_phase1_baseline.py"
SPEC = importlib.util.spec_from_file_location("accuracy_phase1_baseline", SCRIPT)
assert SPEC and SPEC.loader
MODULE = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(MODULE)
INFERENCE_SCRIPT = ROOT / "scripts" / "collect_accuracy_phase1_inference_smoke.py"
INFERENCE_SPEC = importlib.util.spec_from_file_location("accuracy_phase1_inference", INFERENCE_SCRIPT)
assert INFERENCE_SPEC and INFERENCE_SPEC.loader
INFERENCE_MODULE = importlib.util.module_from_spec(INFERENCE_SPEC)
INFERENCE_SPEC.loader.exec_module(INFERENCE_MODULE)
def test_sha256_file_is_stable(tmp_path: Path) -> None:
artifact = tmp_path / "manifest.json"
artifact.write_bytes(b'{"version":1}\n')
assert MODULE.sha256_file(artifact) == "50208d78350a7a160dec59a82df1499b6ca7da33e54c5eb11c97e342118e68bb"
def test_mirror_inventory_distinguishes_identical_and_drifted_files(tmp_path: Path) -> None:
(tmp_path / "geointel").mkdir()
(tmp_path / "same.txt").write_text("same", encoding="utf-8")
(tmp_path / "geointel" / "same.txt").write_text("same", encoding="utf-8")
(tmp_path / "drift.txt").write_text("root", encoding="utf-8")
(tmp_path / "geointel" / "drift.txt").write_text("mirror", encoding="utf-8")
tracked = {"same.txt", "drift.txt", "geointel/same.txt", "geointel/drift.txt"}
report = MODULE.mirror_inventory(tmp_path, tracked)
assert report["tracked_mirror_file_count"] == 2
assert report["paired_identical_file_count"] == 1
assert report["paired_different_file_count"] == 1
assert report["different_files"][0]["path"] == "drift.txt"
def test_artifact_roles_do_not_claim_images_are_models() -> None:
assert MODULE.artifact_role(Path("candidate.pt")) == "model_checkpoint"
assert MODULE.artifact_role(Path("split-manifest.json")) == "manifest"
assert MODULE.artifact_role(Path("contact_sheet_001.png")) == "visual_review"
assert MODULE.artifact_role(Path("orthophoto.tif")) == "raster"
def test_inference_summary_is_explicit_for_empty_and_non_empty_outputs() -> None:
assert INFERENCE_MODULE._summarize_detections([]) == {
"count": 0,
"class_counts": {},
"confidence": {"minimum": None, "maximum": None, "mean": None},
"sample": [],
}
detections = [
{"class_name": "building", "confidence": 0.8, "bbox": [1, 2, 3, 4]},
{"class_name": "building", "confidence": 0.4, "bbox": [5, 6, 7, 8]},
{"class_name": "shed", "confidence": 0.6, "bbox": [9, 10, 11, 12]},
]
summary = INFERENCE_MODULE._summarize_detections(detections)
assert summary["count"] == 3
assert summary["class_counts"] == {"building": 2, "shed": 1}
assert summary["confidence"] == {
"minimum": 0.4,
"maximum": 0.8,
"mean": 0.6,
}
assert summary["sample"] == detections
@@ -0,0 +1,26 @@
import pytest
from scripts.assess_belgium_building_training_iteration import (
INFERENCE_CONFIG_FIELDS,
assert_same_inference_config,
)
def test_regional_model_routes_are_frozen_in_inference_config() -> None:
assert "regional_models" in INFERENCE_CONFIG_FIELDS
calibration = {field: None for field in INFERENCE_CONFIG_FIELDS}
calibration["regional_models"] = {"flanders": "/models/flanders.pt"}
test = dict(calibration)
test["regional_models"] = {"flanders": "/models/other.pt"}
with pytest.raises(ValueError, match="regional_models"):
assert_same_inference_config(calibration, test, "test")
def test_regional_tile_counts_may_differ_between_splits() -> None:
calibration = {field: None for field in INFERENCE_CONFIG_FIELDS}
test = dict(calibration)
calibration["regional_model_tile_counts"] = {"flanders": 48}
test["regional_model_tile_counts"] = {"flanders": 64}
assert_same_inference_config(calibration, test, "test")
@@ -0,0 +1,50 @@
import pytest
from scripts.audit_yolo_cross_tile_repetition import (
interior_global_key,
tile_offsets,
)
from scripts.audit_yolo_label_relationships import Box
def test_tile_offsets_parse_exporter_filename() -> None:
assert tile_offsets("/data/geel_0005_r256_c512.png") == (256, 512)
with pytest.raises(ValueError, match="no row/column offsets"):
tile_offsets("/data/not-a-tile.png")
def test_interior_global_key_reconstructs_same_object_across_tiles() -> None:
first = Box(0, 0.75, 0.5, 0.1, 0.1)
second = Box(0, 0.25, 0.5, 0.1, 0.1)
first_key = interior_global_key(
first,
row_offset=0,
column_offset=0,
tile_size=512,
edge_tolerance_pixels=0.5,
)
second_key = interior_global_key(
second,
row_offset=0,
column_offset=256,
tile_size=512,
edge_tolerance_pixels=0.5,
)
assert first_key == second_key == (358.4, 230.4, 409.6, 281.6)
def test_interior_global_key_rejects_edge_clipped_box() -> None:
edge_box = Box(0, 0.05, 0.5, 0.1, 0.1)
assert (
interior_global_key(
edge_box,
row_offset=0,
column_offset=256,
tile_size=512,
edge_tolerance_pixels=0.5,
)
is None
)
+45
View File
@@ -0,0 +1,45 @@
from scripts.audit_yolo_label_outliers import classify_box
from scripts.audit_yolo_label_relationships import Box
DEFAULTS = {
"tile_size": 640,
"min_dimension_pixels": 4.0,
"extreme_aspect_ratio": 8.0,
"edge_tolerance_pixels": 0.5,
}
def test_classify_box_reports_independent_geometric_risks() -> None:
box = Box(0, 0.5, 0.003, 0.2, 0.006)
assert classify_box(box, **DEFAULTS) == [
{
"category": "small_dimension",
"width_px": 128.0,
"height_px": 3.84,
"area_px2": 491.52,
"aspect_ratio": 33.333333,
},
{
"category": "extreme_aspect_ratio",
"width_px": 128.0,
"height_px": 3.84,
"area_px2": 491.52,
"aspect_ratio": 33.333333,
},
{
"category": "tile_edge",
"edge_sides": ["top"],
"width_px": 128.0,
"height_px": 3.84,
"area_px2": 491.52,
"aspect_ratio": 33.333333,
},
]
def test_classify_box_ignores_ordinary_interior_box() -> None:
box = Box(0, 0.5, 0.5, 0.1, 0.08)
assert classify_box(box, **DEFAULTS) == []
@@ -0,0 +1,45 @@
from scripts.audit_yolo_label_relationships import Box, audit_boxes, classify_pair
DEFAULTS = {
"near_duplicate_iou": 0.9,
"containment_threshold": 0.98,
"max_nested_area_ratio": 4.0,
}
def test_classifies_exact_near_and_possible_nested_relationships() -> None:
exact = Box(0, 0.5, 0.5, 0.2, 0.2)
near = Box(0, 0.501, 0.5, 0.2, 0.2)
outer = Box(0, 0.5, 0.5, 0.18, 0.18)
inner = Box(0, 0.5, 0.5, 0.1, 0.1)
assert classify_pair(exact, exact, **DEFAULTS) == ("exact_duplicate", 1.0)
assert classify_pair(exact, near, **DEFAULTS)[0] == "near_duplicate"
assert classify_pair(outer, inner, **DEFAULTS) == ("possible_nested", 1.0)
def test_ignores_other_classes_and_non_overlapping_boxes() -> None:
first = Box(0, 0.2, 0.2, 0.1, 0.1)
other_class = Box(1, 0.2, 0.2, 0.1, 0.1)
distant = Box(0, 0.8, 0.8, 0.1, 0.1)
assert classify_pair(first, other_class, **DEFAULTS) is None
assert classify_pair(first, distant, **DEFAULTS) is None
def test_audit_boxes_returns_pair_indices_and_coordinates() -> None:
first = Box(0, 0.5, 0.5, 0.2, 0.2)
second = Box(0, 0.5, 0.5, 0.2, 0.2)
relationships = audit_boxes([first, second], **DEFAULTS)
assert relationships == [
{
"relationship": "exact_duplicate",
"score": 1.0,
"first_index": 0,
"second_index": 1,
"first_box": [0, 0.5, 0.5, 0.2, 0.2],
"second_box": [0, 0.5, 0.5, 0.2, 0.2],
}
]
+60
View File
@@ -0,0 +1,60 @@
from __future__ import annotations
import importlib.util
from pathlib import Path
import pytest
SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "build_regional_yolo_dataset.py"
SPEC = importlib.util.spec_from_file_location("build_regional_yolo_dataset", SCRIPT)
assert SPEC and SPEC.loader
module = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(module)
def test_regional_dataset_balances_contexts_and_keeps_validation_closed() -> None:
manifest = {"samples": [
{"sample_slug": "f-train", "region": "flanders", "split": "train", "context": "ribbon"},
{"sample_slug": "f-val", "region": "flanders", "split": "val", "context": "mixed"},
{"sample_slug": "w-train", "region": "wallonia", "split": "train", "context": "ribbon"},
]}
summary = {"tiles": [
{"sample_slug": "f-train", "split": "train", "image_path": "/f-pos.png", "kept": True},
{"sample_slug": "f-train", "split": "train", "image_path": "/f-neg.png", "is_negative": True},
{"sample_slug": "f-val", "split": "val", "image_path": "/f-val.png"},
{"sample_slug": "w-train", "split": "train", "image_path": "/w.png"},
]}
train, val, evidence = module.build(
summary=summary, manifest=manifest, region="flanders",
priority_contexts={"ribbon"}, priority_repeat=3, negative_repeat=2,
)
assert train == ["/f-pos.png"] * 3 + ["/f-neg.png"] * 2
assert val == ["/f-val.png"]
assert evidence["negative_train_entry_count"] == 2
assert evidence["protected_samples_in_training"] == []
@pytest.mark.parametrize("protected_split", ["calibration", "test", "background-test", "challenge"])
def test_regional_dataset_rejects_protected_tiles(protected_split: str) -> None:
manifest = {"samples": [
{"sample_slug": "f-cal", "region": "flanders", "split": protected_split, "context": "ribbon"},
]}
summary = {"tiles": [{"sample_slug": "f-cal", "split": protected_split, "image_path": "/cal.png"}]}
with pytest.raises(ValueError, match="protected"):
module.build(
summary=summary, manifest=manifest, region="flanders",
priority_contexts=set(), priority_repeat=1, negative_repeat=1,
)
def test_regional_dataset_rejects_manifest_protection_hidden_by_tile_split() -> None:
manifest = {"samples": [
{"sample_slug": "f-cal", "region": "flanders", "split": "calibration", "context": "ribbon"},
]}
summary = {"tiles": [{"sample_slug": "f-cal", "split": "train", "image_path": "/cal.png"}]}
with pytest.raises(ValueError, match="protected"):
module.build(
summary=summary, manifest=manifest, region="flanders",
priority_contexts=set(), priority_repeat=1, negative_repeat=1,
)
+290
View File
@@ -0,0 +1,290 @@
from __future__ import annotations
import hashlib
import importlib.util
import json
import sys
import types
from pathlib import Path
import pytest
from PIL import Image
ROOT = Path(__file__).resolve().parents[1]
def load(name: str):
path = ROOT / "scripts" / f"{name}.py"
spec = importlib.util.spec_from_file_location(name, path)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
miner = load("build_building_proposal_classifier_dataset")
trainer = load("train_building_proposal_classifier")
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def _write_json(path: Path, payload: dict) -> None:
path.write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8")
def _governed_proposal_crop_fixture(tmp_path: Path) -> tuple[Path, Path]:
"""Create a complete tiny crop release without importing Torch or YOLO."""
corpus_manifest = tmp_path / "corpus-manifest.json"
_write_json(corpus_manifest, {"samples": []})
corpus_sha256 = _sha256(corpus_manifest)
corpus_freeze = tmp_path / "corpus-freeze.json"
_write_json(corpus_freeze, {"immutable": True})
summary = tmp_path / "source-summary.json"
_write_json(summary, {"source_manifest_sha256": corpus_sha256, "tiles": []})
dataset_dir = tmp_path / "proposal-crops"
entries: list[dict] = []
for split in ("train", "val"):
for label, colour in (("negative", (0, 0, 0)), ("positive", (255, 255, 255))):
crop_path = dataset_dir / split / label / f"{split}-{label}.jpg"
crop_path.parent.mkdir(parents=True, exist_ok=True)
Image.new("RGB", (2, 2), colour).save(crop_path)
relative_path = crop_path.relative_to(dataset_dir).as_posix()
entries.append(
{
"relative_path": relative_path,
"sha256": _sha256(crop_path),
"size_bytes": crop_path.stat().st_size,
"split": split,
"label": label,
"sample_slug": f"{split}-{label}",
"proposal_index": 0,
"proposal_score": 0.8,
"source_box_xyxy": [0.0, 0.0, 1.0, 1.0],
"source_image_path": str(tmp_path / "source-image.tif"),
"source_image_sha256": "a" * 64,
"source_label_path": str(tmp_path / "source-label.txt"),
"source_label_sha256": "b" * 64,
}
)
entries.sort(key=lambda item: item["relative_path"])
counts = {f"{split}/{label}": 1 for split in ("train", "val") for label in ("negative", "positive")}
payload: dict = {
"schema_version": 1,
"status": "ok",
"immutable": True,
"dataset_kind": "building_proposal_classifier_crops",
"fixture_mode": False,
"governed_corpus_live_recheck": True,
"source": {
"corpus_manifest": {"path": str(corpus_manifest), "sha256": corpus_sha256},
"corpus_freeze": {"path": str(corpus_freeze), "sha256": _sha256(corpus_freeze)},
"summary": {
"path": str(summary),
"sha256": _sha256(summary),
"source_manifest_sha256": corpus_sha256,
},
"training_release": {
"dataset_yaml_path": "fixture-dataset.yaml",
"dataset_yaml_sha256": "d" * 64,
"corpus_manifest_sha256": corpus_sha256,
},
"proposal_model": {"path": str(tmp_path / "proposal.pt"), "sha256": "c" * 64},
},
"parameters": {"crop_scale": 1.4},
"counts": counts,
"sample_counts": {item["sample_slug"]: 1 for item in entries},
"tile_count": 2,
"crop_count": len(entries),
"crops_sha256": hashlib.sha256(trainer._canonical_json_bytes({"crops": entries})).hexdigest(),
"crops": entries,
}
payload["manifest_sha256"] = trainer._payload_sha256(payload)
_write_json(dataset_dir / trainer.PROPOSAL_DATASET_PROVENANCE_NAME, payload)
return dataset_dir, corpus_manifest
def test_classify_proposals_consumes_reference_once() -> None:
reference = [(0.0, 0.0, 10.0, 10.0)]
proposals = [((0.0, 0.0, 10.0, 10.0), 0.9), ((0.0, 0.0, 10.0, 10.0), 0.8)]
assert [item[0] for item in miner.classify_proposals(proposals, reference, 0.25)] == ["positive", "negative"]
@pytest.mark.parametrize("protected_split", ["calibration", "test", "background-test", "challenge"])
def test_eligible_tiles_rejects_protected_manifest_split(protected_split: str) -> None:
manifest = {"samples": [{"sample_slug": "x", "region": "flanders", "split": protected_split}]}
summary = {"tiles": [{"sample_slug": "x", "split": "train", "image_path": "x.png"}]}
with pytest.raises(ValueError, match="protected"):
miner.eligible_tiles(summary, manifest, "flanders")
def test_binary_metrics() -> None:
result = trainer.binary_metrics([0.9, 0.8, 0.2, 0.1], [1, 0, 1, 0])
assert result == {"tp": 1, "fp": 1, "fn": 1, "precision": 0.5, "recall": 0.5, "f1": 0.5}
def test_builder_rechecks_frozen_corpus_against_live_governed_state(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
observed: dict[str, object] = {}
def fake_assert(path: Path, **kwargs: object) -> dict:
observed["path"] = path
observed.update(kwargs)
return {"samples": []}
monkeypatch.setattr(miner, "assert_frozen_manifest_training_eligible", fake_assert)
manifest_path = tmp_path / "corpus.json"
manifest_path.write_text("{}", encoding="utf-8")
assert miner.load_governed_corpus_manifest(manifest_path, fixture_mode=False) == {"samples": []}
assert observed == {"path": manifest_path, "fixture_mode": False, "verify_live": True}
def test_builder_rejects_summary_not_bound_to_exact_corpus_manifest(tmp_path: Path) -> None:
manifest_path = tmp_path / "corpus.json"
manifest_path.write_text('{"samples": []}', encoding="utf-8")
with pytest.raises(ValueError, match="not bound"):
miner.assert_summary_source_manifest_binding({"source_manifest_sha256": "0" * 64}, manifest_path)
def test_builder_emits_immutable_checksum_bound_crop_provenance(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
class FakeTensor:
def __init__(self, values: list[list[float]] | list[float]) -> None:
self._values = values
def cpu(self) -> "FakeTensor":
return self
def tolist(self) -> list[list[float]] | list[float]:
return self._values
class FakeBoxes:
xyxy = FakeTensor([[40.0, 40.0, 60.0, 60.0], [0.0, 0.0, 10.0, 10.0]])
conf = FakeTensor([0.9, 0.8])
class FakeResult:
boxes = FakeBoxes()
class FakeYOLO:
def __init__(self, model: str) -> None:
self.model = model
def predict(self, sources: list[str], **_kwargs: object) -> list[FakeResult]:
return [FakeResult() for _source in sources]
corpus_manifest = tmp_path / "corpus-manifest.json"
manifest = {
"samples": [
{"sample_slug": "train-a", "split": "train", "region": "flanders"},
{"sample_slug": "val-b", "split": "val", "region": "flanders"},
]
}
_write_json(corpus_manifest, manifest)
_write_json(tmp_path / "corpus-freeze.json", {"immutable": True})
tiles: list[dict[str, object]] = []
for sample_slug, split in (("train-a", "train"), ("val-b", "val")):
image_path = tmp_path / f"{sample_slug}.png"
Image.new("RGB", (100, 100), (50, 100, 150)).save(image_path)
label_path = tmp_path / f"{sample_slug}.txt"
label_path.write_text("0 0.5 0.5 0.2 0.2\n", encoding="utf-8")
tiles.append(
{
"sample_slug": sample_slug,
"split": split,
"kept": True,
"image_path": str(image_path),
"label_path": str(label_path),
}
)
summary_path = tmp_path / "source-summary.json"
_write_json(
summary_path,
{
"source_manifest_sha256": _sha256(corpus_manifest),
"training_release_manifest": "fixture-training-release.json",
"training_release_manifest_sha256": "a" * 64,
"training_asset_manifest": "fixture-training-assets.json",
"tiles": tiles,
},
)
model_path = tmp_path / "proposal-model.pt"
model_path.write_bytes(b"proposal-model")
output_dir = tmp_path / "proposal-crops"
monkeypatch.setattr(miner, "load_governed_corpus_manifest", lambda *_args, **_kwargs: manifest)
monkeypatch.setattr(
miner,
"assert_yolo_summary_bound_to_embedded_training_release",
lambda **_kwargs: {
"dataset_yaml": {"path": "fixture-dataset.yaml", "sha256": "d" * 64},
"corpus": {"manifest_sha256": _sha256(corpus_manifest)},
},
)
monkeypatch.setitem(sys.modules, "ultralytics", types.SimpleNamespace(YOLO=FakeYOLO))
monkeypatch.setattr(
miner.sys,
"argv",
[
"build_building_proposal_classifier_dataset.py",
"--model",
str(model_path),
"--summary",
str(summary_path),
"--corpus-manifest",
str(corpus_manifest),
"--output-dir",
str(output_dir),
],
)
assert miner.main() == 0
provenance_path = output_dir / miner.PROPOSAL_DATASET_PROVENANCE_NAME
provenance = json.loads(provenance_path.read_text(encoding="utf-8"))
assert provenance["immutable"] is True
assert provenance["crop_count"] == 4
assert provenance["manifest_sha256"] == miner._immutable_payload_sha256(provenance)
assert all(_sha256(output_dir / item["relative_path"]) == item["sha256"] for item in provenance["crops"])
with pytest.raises(RuntimeError, match="immutable provenance"):
miner._write_immutable_json(provenance_path, {"different": True})
def test_trainer_validates_every_crop_and_source_binding_before_torch(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
dataset_dir, corpus_manifest = _governed_proposal_crop_fixture(tmp_path)
monkeypatch.setattr(
trainer,
"assert_yolo_summary_bound_to_embedded_training_release",
lambda **_kwargs: {
"dataset_yaml": {"path": "fixture-dataset.yaml", "sha256": "d" * 64},
"corpus": {"manifest_sha256": _sha256(corpus_manifest)},
},
)
payload = trainer.validate_proposal_dataset_provenance(dataset_dir, corpus_manifest, fixture_mode=False)
assert payload["crop_count"] == 4
crop = dataset_dir / "train" / "positive" / "train-positive.jpg"
crop.write_bytes(b"tampered")
with pytest.raises(trainer.ProposalDatasetProvenanceError, match="checksum"):
trainer.validate_proposal_dataset_provenance(dataset_dir, corpus_manifest, fixture_mode=False)
def test_trainer_rechecks_live_governed_corpus_before_pytorch(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
observed: dict[str, object] = {}
def fake_assert(path: Path, **kwargs: object) -> dict:
observed["path"] = path
observed.update(kwargs)
return {"samples": []}
monkeypatch.setattr(trainer, "assert_frozen_manifest_training_eligible", fake_assert)
manifest_path = tmp_path / "corpus.json"
manifest_path.write_text("{}", encoding="utf-8")
assert trainer.load_governed_corpus_manifest(manifest_path, fixture_mode=False) == {"samples": []}
assert observed == {"path": manifest_path, "fixture_mode": False, "verify_live": True}
@@ -0,0 +1,53 @@
import json
from pathlib import Path
import pytest
from scripts.combine_belgium_building_portfolio_specs import combine_specs
def write_spec(path: Path, slug: str, *, resolution: float = 0.25, status: str = "complete") -> Path:
path.write_text(json.dumps({
"status": status,
"side_m": 256.0,
"resolution_m": resolution,
"samples": [{"sample_slug": slug}],
}), encoding="utf-8")
return path
def test_combine_specs_records_provenance(tmp_path: Path) -> None:
payload = combine_specs([write_spec(tmp_path / "one.json", "one"), write_spec(tmp_path / "two.json", "two")])
assert payload["sample_count"] == 2
assert [sample["sample_slug"] for sample in payload["samples"]] == ["one", "two"]
assert all(len(source["sha256"]) == 64 for source in payload["source_specs"])
def test_combine_specs_rejects_duplicate_slugs(tmp_path: Path) -> None:
with pytest.raises(ValueError, match="Duplicate"):
combine_specs([write_spec(tmp_path / "one.json", "same"), write_spec(tmp_path / "two.json", "same")])
def test_combine_specs_rejects_mismatched_resolution(tmp_path: Path) -> None:
with pytest.raises(ValueError, match="resolution"):
combine_specs([write_spec(tmp_path / "one.json", "one"), write_spec(tmp_path / "two.json", "two", resolution=0.5)])
def test_combine_specs_rejects_incomplete_source(tmp_path: Path) -> None:
with pytest.raises(ValueError, match="not complete"):
combine_specs([write_spec(tmp_path / "one.json", "one", status="in_progress")])
def test_combine_specs_accepts_populated_legacy_v1_when_dimensions_come_from_complete_spec(tmp_path: Path) -> None:
legacy = tmp_path / "legacy.json"
legacy.write_text(json.dumps({"schema_version": 1, "samples": [{"sample_slug": "legacy"}]}), encoding="utf-8")
payload = combine_specs([legacy, write_spec(tmp_path / "current.json", "current")])
assert payload["sample_count"] == 2
assert payload["source_specs"][0]["source_status"] == "legacy_unstated"
def test_combine_specs_rejects_empty_legacy_v1(tmp_path: Path) -> None:
legacy = tmp_path / "legacy.json"
legacy.write_text(json.dumps({"schema_version": 1, "samples": []}), encoding="utf-8")
with pytest.raises(ValueError, match="not complete"):
combine_specs([legacy, write_spec(tmp_path / "current.json", "current")])
@@ -0,0 +1,21 @@
import pytest
from scripts.derive_yolo_min_dimension_corpus import filter_label_lines
def test_filter_label_lines_removes_only_rows_below_pixel_floor() -> None:
lines = [
"0 0.5 0.5 0.005 0.25",
"0 0.5 0.5 0.0078125 0.25",
"0 0.5 0.5 0.1 0.1",
]
kept, removed = filter_label_lines(lines, tile_size=512, min_dimension_pixels=4)
assert kept == lines[1:]
assert removed == [0]
def test_filter_label_lines_rejects_invalid_source_rows() -> None:
with pytest.raises(ValueError, match="invalid YOLO row"):
filter_label_lines(["0 0.5 0.5"], tile_size=512, min_dimension_pixels=4)
@@ -0,0 +1,49 @@
from pathlib import Path
from PIL import Image
from scripts.derive_yolo_nonoverlap_evaluation_view import (
image_has_low_visual_variance,
select_nonoverlap_tiles,
)
def tile(name: str, index: int, split: str = "val") -> dict[str, object]:
return {
"image_path": f"/data/sample_{index:04d}_{name}.png",
"tile_index": index,
"sample_slug": "sample",
"split": split,
"kept": True,
}
def test_select_nonoverlap_tiles_keeps_complete_512_grid() -> None:
tiles = [
tile("r0_c0", 0),
tile("r0_c256", 1),
tile("r0_c512", 2),
tile("r256_c0", 3),
tile("r256_c256", 4),
tile("r256_c512", 5),
tile("r512_c0", 6),
tile("r512_c256", 7),
tile("r512_c512", 8),
tile("r0_c0", 9, split="train"),
]
selected = select_nonoverlap_tiles(tiles, 512)
assert [item["tile_index"] for item in selected] == [0, 2, 6, 8]
def test_image_has_low_visual_variance_rejects_blank_no_data(tmp_path: Path) -> None:
blank = tmp_path / "blank.png"
real = tmp_path / "real.png"
Image.new("L", (8, 8), color=255).save(blank)
image = Image.new("L", (8, 8), color=100)
image.putpixel((0, 0), 120)
image.save(real)
assert image_has_low_visual_variance(blank, 3) is True
assert image_has_low_visual_variance(real, 3) is False
@@ -0,0 +1,23 @@
from pathlib import Path
import pytest
from scripts.evaluate_belgium_building_candidate import parse_regional_models
def test_parse_regional_models_accepts_explicit_unique_routes() -> None:
assert parse_regional_models(["flanders=/models/flanders.pt", "wallonia=/models/wallonia.pt"]) == {
"flanders": Path("/models/flanders.pt"),
"wallonia": Path("/models/wallonia.pt"),
}
@pytest.mark.parametrize("value", ["flanders", "=/model.pt", "flanders="])
def test_parse_regional_models_rejects_incomplete_routes(value: str) -> None:
with pytest.raises(ValueError, match="expected REGION"):
parse_regional_models([value])
def test_parse_regional_models_rejects_duplicate_routes() -> None:
with pytest.raises(ValueError, match="Duplicate regional model"):
parse_regional_models(["flanders=/first.pt", "FLANDERS=/second.pt"])
@@ -0,0 +1,228 @@
import json
import sys
from pathlib import Path
from scripts.evaluate_yolo_checkpoint_matrix import (
dataset_overlap_evidence,
main,
model_lineage_independence_evidence,
validate_pure_background_prefixes,
write_blocked_manifest,
)
def test_dataset_overlap_evidence_marks_repeated_validation_rows(
tmp_path: Path,
) -> None:
dataset_yaml = tmp_path / "dataset.yaml"
dataset_yaml.write_text("path: .\nval: images/val\n", encoding="utf-8")
(tmp_path / "yolo_tile_dataset_summary.json").write_text(
json.dumps({"tile_size": 512, "stride": 256}), encoding="utf-8"
)
evidence = dataset_overlap_evidence(dataset_yaml)
assert evidence["status"] == "overlapping"
assert evidence["overlap_pixels"] == 256
assert evidence["validation_tiles_non_overlapping"] is False
assert evidence["statistical_independence_established"] is False
def test_dataset_overlap_evidence_is_explicit_when_summary_missing(
tmp_path: Path,
) -> None:
evidence = dataset_overlap_evidence(tmp_path / "dataset.yaml")
assert evidence["status"] == "unavailable"
assert evidence["validation_tiles_non_overlapping"] is None
assert evidence["statistical_independence_established"] is False
def test_nonoverlap_does_not_overclaim_statistical_independence(
tmp_path: Path,
) -> None:
dataset_yaml = tmp_path / "dataset.yaml"
dataset_yaml.write_text("path: .\nval: images/val\n", encoding="utf-8")
(tmp_path / "yolo_tile_dataset_summary.json").write_text(
json.dumps({"tile_size": 512, "stride": 512}), encoding="utf-8"
)
evidence = dataset_overlap_evidence(dataset_yaml)
assert evidence["validation_tiles_non_overlapping"] is True
assert evidence["statistical_independence_established"] is False
assert "not established" in evidence["interpretation"]
def _write_summary(path: Path, rows: list[tuple[str, str]]) -> None:
path.write_text(
json.dumps(
{
"tile_size": 512,
"stride": 512,
"tiles": [
{"sample_slug": sample_slug, "split": split}
for sample_slug, split in rows
],
}
),
encoding="utf-8",
)
def test_model_lineage_independence_detects_exposure_in_every_split(
tmp_path: Path,
) -> None:
evaluation = tmp_path / "evaluation"
evaluation.mkdir()
dataset_yaml = evaluation / "dataset.yaml"
dataset_yaml.write_text("path: .\nval: images/val\n", encoding="utf-8")
_write_summary(
evaluation / "yolo_tile_dataset_summary.json",
[("turnhout", "val"), ("postel_bos", "val")],
)
active = tmp_path / "active.json"
challenger = tmp_path / "challenger.json"
_write_summary(active, [("postel_bos", "train"), ("turnhout", "val")])
_write_summary(
challenger, [("postel_bos", "train"), ("dessel", "train")]
)
evidence = model_lineage_independence_evidence(
dataset_yaml, [active, challenger]
)
assert evidence["status"] == "overlap"
assert evidence["overlapping_evaluation_samples"] == ["postel_bos", "turnhout"]
assert evidence["independent_for_all_supplied_lineage_corpora"] is False
assert [
row["overlapping_evaluation_samples"] for row in evidence["lineage_corpora"]
] == [["postel_bos", "turnhout"], ["postel_bos"]]
assert evidence["lineage_corpora"][0]["exposure_roles"]["turnhout"] == ["val"]
def test_model_lineage_independence_accepts_disjoint_samples(tmp_path: Path) -> None:
evaluation = tmp_path / "evaluation"
evaluation.mkdir()
dataset_yaml = evaluation / "dataset.yaml"
dataset_yaml.write_text("path: .\nval: images/val\n", encoding="utf-8")
_write_summary(
evaluation / "yolo_tile_dataset_summary.json", [("turnhout", "val")]
)
training = tmp_path / "training.json"
_write_summary(training, [("mol", "train")])
evidence = model_lineage_independence_evidence(dataset_yaml, [training])
assert evidence["status"] == "independent"
assert evidence["overlapping_evaluation_samples"] == []
assert evidence["independent_for_all_supplied_lineage_corpora"] is True
def test_model_lineage_independence_is_unavailable_without_ancestral_corpus(
tmp_path: Path,
) -> None:
evaluation = tmp_path / "evaluation"
evaluation.mkdir()
dataset_yaml = evaluation / "dataset.yaml"
dataset_yaml.write_text("path: .\nval: images/val\n", encoding="utf-8")
_write_summary(
evaluation / "yolo_tile_dataset_summary.json", [("turnhout", "val")]
)
evidence = model_lineage_independence_evidence(dataset_yaml, [])
assert evidence["status"] == "unavailable"
assert evidence["overlapping_evaluation_samples"] == []
assert evidence["independent_for_all_supplied_lineage_corpora"] is False
def test_blocked_manifest_records_that_models_and_gpu_were_not_used(
tmp_path: Path,
) -> None:
dataset_yaml = tmp_path / "dataset.yaml"
dataset_yaml.write_text("path: .\nval: images/val\n", encoding="utf-8")
output = tmp_path / "evidence" / "matrix.json"
write_blocked_manifest(
output,
dataset_yaml,
{
"status": "overlap",
"independent_for_all_supplied_lineage_corpora": False,
},
)
payload = json.loads(output.read_text(encoding="utf-8"))
assert payload["status"] == "blocked_model_lineage_sample_exposure"
assert payload["model_loading_attempted"] is False
assert payload["gpu_inference_attempted"] is False
def test_cli_blocks_lineage_validation_exposure_before_model_resolution(
tmp_path: Path, monkeypatch
) -> None:
evaluation = tmp_path / "evaluation"
images = evaluation / "images" / "val"
images.mkdir(parents=True)
(images / "turnhout_r0_c0.png").write_bytes(b"not opened before gate")
dataset_yaml = evaluation / "dataset.yaml"
dataset_yaml.write_text("path: .\nval: images/val\n", encoding="utf-8")
_write_summary(
evaluation / "yolo_tile_dataset_summary.json", [("turnhout", "val")]
)
ancestor = tmp_path / "ancestor.json"
_write_summary(ancestor, [("turnhout", "val"), ("mol", "train")])
output = tmp_path / "blocked.json"
monkeypatch.setattr(
sys,
"argv",
[
"evaluate_yolo_checkpoint_matrix.py",
"--dataset-yaml",
str(dataset_yaml),
"--model",
str(tmp_path / "model-is-never-resolved.pt"),
"--output",
str(output),
"--background-prefix",
"background",
"--lineage-summary",
str(ancestor),
"--require-lineage-sample-independence",
],
)
assert main() == 3
payload = json.loads(output.read_text(encoding="utf-8"))
assert payload["status"] == "blocked_model_lineage_sample_exposure"
assert payload["model_loading_attempted"] is False
def test_pure_background_prefix_rejects_nonempty_labels(tmp_path: Path) -> None:
image_dir = tmp_path / "images" / "val"
label_dir = tmp_path / "labels" / "val"
image_dir.mkdir(parents=True)
label_dir.mkdir(parents=True)
image = image_dir / "sparse_bg_0001.png"
image.write_bytes(b"image")
(label_dir / "sparse_bg_0001.txt").write_text(
"0 0.5 0.5 0.1 0.1\n", encoding="utf-8"
)
import pytest
with pytest.raises(ValueError, match="non-empty labels"):
validate_pure_background_prefixes([image], ("sparse_bg",))
def test_pure_background_prefix_accepts_empty_labels(tmp_path: Path) -> None:
image_dir = tmp_path / "images" / "val"
label_dir = tmp_path / "labels" / "val"
image_dir.mkdir(parents=True)
label_dir.mkdir(parents=True)
image = image_dir / "pure_bg_0001.png"
image.write_bytes(b"image")
(label_dir / "pure_bg_0001.txt").write_text("", encoding="utf-8")
assert validate_pure_background_prefixes([image], ("pure_bg",)) == [image]
+40
View File
@@ -0,0 +1,40 @@
from pathlib import Path
import pytest
from scripts.export_experimental_yolo_train_shard import (
is_canonical_train_window,
validate_experimental_request,
)
from scripts.train_experimental_yolo_candidate import validate_paths
from scripts.train_experimental_building_proposal_filter import validate_inputs
from scripts.compose_experimental_yolo_rehearsal_dataset import validate_sources
def test_export_refuses_non_experimental_output(tmp_path: Path) -> None:
manifest = tmp_path / "manifest.json"
manifest.write_text("{}", encoding="utf-8")
with pytest.raises(ValueError, match="output must remain"):
validate_experimental_request(manifest, tmp_path / "output")
def test_training_refuses_paths_outside_experimental_root(tmp_path: Path) -> None:
with pytest.raises(ValueError, match="must remain"):
validate_paths(tmp_path / "dataset", tmp_path / "output")
def test_train_shard_rejects_near_duplicate_edge_cover_windows() -> None:
canonical = {"row_off": 512, "col_off": 0, "height": 512, "width": 512}
edge_cover = {"row_off": 513, "col_off": 0, "height": 512, "width": 512}
assert is_canonical_train_window(canonical, 512)
assert not is_canonical_train_window(edge_cover, 512)
def test_proposal_filter_refuses_non_experimental_paths(tmp_path: Path) -> None:
with pytest.raises(ValueError, match="must remain"):
validate_inputs(tmp_path / "summary.json", tmp_path / "output")
def test_rehearsal_composer_refuses_non_experimental_output(tmp_path: Path) -> None:
with pytest.raises(ValueError, match="output must remain"):
validate_sources(tmp_path / "old.json", tmp_path / "new.json", tmp_path / "out")
@@ -0,0 +1,74 @@
import json
from pathlib import Path
import pytest
from scripts.export_yolo_diagnostic_evaluation_tiles import (
is_canonical_evaluation_window,
validate_diagnostic_manifest,
)
def _write_manifest(tmp_path: Path, *, split: str = "calibration") -> Path:
manifest = tmp_path / "operator_samples_manifest.json"
manifest.write_text(
json.dumps(
{
"purpose": "non_protected_diagnostic_evaluation",
"training_eligibility": {
"status": "not_eligible_evaluation_only"
},
"samples": [
{
"sample_slug": "fresh-aoi",
"split": split,
"sample_role": "positive",
}
],
}
),
encoding="utf-8",
)
import hashlib
digest = hashlib.sha256(manifest.read_bytes()).hexdigest()
(tmp_path / "NO_TRAINING.json").write_text(
json.dumps({"training_allowed": False, "manifest_sha256": digest}),
encoding="utf-8",
)
return manifest
def test_validate_diagnostic_manifest_accepts_bound_calibration(tmp_path: Path) -> None:
manifest = _write_manifest(tmp_path)
payload = validate_diagnostic_manifest(manifest)
assert payload["samples"][0]["sample_slug"] == "fresh-aoi"
def test_validate_diagnostic_manifest_rejects_training_split(tmp_path: Path) -> None:
manifest = _write_manifest(tmp_path, split="train")
with pytest.raises(ValueError, match="calibration-only"):
validate_diagnostic_manifest(manifest)
def test_validate_diagnostic_manifest_rejects_unbound_marker(tmp_path: Path) -> None:
manifest = _write_manifest(tmp_path)
(tmp_path / "NO_TRAINING.json").write_text(
json.dumps({"training_allowed": False, "manifest_sha256": "0" * 64}),
encoding="utf-8",
)
with pytest.raises(ValueError, match="not bound"):
validate_diagnostic_manifest(manifest)
def test_canonical_evaluation_window_rejects_overlapping_edge_cover() -> None:
assert is_canonical_evaluation_window(
{"row_off": 512, "col_off": 512, "height": 512, "width": 512}, 512
)
assert not is_canonical_evaluation_window(
{"row_off": 521, "col_off": 512, "height": 512, "width": 512}, 512
)
@@ -0,0 +1,93 @@
import json
from pathlib import Path
import pytest
from scripts.provision_belgium_building_training_portfolio import AOIS, load_custom_aois
V63_CANDIDATES = {
"aarschot-mixed-cal-candidate-v63",
"beveren-ribbon-cal-candidate-v63",
"oostkamp-suburban-cal-candidate-v63",
}
V66_CANDIDATES = {
"zutendaal-lowrise-cal-candidate-v66",
"zoersel-lowrise-cal-candidate-v66",
"landen-rural-cal-candidate-v66",
}
def test_portfolio_slugs_are_unique() -> None:
slugs = [aoi.slug for aoi in AOIS]
assert len(slugs) == len(set(slugs))
def test_v63_calibration_candidates_are_flemish_train_role_inputs() -> None:
candidates = {aoi.slug: aoi for aoi in AOIS if aoi.slug in V63_CANDIDATES}
assert set(candidates) == V63_CANDIDATES
assert all(aoi.region == "flanders" for aoi in candidates.values())
assert all(aoi.split == "train" for aoi in candidates.values())
assert all(aoi.sample_role == "positive" for aoi in candidates.values())
def test_v66_lowrise_candidates_are_flemish_train_role_inputs() -> None:
candidates = {aoi.slug: aoi for aoi in AOIS if aoi.slug in V66_CANDIDATES}
assert set(candidates) == V66_CANDIDATES
assert all(aoi.region == "flanders" for aoi in candidates.values())
assert all(aoi.split == "train" for aoi in candidates.values())
assert all("lowrise" in aoi.context for aoi in candidates.values())
def test_custom_aoi_spec_loads_non_protected_calibration(tmp_path: Path) -> None:
spec = tmp_path / "aois.json"
spec.write_text(
json.dumps(
{
"aois": [
{
"slug": "fresh-rural-cal",
"region": "wallonia",
"context": "rural-lowrise",
"split": "calibration",
"lon": 5.25,
"lat": 50.25,
}
]
}
),
encoding="utf-8",
)
result = load_custom_aois(spec)
assert len(result) == 1
assert result[0].slug == "fresh-rural-cal"
assert result[0].split == "calibration"
@pytest.mark.parametrize("split", ["test", "background-test"])
def test_custom_aoi_spec_rejects_protected_splits(
tmp_path: Path, split: str
) -> None:
spec = tmp_path / "aois.json"
spec.write_text(
json.dumps(
{
"aois": [
{
"slug": "forbidden",
"region": "flanders",
"context": "urban",
"split": split,
"lon": 4.5,
"lat": 51.0,
}
]
}
),
encoding="utf-8",
)
with pytest.raises(SystemExit, match="protected/unsupported split"):
load_custom_aois(spec)
@@ -0,0 +1,97 @@
import pytest
from scripts.render_operator_yolo_label_qa_contact_sheets import (
CONTACT_SHEET_NAME_TEMPLATE,
build_label_highlights,
build_relationship_highlights,
filter_tiles_by_samples,
)
TILES = [
{"sample_slug": "genk-industry-train"},
{"sample_slug": "lokeren-ribbon-train"},
{"sample_slug": "ostend-coastal-train"},
]
def test_filter_tiles_by_samples_keeps_only_explicit_samples() -> None:
assert filter_tiles_by_samples(
TILES, ["genk-industry-train", "ostend-coastal-train"]
) == [
TILES[0],
TILES[2],
]
def test_filter_tiles_by_samples_rejects_missing_sample() -> None:
with pytest.raises(ValueError, match="absent from summary"):
filter_tiles_by_samples(TILES, ["missing"])
def test_filter_tiles_by_samples_without_filter_preserves_tiles() -> None:
assert filter_tiles_by_samples(TILES, []) is TILES
def test_contact_sheet_name_template_is_stable_and_one_indexed() -> None:
assert CONTACT_SHEET_NAME_TEMPLATE.format(index=1) == "contact_sheet_001.png"
assert CONTACT_SHEET_NAME_TEMPLATE.format(index=12) == "contact_sheet_012.png"
def test_relationship_highlights_bind_indices_and_preserve_highest_priority() -> None:
summary = {
"flagged_tiles": [
{
"label_path": "/data/tile.txt",
"relationships": [
{
"relationship": "possible_nested",
"first_index": 2,
"second_index": 4,
},
{
"relationship": "exact_duplicate",
"first_index": 2,
"second_index": 5,
},
{
"relationship": "near_duplicate",
"first_index": 6,
"second_index": 7,
},
],
}
]
}
assert build_relationship_highlights(summary) == {
"/data/tile.txt": {
2: "exact_duplicate",
4: "possible_nested",
5: "exact_duplicate",
6: "near_duplicate",
7: "near_duplicate",
}
}
def test_label_highlights_support_outliers_with_stable_priority() -> None:
summary = {
"flagged_tiles": [
{
"label_path": "/data/tile.txt",
"outliers": [
{"category": "tile_edge", "index": 3},
{"category": "small_dimension", "index": 3},
{"category": "extreme_aspect_ratio", "index": 4},
],
}
]
}
assert build_label_highlights(summary) == {
"/data/tile.txt": {
3: "small_dimension",
4: "extreme_aspect_ratio",
}
}