feat(lab): publish M4.8T quality evidence
This commit is contained in:
@@ -127,7 +127,7 @@ def test_product_registry_declares_every_advanced_evidence_source() -> None:
|
||||
repository_root / "config" / "laboratories"
|
||||
)
|
||||
|
||||
assert len(registry.definitions) == 37
|
||||
assert len(registry.definitions) == 38
|
||||
assert {item.work_id for item in registry.definitions} >= {
|
||||
"e31-source-binding",
|
||||
"e46j-raw-fisheye-realtime",
|
||||
@@ -142,6 +142,7 @@ def test_product_registry_declares_every_advanced_evidence_source() -> None:
|
||||
"m48-object-centric-quality",
|
||||
"m48-small-static-passage-regression",
|
||||
"m48s-fixed-class-detector",
|
||||
"m48t-risk-quality-temporal",
|
||||
}
|
||||
m48 = next(
|
||||
item for item in registry.definitions
|
||||
|
||||
@@ -99,6 +99,7 @@ def test_repository_registry_classifies_every_evidence_definition() -> None:
|
||||
"e46j-raw-fisheye-realtime",
|
||||
"e47-semantic-slam-shadow",
|
||||
"m48s-fixed-class-detector",
|
||||
"m48t-risk-quality-temporal",
|
||||
}
|
||||
by_work_id = {row.work_id: row for row in execution.definitions}
|
||||
assert by_work_id["m48-small-static-passage-regression"].evidence_contract == (
|
||||
@@ -111,10 +112,17 @@ def test_repository_registry_classifies_every_evidence_definition() -> None:
|
||||
assert by_work_id["e47-semantic-slam-shadow"].isolation == "bounded-adapter"
|
||||
assert by_work_id["m48s-fixed-class-detector"].lifecycle == "experimental"
|
||||
assert by_work_id["m48s-fixed-class-detector"].isolation == "bounded-adapter"
|
||||
assert by_work_id["m48t-risk-quality-temporal"].lifecycle == "experimental"
|
||||
assert by_work_id["m48t-risk-quality-temporal"].isolation == "bounded-adapter"
|
||||
assert all(
|
||||
row.lifecycle == "canonical"
|
||||
for row in execution.definitions
|
||||
if row.work_id not in {"e47-semantic-slam-shadow", "m48s-fixed-class-detector"}
|
||||
if row.work_id
|
||||
not in {
|
||||
"e47-semantic-slam-shadow",
|
||||
"m48s-fixed-class-detector",
|
||||
"m48t-risk-quality-temporal",
|
||||
}
|
||||
)
|
||||
assert len(execution.definitions) + len(execution.legacy_work_ids) == len(
|
||||
evidence.definitions
|
||||
|
||||
@@ -80,7 +80,7 @@ def test_product_value_review_registry_covers_reviewed_laboratory_families() ->
|
||||
root / "config" / "laboratory-value-review.json"
|
||||
)
|
||||
|
||||
assert len(registry.entries) == 36
|
||||
assert len(registry.entries) == 37
|
||||
assert {entry.catalog_id for entry in registry.entries} >= {
|
||||
"e28-local-surface",
|
||||
"e46d-temporal-failure-audit",
|
||||
@@ -89,4 +89,5 @@ def test_product_value_review_registry_covers_reviewed_laboratory_families() ->
|
||||
"l34f-adjudicated-reference",
|
||||
"m4-replay-threat",
|
||||
"m48s-fixed-class-detector",
|
||||
"m48t-risk-quality-temporal",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from k1link.laboratory.m48t_risk_quality_lab import (
|
||||
CATALOG_SCHEMA,
|
||||
LAB_SCHEMA,
|
||||
REPORT_SCHEMA,
|
||||
RESULT_PREFIX,
|
||||
)
|
||||
from k1link.perception.fixed_class_detector_tournament import canonical_json, false_authority
|
||||
from k1link.web.m48t_risk_quality_lab_api import build_m48t_risk_quality_lab_router
|
||||
|
||||
|
||||
def _write_json(path: Path, value: object) -> None:
|
||||
path.write_bytes(canonical_json(value) + b"\n")
|
||||
|
||||
|
||||
def _descriptor(path: Path, root: Path, role: str, media_type: str) -> dict[str, object]:
|
||||
return {
|
||||
"role": role,
|
||||
"path": path.relative_to(root).as_posix(),
|
||||
"byte_length": path.stat().st_size,
|
||||
"sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
|
||||
"media_type": media_type,
|
||||
"schema_version": None,
|
||||
}
|
||||
|
||||
|
||||
def _fixture(tmp_path: Path) -> tuple[TestClient, Path, str]:
|
||||
root = tmp_path / "results"
|
||||
root.mkdir()
|
||||
identity = {"schema_version": LAB_SCHEMA, "authority": false_authority()}
|
||||
identity_sha256 = hashlib.sha256(canonical_json(identity)).hexdigest()
|
||||
result_id = RESULT_PREFIX + identity_sha256
|
||||
result_root = root / result_id
|
||||
review_root = result_root / "review"
|
||||
review_root.mkdir(parents=True)
|
||||
cases = []
|
||||
image_paths = []
|
||||
for index in range(16):
|
||||
case_id = f"{index + 1:012d}"
|
||||
image_path = review_root / f"review-{case_id}.jpg"
|
||||
image_path.write_bytes(b"jpeg" + bytes([index]))
|
||||
image_paths.append(image_path)
|
||||
cases.append(
|
||||
{
|
||||
"case_id": case_id,
|
||||
"image_id": index + 1,
|
||||
"path": f"review/{image_path.name}",
|
||||
"media_type": "image/jpeg",
|
||||
"byte_length": image_path.stat().st_size,
|
||||
"sha256": hashlib.sha256(image_path.read_bytes()).hexdigest(),
|
||||
}
|
||||
)
|
||||
catalog = {
|
||||
"schema_version": CATALOG_SCHEMA,
|
||||
"result_id": result_id,
|
||||
"case_count": 16,
|
||||
"legend": {"ground_truth": "green", "rf_detr_prediction": "yellow"},
|
||||
"cases": cases,
|
||||
}
|
||||
report = {
|
||||
"schema_version": REPORT_SCHEMA,
|
||||
"result_id": result_id,
|
||||
"source": {
|
||||
"quality": {
|
||||
"dataset_id": "coco-2017-val",
|
||||
"risk_images": 3348,
|
||||
"truth_instances": 16060,
|
||||
},
|
||||
"temporal": {"source_id": "RAVNOVES00", "frames": 4481},
|
||||
},
|
||||
"configuration": {},
|
||||
"method": {"schema_version": "missioncore.laboratory-method/v1"},
|
||||
"execution": {},
|
||||
"metrics": {},
|
||||
"acceptance": {},
|
||||
"decision": {
|
||||
"quality_accepted": False,
|
||||
"temporal_invariant_passed": True,
|
||||
},
|
||||
"limitations": [],
|
||||
"authority": false_authority(),
|
||||
}
|
||||
catalog_path = result_root / "catalog.json"
|
||||
report_path = result_root / "report.json"
|
||||
_write_json(catalog_path, catalog)
|
||||
_write_json(report_path, report)
|
||||
artifacts = [
|
||||
_descriptor(catalog_path, result_root, "visual-evidence-catalog", "application/json"),
|
||||
_descriptor(report_path, result_root, "laboratory-report", "application/json"),
|
||||
*[
|
||||
_descriptor(path, result_root, "visual-evidence-independent-truth-review", "image/jpeg")
|
||||
for path in image_paths
|
||||
],
|
||||
]
|
||||
manifest = {
|
||||
"schema_version": LAB_SCHEMA,
|
||||
"result_id": result_id,
|
||||
"identity_sha256": identity_sha256,
|
||||
"identity": identity,
|
||||
"created_at_utc": "2026-08-25T17:38:01.505739Z",
|
||||
"status": "complete-quality-gate-failed-temporal-invariant-passed",
|
||||
"completed": True,
|
||||
"bounded_question_accepted": False,
|
||||
"ground_truth": False,
|
||||
"authority": false_authority(),
|
||||
"artifacts": artifacts,
|
||||
}
|
||||
_write_json(result_root / "manifest.json", manifest)
|
||||
app = FastAPI()
|
||||
app.include_router(build_m48t_risk_quality_lab_router(root_provider=lambda: root))
|
||||
return TestClient(app), result_root, result_id
|
||||
|
||||
|
||||
def test_m48t_lab_api_projects_failed_quality_and_verified_review(tmp_path: Path) -> None:
|
||||
client, result_root, result_id = _fixture(tmp_path)
|
||||
|
||||
catalog = client.get("/api/v1/laboratory/m48t/risk-quality/results")
|
||||
assert catalog.status_code == 200
|
||||
assert catalog.json()["items"][0]["result_id"] == result_id
|
||||
assert catalog.json()["invalid_total"] == 0
|
||||
|
||||
result = client.get(f"/api/v1/laboratory/m48t/risk-quality/results/{result_id}")
|
||||
assert result.status_code == 200
|
||||
assert result.json()["decision"]["quality_accepted"] is False
|
||||
assert result.json()["decision"]["temporal_invariant_passed"] is True
|
||||
assert len(result.json()["review"]["cases"]) == 16
|
||||
|
||||
case_id = "000000000001"
|
||||
image = client.get(
|
||||
f"/api/v1/laboratory/m48t/risk-quality/results/{result_id}/review/{case_id}.jpg"
|
||||
)
|
||||
assert image.status_code == 200
|
||||
assert image.headers["content-type"] == "image/jpeg"
|
||||
assert image.content == (result_root / f"review/review-{case_id}.jpg").read_bytes()
|
||||
|
||||
|
||||
def test_m48t_lab_api_fails_closed_after_visual_tamper(tmp_path: Path) -> None:
|
||||
client, result_root, result_id = _fixture(tmp_path)
|
||||
(result_root / "review/review-000000000001.jpg").write_bytes(b"tampered")
|
||||
|
||||
response = client.get(f"/api/v1/laboratory/m48t/risk-quality/results/{result_id}")
|
||||
assert response.status_code == 404
|
||||
catalog = client.get("/api/v1/laboratory/m48t/risk-quality/results")
|
||||
assert catalog.json()["items"] == []
|
||||
assert catalog.json()["invalid_total"] == 1
|
||||
Reference in New Issue
Block a user