feat(lab): freeze RAVNOVES00 R0 acceptance contract
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import Counter
|
||||
|
||||
import pytest
|
||||
|
||||
from k1link.compute.e37_acceptance_contract import (
|
||||
E37AcceptanceContractError,
|
||||
assign_split,
|
||||
derive_reference_labels,
|
||||
)
|
||||
|
||||
|
||||
def _decision(
|
||||
*,
|
||||
detector: str,
|
||||
ownership: str,
|
||||
cause: str | None = None,
|
||||
effective_stratum: str | None = "agree",
|
||||
) -> dict[str, object]:
|
||||
return {
|
||||
"detector_assessment": detector,
|
||||
"point_ownership": ownership,
|
||||
"cause_code": cause,
|
||||
"effective_stratum": effective_stratum,
|
||||
}
|
||||
|
||||
|
||||
def test_r0_reference_projection_keeps_dimensions_independent() -> None:
|
||||
assert derive_reference_labels(
|
||||
_decision(detector="valid", ownership="object"),
|
||||
None,
|
||||
) == ("object-present", "object-associated", "current")
|
||||
assert derive_reference_labels(
|
||||
_decision(
|
||||
detector="false-positive",
|
||||
ownership="surface-or-background",
|
||||
cause="time_mismatch",
|
||||
),
|
||||
None,
|
||||
) == ("background-or-noise", "rejected-nonobject", "stale")
|
||||
assert derive_reference_labels(
|
||||
_decision(
|
||||
detector="not-applicable",
|
||||
ownership="insufficient-support",
|
||||
effective_stratum="camera-only",
|
||||
),
|
||||
None,
|
||||
) == ("unknown", "insufficient-support", "unavailable")
|
||||
|
||||
|
||||
def test_human_exception_only_overrides_the_ambiguous_reference() -> None:
|
||||
ambiguous = _decision(
|
||||
detector="insufficient-evidence",
|
||||
ownership="insufficient-evidence",
|
||||
effective_stratum=None,
|
||||
)
|
||||
assert derive_reference_labels(ambiguous, "object-present") == (
|
||||
"occupied-environment",
|
||||
"independent-occupied",
|
||||
"unavailable",
|
||||
)
|
||||
assert derive_reference_labels(ambiguous, "background-or-noise") == (
|
||||
"background-or-noise",
|
||||
"rejected-nonobject",
|
||||
"unavailable",
|
||||
)
|
||||
|
||||
|
||||
def test_split_is_deterministic_balanced_and_complete() -> None:
|
||||
rows = [
|
||||
{
|
||||
"item_id": f"item-{index:03d}",
|
||||
"source_stratum": "agree" if index % 2 else "conflict",
|
||||
"range_bucket": "near" if index % 3 else "far",
|
||||
}
|
||||
for index in range(60)
|
||||
]
|
||||
first = assign_split(
|
||||
rows,
|
||||
seed="frozen-seed",
|
||||
validation_fraction=0.3,
|
||||
)
|
||||
second = assign_split(
|
||||
list(reversed(rows)),
|
||||
seed="frozen-seed",
|
||||
validation_fraction=0.3,
|
||||
)
|
||||
assert first == second
|
||||
assert set(first) == {row["item_id"] for row in rows}
|
||||
assert Counter(first.values())["validation"] == 18
|
||||
|
||||
|
||||
def test_split_rejects_mutable_or_invalid_fraction() -> None:
|
||||
with pytest.raises(E37AcceptanceContractError):
|
||||
assign_split([], seed="", validation_fraction=0.3)
|
||||
with pytest.raises(E37AcceptanceContractError):
|
||||
assign_split([], seed="seed", validation_fraction=0.9)
|
||||
Reference in New Issue
Block a user