Files
NODEDC_MISSION_CORE/tests/test_e30_engineering_generation.py
T

159 lines
5.1 KiB
Python

from __future__ import annotations
import pytest
from k1link.compute.e30_engineering_generation import (
E30_ENGINEERING_DECISION_SCHEMA,
E30EngineeringGenerationError,
_validate_decision,
)
from k1link.web.e30_engineering_api import _validate_decisions
def _item() -> dict[str, object]:
return {
"sequence": 0,
"item_id": f"e30-review-item-{'a' * 64}",
"review_key": "geometry:100:0",
"stratum": "geometry-only",
}
def _decision(**overrides: object) -> dict[str, object]:
value: dict[str, object] = {
"schema_version": E30_ENGINEERING_DECISION_SCHEMA,
"sequence": 0,
"item_id": f"e30-review-item-{'a' * 64}",
"review_key": "geometry:100:0",
"source_stratum": "geometry-only",
"verdict": "confirmed",
"effective_stratum": "geometry-only",
"detector_assessment": "missed-object",
"projection_assessment": "aligned",
"point_ownership": "object",
"cause_code": "detector_error",
"confidence": 0.88,
"human_exception_required": False,
"exception_reason": None,
"review_prompt": None,
"evidence_note": "Visible object has geometry but no semantic observation.",
"review_sheet": {
"path": "geometry-only-01.jpg",
"sha256": "b" * 64,
"ordinal": 1,
},
}
value.update(overrides)
return value
def test_engineering_decision_supports_detector_miss_without_rewriting_a2() -> None:
validated = _validate_decision(
value=_decision(),
item=_item(),
reason_taxonomy=("detector_error", "unknown"),
expected_sheet={
"path": "geometry-only-01.jpg",
"sha256": "b" * 64,
"ordinal": 1,
},
)
assert validated["verdict"] == "confirmed"
assert validated["effective_stratum"] == "geometry-only"
assert validated["detector_assessment"] == "missed-object"
def test_engineering_uncertainty_must_route_a_bounded_exception() -> None:
with pytest.raises(
E30EngineeringGenerationError,
match="insufficient decision must route an exception",
):
_validate_decision(
value=_decision(
verdict="insufficient-evidence",
effective_stratum=None,
detector_assessment="insufficient-evidence",
confidence=0.48,
),
item=_item(),
reason_taxonomy=("detector_error", "unknown"),
expected_sheet={
"path": "geometry-only-01.jpg",
"sha256": "b" * 64,
"ordinal": 1,
},
)
def test_engineering_api_recomputes_distributions_from_all_486_decisions() -> None:
decisions = []
for sequence in range(486):
decision = _decision(
sequence=sequence,
item_id=f"e30-review-item-{sequence:064x}",
review_key=f"geometry:{sequence}:0",
)
decisions.append(decision)
decisions[-1] = {
**decisions[-1],
"verdict": "insufficient-evidence",
"effective_stratum": None,
"detector_assessment": "insufficient-evidence",
"projection_assessment": "not-assessable",
"point_ownership": "insufficient-evidence",
"cause_code": "unknown",
"confidence": 0.48,
"human_exception_required": True,
"exception_reason": "ambiguity",
"review_prompt": {
"question": "Is this an occupied physical object?",
"focus": "Inspect the selected white LiDAR cluster.",
"effects": {
"object-present": "Retain occupied geometry.",
"background-or-noise": "Reject the cluster.",
"insufficient-evidence": "Keep the item unknown.",
},
},
}
summary, causes = _validate_decisions(decisions)
assert summary["reviewed_item_count"] == 486
assert summary["human_exception_count"] == 1
assert summary["verdict_distribution"] == {
"confirmed": 485,
"insufficient-evidence": 1,
}
assert causes["reasons"] == [
{"reason_code": "detector_error", "count": 485},
{"reason_code": "unknown", "count": 1},
]
def test_engineering_exception_requires_a_specific_review_prompt() -> None:
with pytest.raises(
E30EngineeringGenerationError,
match="exception review prompt is invalid",
):
_validate_decision(
value=_decision(
verdict="insufficient-evidence",
effective_stratum=None,
detector_assessment="insufficient-evidence",
projection_assessment="not-assessable",
point_ownership="insufficient-evidence",
cause_code="unknown",
confidence=0.48,
human_exception_required=True,
exception_reason="ambiguity",
),
item=_item(),
reason_taxonomy=("detector_error", "unknown"),
expected_sheet={
"path": "geometry-only-01.jpg",
"sha256": "b" * 64,
"ordinal": 1,
},
)