feat(api): publish immutable perception lab evidence

This commit is contained in:
DCCONSTRUCTIONS
2026-08-05 07:48:58 +03:00
parent 3982256f08
commit 12c8a2d74c
37 changed files with 10259 additions and 265 deletions
+211 -88
View File
@@ -56,14 +56,11 @@ from k1link.compute.e40_perception_product_gate import (
read_e40_perception_product_gate,
)
from k1link.web.l3_pointpillars_visual_api import latest_l3_visual_identity
from k1link.web.l31_pointpillars_ravnoves_api import latest_l31_identity
from k1link.web.l32_pointpillars_camera_review_api import latest_l32_identity
from k1link.web.l33_camera_first_detector_review_api import latest_l33_identity
LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = (
"missioncore.laboratory-advanced-catalog/v1"
)
LABORATORY_ADVANCED_INDEX_SCHEMA: Final = (
"missioncore.laboratory-advanced-index/v1"
)
LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = "missioncore.laboratory-advanced-catalog/v1"
LABORATORY_ADVANCED_INDEX_SCHEMA: Final = "missioncore.laboratory-advanced-index/v1"
_INDEX_DOCUMENT_MAX_BYTES: Final = 64 * 1024
_E31_RESULT_ID = re.compile(r"^e31-source-qualification-[a-f0-9]{64}$")
@@ -75,6 +72,24 @@ _E37_RESULT_ID = re.compile(r"^e37-ravnoves-acceptance-[a-f0-9]{64}$")
_E38_RESULT_ID = re.compile(r"^e38-perception-baseline-[a-f0-9]{64}$")
_E39_RESULT_ID = re.compile(r"^e39-perception-refinement-[a-f0-9]{64}$")
_E40_RESULT_ID = re.compile(r"^e40-perception-product-gate-[a-f0-9]{64}$")
_E46_RESULT_ID = re.compile(r"^e46-detector-truth-island-[a-f0-9]{64}$")
_E46A_RESULT_ID = re.compile(r"^e46a-ai-engineering-preannotation-[a-f0-9]{64}$")
_E46B_RESULT_ID = re.compile(r"^e46b-temporal-motion-[a-f0-9]{64}$")
_E46C_RESULT_ID = re.compile(r"^e46c-full-replay-world-tracks-[a-f0-9]{64}$")
_E46D_RESULT_ID = re.compile(r"^e46d-temporal-failure-audit-[a-f0-9]{64}$")
_E46E_RESULT_ID = re.compile(r"^e46e-ready-stack-[a-f0-9]{64}$")
_E46F_RESULT_ID = re.compile(r"^e46f-dashcam-bakeoff-[a-f0-9]{64}$")
_E46G_RESULT_ID = re.compile(r"^e46g-rectified-detector-bakeoff-[a-f0-9]{64}$")
_E46H_RESULT_ID = re.compile(r"^e46h-full-rectified-front-replay-[a-f0-9]{64}$")
_E46I_RESULT_ID = re.compile(r"^e46i-grounding-dino-full-replay-[a-f0-9]{64}$")
_E46J_RESULT_ID = re.compile(r"^e46j-raw-fisheye-realtime-[a-f0-9]{64}$")
_L34_RESULT_ID = re.compile(r"^l34-right-yolox-truth-island-freeze-[a-f0-9]{64}$")
_L34A_RESULT_ID = re.compile(r"^l34a-assisted-yolox-error-audit-[a-f0-9]{64}$")
_L34B_RESULT_ID = re.compile(r"^l34b-nested-box-consolidation-shadow-[a-f0-9]{64}$")
_L34C_RESULT_ID = re.compile(r"^l34c-tile-seam-stitch-shadow-[a-f0-9]{64}$")
_L34D_RESULT_ID = re.compile(r"^l34d-cumulative-postprocessing-candidate-[a-f0-9]{64}$")
_L34E_RESULT_ID = re.compile(r"^l34e-self-review-diagnostic-[a-f0-9]{64}$")
_L34F_RESULT_ID = re.compile(r"^l34f-adjudicated-reference-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
@@ -328,12 +343,8 @@ def _project_e31(result: E31SourceQualification) -> dict[str, object]:
"correspondence_count": offset.get("correspondence_count"),
"supported_fraction": offset.get("baseline_supported_fraction"),
"semantic_self_sample_count": semantic_mask.get("source_sample_count"),
"semantic_self_collateral_count": semantic_mask.get(
"collateral_item_count"
),
"exact_geometry_correction_count": len(
self_mask.get("exact_correction_item_ids", [])
),
"semantic_self_collateral_count": semantic_mask.get("collateral_item_count"),
"exact_geometry_correction_count": len(self_mask.get("exact_correction_item_ids", [])),
"geometry_point_mask_status": geometry_mask.get("status"),
},
"limitations": copy.deepcopy(result.report.get("limitations")),
@@ -375,13 +386,9 @@ def _project_e32(result: E32TrackGeometryReplay) -> dict[str, object]:
"semantic_masked": objects.get("semantic_masked"),
"geometry_published": objects.get("geometry_published"),
"observations_arbitrated": ownership.get("observations_arbitrated"),
"overlapping_claims_removed": ownership.get(
"overlapping_claims_removed"
),
"overlapping_claims_removed": ownership.get("overlapping_claims_removed"),
"qualified_points_published": point_rows.get("e32_published"),
"qualified_points_withheld": point_rows.get(
"unqualified_ranges_withheld"
),
"qualified_points_withheld": point_rows.get("unqualified_ranges_withheld"),
"frame_processing_p95_ms": frame_processing.get("p95"),
"build_elapsed_ms": runtime.get("build_elapsed_ms"),
},
@@ -444,8 +451,7 @@ def _project_e33(
"source_frames": accounting.get("source_frames"),
"source_available_frames": linked_frames.get("source_available"),
"source_unavailable_frames": (
int(accounting["source_frames"])
- int(linked_frames["source_available"])
int(accounting["source_frames"]) - int(linked_frames["source_available"])
),
"delivered_frames": accounting.get("delivered"),
"input_superseded": accounting.get("input_superseded"),
@@ -460,9 +466,7 @@ def _project_e33(
"result_deadline_ms": deadlines.get("result_ms"),
"process_rss_p95_mib": process_rss.get("p95"),
"process_rss_max_mib": process_rss.get("maximum"),
"process_rss_limit_mib": profile_acceptance.get(
"maximum_process_rss_mib"
),
"process_rss_limit_mib": profile_acceptance.get("maximum_process_rss_mib"),
"gpu_utilization_p95_percent": gpu_utilization.get("p95"),
"gpu_visible": resources.get("gpu_visible"),
"work_queue_capacity": work_queue.get("capacity"),
@@ -507,15 +511,9 @@ def _project_e34(result: E34TemporalOccupiedReplay) -> dict[str, object]:
"configuration": {
"voxel_size_m": layer.get("voxel_size_m"),
"occupied_ttl_seconds": layer.get("occupied_ttl_seconds"),
"maximum_active_components": layer.get(
"maximum_active_components"
),
"maximum_cells_per_component": layer.get(
"maximum_cells_per_component"
),
"geometry_maximum_gap_seconds": association.get(
"geometry_maximum_gap_seconds"
),
"maximum_active_components": layer.get("maximum_active_components"),
"maximum_cells_per_component": layer.get("maximum_cells_per_component"),
"geometry_maximum_gap_seconds": association.get("geometry_maximum_gap_seconds"),
"geometry_maximum_centroid_distance_m": association.get(
"geometry_maximum_centroid_distance_m"
),
@@ -529,44 +527,26 @@ def _project_e34(result: E34TemporalOccupiedReplay) -> dict[str, object]:
"created_components": components.get("created"),
"camera_created_components": components.get("camera_created"),
"geometry_created_components": components.get("geometry_created"),
"geometry_reassociated_components": components.get(
"geometry_reassociated_components"
),
"exact_camera_associations": components.get(
"exact_camera_associations"
),
"geometry_spatial_reassociations": components.get(
"geometry_spatial_reassociations"
),
"geometry_reassociated_components": components.get("geometry_reassociated_components"),
"exact_camera_associations": components.get("exact_camera_associations"),
"geometry_spatial_reassociations": components.get("geometry_spatial_reassociations"),
"held_publications": components.get("held_publications"),
"expired_components": components.get("expired"),
"peak_active_components": components.get("peak_active"),
"maximum_observed_span_seconds": components.get(
"maximum_observed_span_seconds"
),
"maximum_observed_span_seconds": components.get("maximum_observed_span_seconds"),
"continuity_fraction": components.get("continuity_fraction"),
"geometry_only_reassociation_fraction": components.get(
"geometry_only_reassociation_fraction"
),
"e32_current_point_rows": occupancy.get(
"e32_current_point_rows"
),
"e34_consumed_current_point_rows": occupancy.get(
"e34_consumed_current_point_rows"
),
"e32_current_point_rows": occupancy.get("e32_current_point_rows"),
"e34_consumed_current_point_rows": occupancy.get("e34_consumed_current_point_rows"),
"current_cell_rows": occupancy.get("current_cell_rows"),
"held_cell_rows": occupancy.get("held_cell_rows"),
"stored_cell_rows": occupancy.get("stored_cell_rows"),
"free_cell_rows": occupancy.get("free_cell_rows"),
"peak_cells_per_component": occupancy.get(
"peak_cells_per_component"
),
"maximum_held_age_seconds": aging.get(
"maximum_held_age_seconds"
),
"maximum_expiry_delay_seconds": aging.get(
"maximum_expiry_delay_seconds"
),
"peak_cells_per_component": occupancy.get("peak_cells_per_component"),
"maximum_held_age_seconds": aging.get("maximum_held_age_seconds"),
"maximum_expiry_delay_seconds": aging.get("maximum_expiry_delay_seconds"),
"maximum_replay_materialization_delay_seconds": aging.get(
"maximum_replay_materialization_delay_seconds"
),
@@ -611,19 +591,13 @@ def _project_e35(result: E35DegradationReplay) -> dict[str, object]:
"pipeline_id": identity.get("pipeline"),
"coordinate_frame": identity.get("coordinate_frame"),
"configuration": {
"maximum_recovery_seconds": acceptance_profile.get(
"maximum_recovery_seconds"
),
"scenario_count": acceptance_profile.get(
"expected_scenario_count"
),
"maximum_recovery_seconds": acceptance_profile.get("maximum_recovery_seconds"),
"scenario_count": acceptance_profile.get("expected_scenario_count"),
},
"metrics": {
"source_frames": accounting.get("source_frames"),
"variant_count": accounting.get("variant_count"),
"variant_frame_outcomes": accounting.get(
"variant_frame_outcomes"
),
"variant_frame_outcomes": accounting.get("variant_frame_outcomes"),
"injection_records": accounting.get("injection_records"),
"variant_frame_processing_p95_ms": processing.get("p95"),
"build_elapsed_ms": runtime.get("build_elapsed_ms"),
@@ -669,18 +643,12 @@ def _project_e37(result: E37AcceptanceContract) -> dict[str, object]:
"accounting_fraction": metrics.get("accounting_fraction"),
"false_free_claims": metrics.get("false_free_claims"),
},
"dimension_distributions": copy.deepcopy(
result.contract.get("dimension_distributions")
),
"severity_distribution": copy.deepcopy(
result.contract.get("severity_distribution")
),
"dimension_distributions": copy.deepcopy(result.contract.get("dimension_distributions")),
"severity_distribution": copy.deepcopy(result.contract.get("severity_distribution")),
"label_provenance": {
"engineering_items": provenance.get("engineering_items"),
"human_exception_items": provenance.get("human_exception_items"),
"independent_ground_truth": provenance.get(
"independent_ground_truth"
),
"independent_ground_truth": provenance.get("independent_ground_truth"),
},
"split": copy.deepcopy(result.contract.get("split")),
"targets": copy.deepcopy(result.contract.get("targets")),
@@ -827,8 +795,28 @@ def build_advanced_laboratory_router(
e38_root_provider: RootProvider = lambda: None,
e39_root_provider: RootProvider = lambda: None,
e40_root_provider: RootProvider = lambda: None,
e46_root_provider: RootProvider = lambda: None,
e46a_root_provider: RootProvider = lambda: None,
e46b_root_provider: RootProvider = lambda: None,
e46c_root_provider: RootProvider = lambda: None,
e46d_root_provider: RootProvider = lambda: None,
e46e_root_provider: RootProvider = lambda: None,
e46f_root_provider: RootProvider = lambda: None,
e46g_root_provider: RootProvider = lambda: None,
e46h_root_provider: RootProvider = lambda: None,
e46i_root_provider: RootProvider = lambda: None,
e46j_root_provider: RootProvider = lambda: None,
l34_root_provider: RootProvider = lambda: None,
l34a_root_provider: RootProvider = lambda: None,
l34b_root_provider: RootProvider = lambda: None,
l34c_root_provider: RootProvider = lambda: None,
l34d_root_provider: RootProvider = lambda: None,
l34e_root_provider: RootProvider = lambda: None,
l34f_root_provider: RootProvider = lambda: None,
l3_visual_root_provider: RootProvider = lambda: None,
l31_ravnoves_root_provider: RootProvider = lambda: None,
l32_camera_review_root_provider: RootProvider = lambda: None,
l33_camera_first_review_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@@ -899,23 +887,161 @@ def build_advanced_laboratory_router(
"manifest.json",
"missioncore.e40-perception-product-gate/v1",
),
(
"e46-detector-truth-island",
e46_root_provider,
_E46_RESULT_ID,
"manifest.json",
"missioncore.e46-detector-truth-island/v1",
),
(
"e46a-ai-engineering-preannotation",
e46a_root_provider,
_E46A_RESULT_ID,
"manifest.json",
"missioncore.e46a-ai-engineering-preannotation/v1",
),
(
"e46b-temporal-motion",
e46b_root_provider,
_E46B_RESULT_ID,
"manifest.json",
"missioncore.e46b-temporal-motion/v1",
),
(
"e46c-full-replay-world-tracks",
e46c_root_provider,
_E46C_RESULT_ID,
"manifest.json",
"missioncore.e46c-full-replay-world-tracks/v1",
),
(
"e46d-temporal-failure-audit",
e46d_root_provider,
_E46D_RESULT_ID,
"manifest.json",
"missioncore.e46d-temporal-failure-audit/v1",
),
(
"e46e-ready-stack",
e46e_root_provider,
_E46E_RESULT_ID,
"manifest.json",
"missioncore.e46e-ready-stack-result/v1",
),
(
"e46f-dashcam-bakeoff",
e46f_root_provider,
_E46F_RESULT_ID,
"manifest.json",
"missioncore.e46f-dashcam-bakeoff-result/v1",
),
(
"e46g-rectified-detector-bakeoff",
e46g_root_provider,
_E46G_RESULT_ID,
"manifest.json",
"missioncore.e46g-rectified-detector-bakeoff-result/v1",
),
(
"e46h-full-rectified-front-replay",
e46h_root_provider,
_E46H_RESULT_ID,
"manifest.json",
"missioncore.e46h-full-rectified-front-replay-result/v1",
),
(
"e46i-grounding-dino-full-replay",
e46i_root_provider,
_E46I_RESULT_ID,
"manifest.json",
"missioncore.e46i-grounding-dino-full-replay-result/v1",
),
(
"e46j-raw-fisheye-realtime",
e46j_root_provider,
_E46J_RESULT_ID,
"manifest.json",
"missioncore.e46j-raw-fisheye-realtime-result/v1",
),
(
"l34-right-yolox-truth-island-freeze",
l34_root_provider,
_L34_RESULT_ID,
"manifest.json",
"missioncore.l34-right-yolox-truth-island-freeze/v1",
),
(
"l34a-assisted-yolox-error-audit",
l34a_root_provider,
_L34A_RESULT_ID,
"manifest.json",
"missioncore.l34a-assisted-yolox-error-audit/v1",
),
(
"l34b-nested-box-consolidation-shadow",
l34b_root_provider,
_L34B_RESULT_ID,
"manifest.json",
"missioncore.l34b-nested-box-consolidation-shadow/v1",
),
(
"l34c-tile-seam-stitch-shadow",
l34c_root_provider,
_L34C_RESULT_ID,
"manifest.json",
"missioncore.l34c-tile-seam-stitch-shadow/v1",
),
(
"l34d-cumulative-postprocessing-candidate",
l34d_root_provider,
_L34D_RESULT_ID,
"manifest.json",
"missioncore.l34d-cumulative-postprocessing-candidate/v1",
),
(
"l34e-self-review-diagnostic",
l34e_root_provider,
_L34E_RESULT_ID,
"manifest.json",
"missioncore.l34e-self-review-diagnostic/v1",
),
(
"l34f-adjudicated-reference",
l34f_root_provider,
_L34F_RESULT_ID,
"manifest.json",
"missioncore.l34f-adjudicated-reference/v1",
),
)
)
items = result["items"]
if not isinstance(items, list):
raise RuntimeError("advanced LAB index items are invalid")
l3_identity = latest_l3_visual_identity(l3_visual_root_provider)
if l3_identity is not None:
result["items"].append(
items.append(
{
"work_id": "l3-pointpillars-visual-audit",
**l3_identity,
"access": "read-only",
}
)
l31_identity = latest_l31_identity(l31_ravnoves_root_provider)
if l31_identity is not None:
result["items"].append(
l32_identity = latest_l32_identity(l32_camera_review_root_provider)
if l32_identity is not None:
items.append(
{
"work_id": "l31-pointpillars-ravnoves",
**l31_identity,
"work_id": "l32-pointpillars-camera-review",
**l32_identity,
"access": "read-only",
}
)
l33_identity = latest_l33_identity(l33_camera_first_review_root_provider)
if l33_identity is not None:
items.append(
{
"work_id": "l33-camera-first-detector-review",
**l33_identity,
"access": "read-only",
}
)
@@ -972,10 +1098,7 @@ def build_advanced_laboratory_router(
str(candidate.resolve()),
_result_signature(candidate),
)
if (
result.report.get("status")
!= "accepted-diagnostic-track-geometry-replay"
):
if result.report.get("status") != "accepted-diagnostic-track-geometry-replay":
raise ValueError("E32 result is not accepted")
if len(items) < limit:
items.append(_project_e32(result))
+544 -172
View File
@@ -41,6 +41,31 @@ from k1link.web.e30_engineering_api import build_e30_engineering_router
from k1link.web.e30_human_review_api import build_e30_human_review_router
from k1link.web.e30_review_api import build_e30_review_router
from k1link.web.e40_case_review_api import build_e40_case_review_router
from k1link.web.e46_blind_review_api import build_e46_blind_review_router
from k1link.web.e46a_ai_engineering_preannotation_api import (
build_e46a_ai_engineering_preannotation_router,
)
from k1link.web.e46b_temporal_motion_api import build_e46b_temporal_motion_router
from k1link.web.e46c_full_replay_world_tracks_api import (
build_e46c_full_replay_world_tracks_router,
)
from k1link.web.e46d_temporal_failure_audit_api import (
build_e46d_temporal_failure_audit_router,
)
from k1link.web.e46e_ready_stack_api import build_e46e_ready_stack_router
from k1link.web.e46f_dashcam_bakeoff_api import build_e46f_dashcam_bakeoff_router
from k1link.web.e46g_rectified_detector_bakeoff_api import (
build_e46g_rectified_detector_bakeoff_router,
)
from k1link.web.e46h_full_rectified_front_replay_api import (
build_e46h_full_rectified_front_replay_router,
)
from k1link.web.e46i_grounding_dino_full_replay_api import (
build_e46i_grounding_dino_full_replay_router,
)
from k1link.web.e46j_raw_fisheye_realtime_api import (
build_e46j_raw_fisheye_realtime_router,
)
from k1link.web.environment_api import build_environment_router
from k1link.web.l3_pointpillars_visual_api import (
build_l3_pointpillars_visual_router,
@@ -48,6 +73,35 @@ from k1link.web.l3_pointpillars_visual_api import (
from k1link.web.l31_pointpillars_ravnoves_api import (
build_l31_pointpillars_ravnoves_router,
)
from k1link.web.l32_pointpillars_camera_review_api import (
build_l32_pointpillars_camera_review_router,
)
from k1link.web.l33_camera_first_detector_review_api import (
build_l33_camera_first_detector_review_router,
)
from k1link.web.l34_annotation_api import (
build_l34_annotation_router,
build_l34d_blind_annotation_router,
)
from k1link.web.l34_right_yolox_truth_island_api import (
build_l34_right_yolox_truth_island_freeze_router,
)
from k1link.web.l34a_assisted_yolox_error_audit_api import (
build_l34a_assisted_yolox_error_audit_router,
)
from k1link.web.l34b_nested_box_consolidation_api import (
build_l34b_nested_box_consolidation_router,
)
from k1link.web.l34c_tile_seam_stitch_api import (
build_l34c_tile_seam_stitch_router,
)
from k1link.web.l34d_cumulative_postprocessing_api import (
build_l34d_cumulative_postprocessing_router,
)
from k1link.web.l34e_self_review_diagnostic_api import (
build_l34e_self_review_diagnostic_router,
)
from k1link.web.l34f_adjudication_api import build_l34f_adjudication_router
from k1link.web.laboratory_api import build_laboratory_router
from k1link.web.lidar_api import build_lidar_router
from k1link.web.lidar_local_surface_service import K1LocalSurfaceReadService
@@ -139,18 +193,10 @@ session_integrated_perception_store = (
IntegratedPerceptionOverlayStore(
jobs_root=REPOSITORY_ROOT / ".runtime" / "compute-jobs",
results_root=(
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e10"
/ "worker-results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e10" / "worker-results"
),
lidar_packs_root=(
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e10"
/ "lidar-packs"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e10" / "lidar-packs"
),
cache_root=session_store.data_dir / "integrated-perception-overlays",
ffmpeg_path=_ffmpeg,
@@ -304,9 +350,7 @@ async def _recording_preparation_reconciler() -> None:
async def app_lifespan(_: FastAPI) -> AsyncIterator[None]:
reconciler: asyncio.Task[None] | None = None
try:
configure_scanner_diagnostics(
REPOSITORY_ROOT / ".runtime" / "mission-core" / "logs"
)
configure_scanner_diagnostics(REPOSITORY_ROOT / ".runtime" / "mission-core" / "logs")
session_recording_preparation_manager.start()
# Recovery is intentionally a one-shot startup phase. The archive
# helper owns a cross-process lease, while ordinary catalog requests
@@ -441,9 +485,7 @@ app.include_router(
)
)
app.include_router(
build_environment_router(
root_provider=lambda: session_store.data_dir / "ui-environment"
)
build_environment_router(root_provider=lambda: session_store.data_dir / "ui-environment")
)
app.include_router(build_map_router(map_gateway_proxy))
app.include_router(
@@ -453,25 +495,18 @@ app.include_router(
)
app.include_router(
build_polygon_router(
root_provider=lambda: configured_polygon_runs_root()
or REPOSITORY_ROOT / ".runtime" / "polygon-runs"
root_provider=lambda: (
configured_polygon_runs_root() or REPOSITORY_ROOT / ".runtime" / "polygon-runs"
)
)
)
app.include_router(
build_lidar_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "lidar-replay-v2"
/ "packs"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "lidar-replay-v2" / "packs"
),
ground_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "lidar-ground-v1"
/ "benchmarks"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "lidar-ground-v1" / "benchmarks"
),
field_review_root_provider=lambda: (
REPOSITORY_ROOT
@@ -481,18 +516,10 @@ app.include_router(
/ "reviews"
),
local_surface_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "k1-local-surface-v1"
/ "models"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "k1-local-surface-v1" / "models"
),
e10_source_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e10"
/ "lidar-packs"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e10" / "lidar-packs"
),
dataset_admission_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "dataset-gateway" / "admission.json"
@@ -518,221 +545,574 @@ app.include_router(
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e29" / "results"
),
local_surface_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "k1-local-surface-v1"
/ "models"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "k1-local-surface-v1" / "models"
),
source_pack_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e10"
/ "lidar-packs"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e10" / "lidar-packs"
),
source_result_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e10"
/ "worker-results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e10" / "worker-results"
),
)
)
app.include_router(
build_advanced_laboratory_router(
e31_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e31"
/ "source-qualifications"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e31" / "source-qualifications"
),
e32_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e32"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e32" / "results"
),
e33_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e33"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e33" / "results"
),
e34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e34"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e34" / "results"
),
e35_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e35"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e35" / "results"
),
e37_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e37"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e37" / "results"
),
e38_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e38"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e38" / "results"
),
e39_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e39"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e39" / "results"
),
e40_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e40" / "results"
),
e46_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
e46a_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e40"
/ "results"
/ "e46a"
/ "ai-engineering-preannotations"
),
e46b_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46b" / "temporal-motion"
),
e46c_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46c"
/ "full-replay-world-tracks"
),
e46d_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46d"
/ "temporal-failure-audits"
),
e46e_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46e"
/ "ready-stack-results"
),
e46f_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46f"
/ "dashcam-bakeoff-results"
),
e46g_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46g" / "results"
),
e46h_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46h" / "results"
),
e46i_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46i" / "results"
),
e46j_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46j" / "results"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
l34a_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "assisted-yolox-error-audits"
),
l34b_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "nested-box-consolidation-shadows"
),
l34c_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "tile-seam-stitch-shadows"
),
l34d_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "cumulative-postprocessing-candidates"
),
l34e_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "self-review-diagnostics"
),
l34f_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "adjudicated-references"
),
l3_visual_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "visual-audits"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "visual-audits"
),
l31_ravnoves_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "pointpillars-ravnoves"
),
l32_camera_review_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "pointpillars-ravnoves"
/ "pointpillars-camera-review"
),
l33_camera_first_review_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "camera-first-detector-review"
),
)
)
app.include_router(
build_l3_pointpillars_visual_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "visual-audits"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "visual-audits"
)
)
)
app.include_router(
build_l31_pointpillars_ravnoves_router(
root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "pointpillars-ravnoves"
)
)
)
app.include_router(
build_l32_pointpillars_camera_review_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "pointpillars-ravnoves"
/ "pointpillars-camera-review"
)
)
)
app.include_router(
build_l33_camera_first_detector_review_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "camera-first-detector-review"
)
)
)
app.include_router(
build_l34_right_yolox_truth_island_freeze_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
)
)
app.include_router(
build_e46_blind_review_router(
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
annotation_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "laboratory-annotations" / "e46-blind"
),
submission_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e48" / "review-submissions"
),
)
)
app.include_router(
build_e46a_ai_engineering_preannotation_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46a"
/ "ai-engineering-preannotations"
),
annotation_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "laboratory-annotations" / "e46a-correction"
),
)
)
app.include_router(
build_e46b_temporal_motion_router(
root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46b" / "temporal-motion"
),
)
)
app.include_router(
build_e46c_full_replay_world_tracks_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46c"
/ "full-replay-world-tracks"
),
e26_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e10" / "worker-results"
),
)
)
app.include_router(
build_e46d_temporal_failure_audit_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46d"
/ "temporal-failure-audits"
),
)
)
app.include_router(
build_e46e_ready_stack_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46e"
/ "ready-stack-results"
),
)
)
app.include_router(
build_e46f_dashcam_bakeoff_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46f"
/ "dashcam-bakeoff-results"
),
e46e_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e46e"
/ "ready-stack-results"
),
)
)
app.include_router(
build_e46g_rectified_detector_bakeoff_router(
root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46g" / "results"
)
)
)
app.include_router(
build_e46h_full_rectified_front_replay_router(
root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46h" / "results"
)
)
)
app.include_router(
build_e46i_grounding_dino_full_replay_router(
root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46i" / "results"
)
)
)
app.include_router(
build_e46j_raw_fisheye_realtime_router(
root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46j" / "results"
)
)
)
app.include_router(
build_l34_annotation_router(
root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
annotation_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "laboratory-annotations" / "l34"
),
)
)
app.include_router(
build_l34a_assisted_yolox_error_audit_router(
audit_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "assisted-yolox-error-audits"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
)
)
app.include_router(
build_l34b_nested_box_consolidation_router(
shadow_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "nested-box-consolidation-shadows"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
)
)
app.include_router(
build_l34c_tile_seam_stitch_router(
shadow_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "tile-seam-stitch-shadows"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
)
)
app.include_router(
build_l34d_cumulative_postprocessing_router(
candidate_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "cumulative-postprocessing-candidates"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
)
)
app.include_router(
build_l34d_blind_annotation_router(
candidate_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "cumulative-postprocessing-candidates"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
annotation_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "laboratory-annotations" / "l34d-blind"
),
)
)
app.include_router(
build_l34e_self_review_diagnostic_router(
diagnostic_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "self-review-diagnostics"
),
candidate_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "cumulative-postprocessing-candidates"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
)
)
app.include_router(
build_l34f_adjudication_router(
diagnostic_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "self-review-diagnostics"
),
candidate_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "cumulative-postprocessing-candidates"
),
l34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "l3"
/ "right-yolox-truth-island-freeze"
),
truth_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e46" / "results"
),
evaluation_pack_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e2" / "evaluation-packs"
),
adjudication_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "laboratory-annotations" / "l34f-adjudication"
),
result_root_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "l3" / "adjudicated-references"
),
)
)
app.include_router(
build_e30_review_router(
materialization_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "materializations"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "materializations"
),
review_pack_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "review-packs"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "review-packs"
),
)
)
app.include_router(
build_e40_case_review_router(
e40_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e40"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e40" / "results"
),
operator_review_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e40"
/ "operator-reviews"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e40" / "operator-reviews"
),
)
)
app.include_router(
build_e30_engineering_router(
generation_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "engineering-generations"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "engineering-generations"
),
materialization_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "materializations"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "materializations"
),
review_pack_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "review-packs"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "review-packs"
),
)
)
app.include_router(
build_e30_human_review_router(
materialization_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "materializations"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "materializations"
),
review_pack_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "review-packs"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "review-packs"
),
engineering_generation_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "engineering-generations"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "engineering-generations"
),
draft_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e30"
/ "human-review-drafts"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e30" / "human-review-drafts"
),
generation_root_provider=lambda: (
REPOSITORY_ROOT
@@ -752,18 +1132,10 @@ app.include_router(
build_artifact_health_router(
runtime_root_provider=lambda: REPOSITORY_ROOT / ".runtime",
e44_results_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e44"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e44" / "results"
),
e50_results_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e50"
/ "results"
REPOSITORY_ROOT / ".runtime" / "compute-experiments" / "e50" / "results"
),
)
)
+610
View File
@@ -0,0 +1,610 @@
"""Source-only E46 review collection for two independent human slots."""
from __future__ import annotations
import copy
import hashlib
import json
import re
import secrets
from collections.abc import Callable
from pathlib import Path, PurePosixPath
from typing import Annotated, Any, Final, Literal
from fastapi import APIRouter, Header, HTTPException, Query
from fastapi import Path as ApiPath
from fastapi.responses import FileResponse
from pydantic import BaseModel, ConfigDict, Field
from k1link.artifacts import write_json_atomic
from k1link.compute.e46_detector_truth_island import (
E46_REFERENCES_NAME,
E46DetectorTruthIsland,
E46DetectorTruthIslandError,
read_e46_detector_truth_island,
)
from k1link.compute.e46_lab_review_submission import (
E46LabReviewSubmissionError,
build_e46_lab_review_submission,
read_e46_lab_review_submission,
)
from k1link.web.l34_annotation_api import (
L34_ANNOTATION_LABEL_CATALOG_SCHEMA,
L34_ANNOTATION_SESSION_CATALOG_SCHEMA,
L34_ANNOTATION_SOURCE_CATALOG_SCHEMA,
L34_ANNOTATION_SOURCE_SCHEMA,
L34AnnotationCreateRequest,
L34AnnotationSaveRequest,
_L34AnnotationSessionStore,
_normalize_object,
_png_dimensions,
_source_projection,
)
_TRUTH_ID = re.compile(r"^e46-detector-truth-island-[a-f0-9]{64}$")
_SESSION_ID = re.compile(r"^l34-annotation-session-[a-f0-9]{64}$")
_SUBMISSION_ID = re.compile(r"^e46-lab-review-submission-[a-f0-9]{64}$")
_PACK_ID = re.compile(r"^evaluation-pack-[a-f0-9]{64}$")
_REVIEWER_ID = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{1,63}$")
_TARGET_CLASSES: Final = (
"person",
"bicycle",
"motorcycle",
"car",
"heavy_vehicle",
"static_obstacle",
"animal",
)
_AUTHORITY: Final = {
"ground_truth": False,
"independent_truth": False,
"metric_grade_reference": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
RootProvider = Callable[[], Path | None]
class E46ReviewFreezeRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
expected_revision: int = Field(ge=1)
reviewer_id: str = Field(min_length=2, max_length=64)
independent_attestation: Literal[True]
candidate_identity_not_seen: Literal[True]
model_material_not_seen: Literal[True]
def build_e46_blind_review_router(
*,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
annotation_root_provider: RootProvider = lambda: None,
submission_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46", tags=["laboratory"])
store = _L34AnnotationSessionStore(
annotation_root_provider,
result_id_pattern=_TRUTH_ID,
lab_label="E46",
initial_assistance_mode="prediction-free-manual",
allowed_assistance_modes=frozenset({"prediction-free-manual"}),
)
def require_capability(
result_id: str,
session_id: str,
capability: str | None,
) -> None:
sidecar = store.session_path(result_id, session_id).with_suffix(
".capability.json"
)
try:
document = json.loads(sidecar.read_text(encoding="utf-8"))
except (OSError, ValueError):
raise HTTPException(status_code=403, detail="E46 reviewer slot недоступен") from None
expected = document.get("capability") if isinstance(document, dict) else None
if (
not isinstance(capability, str)
or not isinstance(expected, str)
or not secrets.compare_digest(capability, expected)
):
raise HTTPException(status_code=403, detail="E46 reviewer slot недоступен")
def truth(result_id: str) -> tuple[E46DetectorTruthIsland, tuple[dict[str, Any], ...]]:
if _TRUTH_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46 truth island не найден")
root = _configured_root(truth_root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46 truth island не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46 truth island не найден")
try:
result = read_e46_detector_truth_island(path)
references = tuple(_read_jsonl(result.result_root / E46_REFERENCES_NAME))
except (E46DetectorTruthIslandError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46 truth island не найден") from None
return result, references
def source(
result_id: str,
sequence: int,
) -> tuple[E46DetectorTruthIsland, dict[str, Any], Path]:
result, references = truth(result_id)
reference = next(
(item for item in references if item.get("truth_island_sequence") == sequence),
None,
)
if reference is None:
raise HTTPException(status_code=404, detail="E46 source frame не найден")
identity = result.manifest.get("identity")
source_identity = identity.get("source") if isinstance(identity, dict) else None
pack_id = (
source_identity.get("evaluation_pack_id")
if isinstance(source_identity, dict)
else None
)
pack_root = _configured_root(evaluation_pack_root_provider)
if (
pack_root is None
or not isinstance(pack_id, str)
or _PACK_ID.fullmatch(pack_id) is None
):
raise HTTPException(status_code=404, detail="E46 image source не найден")
pack = (pack_root / pack_id).resolve()
relative = reference.get("source_path")
if not isinstance(relative, str):
raise HTTPException(status_code=404, detail="E46 image source не найден")
pure = PurePosixPath(relative)
if (
pack.parent != pack_root
or pack.is_symlink()
or not pack.is_dir()
or pure.is_absolute()
or ".." in pure.parts
or pure.parts[:2] != ("images", "valid-fov-fill")
or pure.suffix.lower() != ".png"
):
raise HTTPException(status_code=404, detail="E46 image source не найден")
image = (pack / Path(*pure.parts)).resolve()
if (
not image.is_relative_to(pack)
or image.is_symlink()
or not image.is_file()
or image.stat().st_size != reference.get("byte_length")
or _sha256(image) != reference.get("sha256")
):
raise HTTPException(status_code=404, detail="E46 image source изменён")
return result, reference, image
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _truth_candidates(truth_root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
result, references = truth(path.name)
if len(items) < limit:
items.append(
_project_result(
result,
references,
sessions=store.list(result.result_id),
submissions=_submissions_for_truth(
submission_root_provider,
result.result_root,
result.result_id,
),
)
)
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46-detector-truth-island-catalog/v1",
"configured": _configured_root(truth_root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/results/{result_id}/annotation-source")
def get_source_catalog(result_id: str) -> dict[str, object]:
result, references = truth(result_id)
frames: list[dict[str, object]] = []
for reference in references:
_, _, image = source(result_id, int(reference["truth_island_sequence"]))
width, height = _png_dimensions(image)
frames.append(_source_projection(reference, width=width, height=height))
return {
"schema_version": L34_ANNOTATION_SOURCE_CATALOG_SCHEMA,
"result_id": result.result_id,
"truth_island_id": result.result_id,
"contract": _review_contract(),
"frames": frames,
"frame_count": len(frames),
"model_material_included": False,
"candidate_identity_included": False,
"candidate_predictions_included": False,
"prelabels_included": False,
"reviewer_slots": ["A", "B"],
"access": "prediction-free-independent-review-source-read-only",
}
@router.get("/results/{result_id}/annotation-source/frames/{sequence}")
def get_source_frame(result_id: str, sequence: int) -> dict[str, object]:
_, reference, image = source(result_id, sequence)
width, height = _png_dimensions(image)
return {
"schema_version": L34_ANNOTATION_SOURCE_SCHEMA,
"result_id": result_id,
**_source_projection(reference, width=width, height=height),
"camera_url": (
f"/api/v1/laboratory/e46/results/{result_id}"
f"/annotation-source/frames/{sequence}/camera"
),
"model_material_included": False,
"candidate_identity_included": False,
"candidate_predictions_included": False,
"prelabels_included": False,
"access": "prediction-free-independent-review-source-read-only",
}
@router.get("/results/{result_id}/annotation-source/frames/{sequence}/camera")
def get_source_camera(result_id: str, sequence: int) -> FileResponse:
_, _, image = source(result_id, sequence)
return FileResponse(image, media_type="image/png")
@router.get("/results/{result_id}/annotation-sessions")
def list_sessions(result_id: str) -> dict[str, object]:
truth(result_id)
items = store.list(result_id)
return {
"schema_version": L34_ANNOTATION_SESSION_CATALOG_SCHEMA,
"result_id": result_id,
"items": items,
"total": len(items),
"maximum_sessions": 2,
"access": "prediction-free-independent-review-summaries",
}
@router.get("/results/{result_id}/annotation-labels")
def get_labels(result_id: str) -> dict[str, object]:
truth(result_id)
return {
"schema_version": L34_ANNOTATION_LABEL_CATALOG_SCHEMA,
"result_id": result_id,
"items": [],
"total": 0,
"access": "prediction-free-fixed-taxonomy",
}
@router.post("/results/{result_id}/annotation-sessions")
def create_session(
result_id: str,
request: L34AnnotationCreateRequest,
) -> dict[str, object]:
result, _ = truth(result_id)
expected = "l34-annotation-session-" + hashlib.sha256(
f"{result_id}\n{request.idempotency_key}".encode()
).hexdigest()
existing = store.list(result_id)
if len(existing) >= 2 and all(item["session_id"] != expected for item in existing):
raise HTTPException(status_code=409, detail="E46 допускает только Reviewer A и B")
created = store.create(
result_id=result_id,
truth_island_id=result.result_id,
idempotency_key=request.idempotency_key,
)
capability_path = store.session_path(
result_id,
str(created["session_id"]),
).with_suffix(".capability.json")
if capability_path.exists():
try:
capability_document = json.loads(
capability_path.read_text(encoding="utf-8")
)
capability = capability_document["capability"]
except (KeyError, OSError, TypeError, ValueError):
raise HTTPException(
status_code=409,
detail="E46 reviewer slot не прошёл проверку",
) from None
else:
capability = secrets.token_urlsafe(32)
write_json_atomic(
capability_path,
{
"schema_version": "missioncore.e46-review-capability/v1",
"result_id": result_id,
"session_id": created["session_id"],
"capability": capability,
},
)
capability_path.chmod(0o600)
return {**created, "review_capability": capability}
@router.get("/results/{result_id}/annotation-sessions/{session_id}")
def get_session(
result_id: str,
session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)],
x_e46_review_capability: Annotated[
str | None,
Header(alias="X-E46-Review-Capability"),
] = None,
) -> dict[str, object]:
truth(result_id)
require_capability(result_id, session_id, x_e46_review_capability)
return store.get(result_id, session_id)
@router.put("/results/{result_id}/annotation-sessions/{session_id}")
def save_session(
result_id: str,
session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)],
request: L34AnnotationSaveRequest,
x_e46_review_capability: Annotated[
str | None,
Header(alias="X-E46-Review-Capability"),
] = None,
) -> dict[str, object]:
require_capability(result_id, session_id, x_e46_review_capability)
result, _ = truth(result_id)
if any(
item["annotation_session_id"] == session_id
for item in _submissions_for_truth(
submission_root_provider,
result.result_root,
result.result_id,
)
):
raise HTTPException(status_code=409, detail="E46 reviewer slot уже заморожен")
if request.assistance_mode != "prediction-free-manual":
raise HTTPException(
status_code=422,
detail="E46 принимает только prediction-free разметку",
)
sequences: set[int] = set()
normalized: list[dict[str, object]] = []
for frame in request.frames:
sequence = frame.truth_island_sequence
if sequence in sequences:
raise HTTPException(status_code=422, detail="Кадр размечен дважды")
sequences.add(sequence)
_, reference, image = source(result_id, sequence)
width, height = _png_dimensions(image)
if any(
item.origin != "manual" or item.category == "unmapped"
for item in frame.objects
):
raise HTTPException(
status_code=422,
detail="E46 принимает только ручные canonical-классы",
)
objects = [
_normalize_object(item, width=width, height=height)
for item in frame.objects
]
if frame.hard_negative != (len(objects) == 0):
raise HTTPException(status_code=422, detail="Пустой кадр должен быть явно отмечен")
normalized.append(
{
"truth_island_sequence": sequence,
"image_id": int(reference["image_id"]),
"frame_index": int(reference["frame_index"]),
"source_sha256": str(reference["sha256"]),
"reviewed": True,
"hard_negative": frame.hard_negative,
"objects": objects,
}
)
normalized.sort(key=lambda item: int(item["truth_island_sequence"]))
return store.save(
result_id=result_id,
session_id=session_id,
request=request,
frames=normalized,
)
@router.post("/results/{result_id}/annotation-sessions/{session_id}/freeze")
def freeze_session(
result_id: str,
session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)],
request: E46ReviewFreezeRequest,
x_e46_review_capability: Annotated[
str | None,
Header(alias="X-E46-Review-Capability"),
] = None,
) -> dict[str, object]:
result, _ = truth(result_id)
require_capability(result_id, session_id, x_e46_review_capability)
session = store.get(result_id, session_id)
if session["revision"] != request.expected_revision:
raise HTTPException(status_code=409, detail="E46-сессия уже изменена")
if not session["progress"]["complete"]:
raise HTTPException(status_code=422, detail="Для freeze нужны 32/32 кадров")
reviewer_id = request.reviewer_id.strip()
if _REVIEWER_ID.fullmatch(reviewer_id) is None:
raise HTTPException(status_code=422, detail="Некорректный reviewer id")
root = submission_root_provider()
if root is None:
raise HTTPException(status_code=503, detail="Хранилище E46 review не настроено")
existing = _submissions_for_truth(
submission_root_provider,
result.result_root,
result.result_id,
)
for item in existing:
if item["annotation_session_id"] == session_id:
if item["reviewer_id"] == reviewer_id:
return item
raise HTTPException(
status_code=409,
detail="E46 reviewer slot уже заморожен другим reviewer id",
)
if item["reviewer_id"] == reviewer_id and item["annotation_session_id"] != session_id:
raise HTTPException(
status_code=409,
detail="Reviewer id уже использован другим слотом",
)
try:
frozen = build_e46_lab_review_submission(
truth_island_root=result.result_root,
annotation_session_path=store.session_path(result_id, session_id),
reviewer_id=reviewer_id,
output_root=root,
)
except (E46LabReviewSubmissionError, OSError) as exc:
raise HTTPException(
status_code=409,
detail="E46 review freeze не прошёл проверку",
) from exc
return _project_submission(frozen)
return router
def _project_result(
result: E46DetectorTruthIsland,
references: tuple[dict[str, Any], ...],
*,
sessions: list[dict[str, object]],
submissions: list[dict[str, object]],
) -> dict[str, object]:
selection = result.report["selection"]
source = result.manifest["identity"]["source"]
return {
"result_id": result.result_id,
"created_at_utc": result.manifest["created_at_utc"],
"status": result.report["status"],
"source_session_id": source["session_id"],
"camera_source_id": source["source_id"],
"metrics": {
"frame_count": len(references),
"anchor_count": selection["anchor_count"],
"temporal_frame_count": selection["temporal_frame_count"],
"temporal_group_count": selection["temporal_group_count"],
"review_session_count": len(sessions),
"completed_submission_count": len(submissions),
"required_submission_count": 2,
},
"review_sessions": copy.deepcopy(sessions),
"submissions": copy.deepcopy(submissions),
"decision": {
"collection_ready": True,
"two_independent_reviews_complete": len(submissions) == 2,
"adjudication_ready": len(submissions) == 2,
"e48_sealed": False,
"l35_open": False,
"next_action": (
"complete two distinct prediction-free reviewer submissions"
if len(submissions) < 2
else "adjudicate both frozen reviews before E48 seal"
),
},
"blindness": {
"candidate_identity_included": False,
"model_prelabels_included": False,
"model_predictions_included": False,
"model_scores_included": False,
},
"authority": _AUTHORITY,
"ground_truth": False,
"access": "review-collection-read-only-summary",
}
def _project_submission(result: dict[str, Any]) -> dict[str, object]:
identity = result["manifest"]["identity"]
return {
"result_id": result["result_id"],
"created_at_utc": result["manifest"]["created_at_utc"],
"truth_island_id": identity["truth_island_id"],
"annotation_session_id": identity["annotation_session_id"],
"reviewer_id": identity["reviewer_id"],
"state": result["manifest"]["state"],
"frame_count": len(result["review"]["images"]),
"object_count": sum(len(item["objects"]) for item in result["review"]["images"]),
"blindness": copy.deepcopy(identity["blindness"]),
"authority": copy.deepcopy(identity["authority"]),
"ground_truth": False,
"access": "immutable-e48-review-input",
}
def _submissions_for_truth(
provider: RootProvider,
truth_root: Path,
truth_id: str,
) -> list[dict[str, object]]:
root = _configured_root(provider)
if root is None:
return []
items: list[dict[str, object]] = []
for path in sorted(root.iterdir(), key=lambda item: item.stat().st_mtime_ns):
if not path.is_dir() or path.is_symlink() or _SUBMISSION_ID.fullmatch(path.name) is None:
continue
try:
result = read_e46_lab_review_submission(path, truth_island_root=truth_root)
if result["manifest"]["identity"]["truth_island_id"] == truth_id:
items.append(_project_submission(result))
except (E46LabReviewSubmissionError, OSError):
continue
return items
def _review_contract() -> dict[str, object]:
return {
"contract_id": "e46-detector-blind-review/v1",
"classes": list(_TARGET_CLASSES),
"unmapped_class": None,
"box_format": "xyxy-pixels-800x600",
"all_identifiable_instances_required": True,
"inside_valid_fov_only": True,
"hard_negative_frame_flag_required": True,
"occluded_and_truncated_flags_required": True,
}
def _truth_candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
path
for path in root.iterdir()
if path.is_dir() and not path.is_symlink() and _TRUTH_ID.fullmatch(path.name)
),
key=lambda path: path.stat().st_mtime_ns,
reverse=True,
)
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _read_jsonl(path: Path) -> list[dict[str, Any]]:
rows = [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines() if line]
if any(not isinstance(row, dict) for row in rows):
raise ValueError("invalid E46 references")
return rows
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
@@ -0,0 +1,383 @@
"""Read-only LAB projection for E46A AI engineering preannotations."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Annotated, Any
from fastapi import APIRouter, HTTPException, Query
from fastapi import Path as ApiPath
from k1link.compute.e46a_ai_engineering_preannotation import (
E46AAiEngineeringPreannotationError,
read_e46a_ai_engineering_preannotation,
)
from k1link.web.l34_annotation_api import (
L34_ANNOTATION_LABEL_CATALOG_SCHEMA,
L34_ANNOTATION_SEED_SCHEMA,
L34_ANNOTATION_SESSION_CATALOG_SCHEMA,
L34_ANNOTATION_SOURCE_CATALOG_SCHEMA,
L34_ANNOTATION_SOURCE_SCHEMA,
L34AnnotationCreateRequest,
L34AnnotationSaveRequest,
_annotation_contract,
_L34AnnotationSessionStore,
_normalize_object,
)
_RESULT_ID = re.compile(r"^e46a-ai-engineering-preannotation-[a-f0-9]{64}$")
_SESSION_ID = re.compile(r"^l34-annotation-session-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
def build_e46a_ai_engineering_preannotation_router(
*,
root_provider: RootProvider = lambda: None,
annotation_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46a", tags=["laboratory"])
store = _L34AnnotationSessionStore(
annotation_root_provider,
result_id_pattern=_RESULT_ID,
lab_label="E46A correction",
initial_assistance_mode="frozen-candidate-seeded",
allowed_assistance_modes=frozenset({"frozen-candidate-seeded"}),
contract_id_overrides={
"frozen-candidate-seeded": "e46a-ai-engineering-correction/v1"
},
)
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46A result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46A result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46A result не найден")
try:
return read_e46a_ai_engineering_preannotation(path)
except (E46AAiEngineeringPreannotationError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46A result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46a-ai-engineering-preannotation-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-non-truth",
}
@router.get("/results/{result_id}/cases/{sequence}")
def get_case(result_id: str, sequence: int) -> dict[str, object]:
if sequence < 1 or sequence > 32:
raise HTTPException(status_code=404, detail="E46A frame не найден")
frozen = result(result_id)
case = next(
(
item
for item in frozen["cases"]
if item.get("truth_island_sequence") == sequence
),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="E46A frame не найден")
identity = frozen["manifest"].get("identity")
e46_source = identity.get("e46_source") if isinstance(identity, dict) else None
e46_result_id = (
e46_source.get("result_id") if isinstance(e46_source, dict) else None
)
if not isinstance(e46_result_id, str):
raise HTTPException(status_code=404, detail="E46A source не найден")
return {
**copy.deepcopy(case),
"result_id": result_id,
"camera_url": (
f"/api/v1/laboratory/e46/results/{e46_result_id}"
f"/annotation-source/frames/{sequence}/camera"
),
"candidate_identity_included": True,
"model_predictions_seen_during_source_adjudication": True,
"model_scores_included": False,
"independent_review": False,
"ground_truth": False,
"access": "read-only-ai-engineering-preannotation-not-truth",
}
def annotation_case(result_id: str, sequence: int) -> tuple[dict[str, Any], dict[str, Any]]:
frozen = result(result_id)
case = next(
(
item
for item in frozen["cases"]
if item.get("truth_island_sequence") == sequence
),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="E46A frame не найден")
return frozen, case
def source_projection(case: dict[str, Any]) -> dict[str, object]:
group_id = str(case["group_id"])
return {
"truth_island_sequence": int(case["truth_island_sequence"]),
"image_id": int(case["image_id"]),
"frame_index": int(case["frame_index"]),
"group_id": group_id,
"role": "temporal" if group_id.startswith("clip-") else "anchor",
"session_seconds": float(case["session_seconds"]),
"camera": {
"width": 800,
"height": 600,
"sha256": str(case["source_image_sha256"]),
},
}
def e46_source_id(frozen: dict[str, Any]) -> str:
identity = frozen["manifest"].get("identity")
source = identity.get("e46_source") if isinstance(identity, dict) else None
source_id = source.get("result_id") if isinstance(source, dict) else None
if not isinstance(source_id, str):
raise HTTPException(status_code=404, detail="E46A source не найден")
return source_id
@router.get("/results/{result_id}/annotation-source")
def get_annotation_source_catalog(result_id: str) -> dict[str, object]:
frozen = result(result_id)
frames = [source_projection(case) for case in frozen["cases"]]
return {
"schema_version": L34_ANNOTATION_SOURCE_CATALOG_SCHEMA,
"result_id": result_id,
"truth_island_id": e46_source_id(frozen),
"contract": _annotation_contract(
contract_id="e46a-ai-engineering-correction/v1"
),
"frames": frames,
"frame_count": len(frames),
"model_material_included": False,
"candidate_identity_included": True,
"candidate_predictions_included": False,
"prelabels_included": False,
"access": "ai-engineering-correction-source-read-only",
}
@router.get("/results/{result_id}/annotation-source/frames/{sequence}")
def get_annotation_source_frame(result_id: str, sequence: int) -> dict[str, object]:
frozen, case = annotation_case(result_id, sequence)
source_id = e46_source_id(frozen)
return {
"schema_version": L34_ANNOTATION_SOURCE_SCHEMA,
"result_id": result_id,
**source_projection(case),
"camera_url": (
f"/api/v1/laboratory/e46/results/{source_id}"
f"/annotation-source/frames/{sequence}/camera"
),
"model_material_included": False,
"candidate_identity_included": True,
"candidate_predictions_included": False,
"prelabels_included": False,
"access": "ai-engineering-correction-source-read-only",
}
@router.get("/results/{result_id}/annotation-seed/frames/{sequence}")
def get_annotation_seed_frame(result_id: str, sequence: int) -> dict[str, object]:
_, case = annotation_case(result_id, sequence)
objects: list[dict[str, object]] = []
for raw in case["objects"]:
category = str(raw["category"])
proposed_label: str | None = None
if category == "stroller":
category = "unmapped"
proposed_label = "Коляска"
elif category == "laptop":
category = "unmapped"
proposed_label = "Ноутбук"
objects.append(
{
"object_id": str(raw["object_id"]),
"category": category,
"proposed_label": proposed_label,
"origin": "frozen_candidate_seed",
"box_xyxy": copy.deepcopy(raw["box_xyxy"]),
"occluded": bool(raw["occluded"]),
"truncated": bool(raw["truncated"]),
}
)
return {
"schema_version": L34_ANNOTATION_SEED_SCHEMA,
"result_id": result_id,
"truth_island_sequence": sequence,
"source_sha256": str(case["source_image_sha256"]),
"objects": objects,
"assistance": {
"mode": "frozen-candidate-seeded",
"independent_truth_eligible": False,
},
"model_material_included": True,
"access": "ai-engineering-preannotation-seed-read-only",
}
@router.get("/results/{result_id}/annotation-sessions")
def list_annotation_sessions(result_id: str) -> dict[str, object]:
annotation_case(result_id, 1)
items = store.list(result_id)
return {
"schema_version": L34_ANNOTATION_SESSION_CATALOG_SCHEMA,
"result_id": result_id,
"items": items,
"total": len(items),
"access": "ai-engineering-human-correction",
}
@router.get("/results/{result_id}/annotation-labels")
def get_annotation_labels(result_id: str) -> dict[str, object]:
annotation_case(result_id, 1)
values = {"коляска": "Коляска", "ноутбук": "Ноутбук"}
for item in store.labels(result_id):
label = str(item["value"])
values[label.casefold()] = label
items = [
{"value": value, "normalization_state": "pending-adjudication"}
for value in sorted(values.values(), key=str.casefold)
]
return {
"schema_version": L34_ANNOTATION_LABEL_CATALOG_SCHEMA,
"result_id": result_id,
"items": items,
"total": len(items),
"access": "ai-engineering-correction-taxonomy",
}
@router.post("/results/{result_id}/annotation-sessions")
def create_annotation_session(
result_id: str,
request: L34AnnotationCreateRequest,
) -> dict[str, object]:
frozen, _ = annotation_case(result_id, 1)
return store.create(
result_id=result_id,
truth_island_id=e46_source_id(frozen),
idempotency_key=request.idempotency_key,
)
@router.get("/results/{result_id}/annotation-sessions/{session_id}")
def get_annotation_session(
result_id: str,
session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)],
) -> dict[str, object]:
annotation_case(result_id, 1)
return store.get(result_id, session_id)
@router.put("/results/{result_id}/annotation-sessions/{session_id}")
def save_annotation_session(
result_id: str,
session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)],
request: L34AnnotationSaveRequest,
) -> dict[str, object]:
if request.assistance_mode != "frozen-candidate-seeded":
raise HTTPException(status_code=422, detail="Режим E46A correction запрещён")
sequences: set[int] = set()
frames: list[dict[str, object]] = []
for frame in request.frames:
sequence = frame.truth_island_sequence
if sequence in sequences:
raise HTTPException(status_code=422, detail="Кадр размечен дважды")
sequences.add(sequence)
_, case = annotation_case(result_id, sequence)
objects = [
_normalize_object(item, width=800, height=600) for item in frame.objects
]
if frame.hard_negative != (len(objects) == 0):
raise HTTPException(
status_code=422,
detail="Пустой кадр должен быть явно отмечен",
)
frames.append(
{
"truth_island_sequence": sequence,
"image_id": int(case["image_id"]),
"frame_index": int(case["frame_index"]),
"source_sha256": str(case["source_image_sha256"]),
"reviewed": True,
"hard_negative": frame.hard_negative,
"objects": objects,
}
)
frames.sort(key=lambda item: int(item["truth_island_sequence"]))
return store.save(
result_id=result_id,
session_id=session_id,
request=request,
frames=frames,
)
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
manifest = frozen["manifest"]
report = frozen["report"]
identity = manifest.get("identity")
e46_source = identity.get("e46_source") if isinstance(identity, dict) else None
return {
"schema_version": "missioncore.e46a-ai-engineering-preannotation-view/v1",
"result_id": frozen["result_id"],
"created_at_utc": report.get("created_at_utc"),
"source_session_id": report.get("source_session_id"),
"camera_source_id": report.get("camera_source_id"),
"source_e46_result_id": (
e46_source.get("result_id") if isinstance(e46_source, dict) else None
),
"metrics": copy.deepcopy(report.get("metrics")),
"assistance": copy.deepcopy(report.get("assistance")),
"taxonomy": copy.deepcopy(report.get("taxonomy")),
"decision": copy.deepcopy(report.get("decision")),
"limitations": copy.deepcopy(report.get("limitations")),
"authority": copy.deepcopy(report.get("authority")),
"ground_truth": False,
"access": "read-only-ai-engineering-preannotation-not-truth",
}
def _configured_root(provider: RootProvider) -> Path | None:
configured = provider()
if configured is None:
return None
return configured.expanduser().absolute()
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None or not root.is_dir() or root.is_symlink():
return []
return sorted(
(
path
for path in root.iterdir()
if path.is_dir()
and not path.is_symlink()
and _RESULT_ID.fullmatch(path.name) is not None
),
key=lambda path: (path.stat().st_mtime_ns, path.name),
reverse=True,
)
+133
View File
@@ -0,0 +1,133 @@
"""Read-only LAB projection for E46B temporal tracks and motion state."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from k1link.compute.e46b_temporal_motion import (
E46BTemporalMotionError,
read_e46b_temporal_motion,
)
_RESULT_ID = re.compile(r"^e46b-temporal-motion-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
def build_e46b_temporal_motion_router(
*, root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46b", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46B result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46B result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46B result не найден")
try:
return read_e46b_temporal_motion(path)
except (E46BTemporalMotionError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46B result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46b-temporal-motion-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-engineering-evidence",
}
@router.get("/results/{result_id}/cases/{sequence}")
def get_case(result_id: str, sequence: int) -> dict[str, object]:
frozen = result(result_id)
case = next(
(item for item in frozen["cases"] if item.get("truth_island_sequence") == sequence),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="E46B frame не найден")
identity = frozen["manifest"]["identity"]
e46_result_id = identity["e46_source"]["result_id"]
return {
**copy.deepcopy(case),
"result_id": result_id,
"camera_url": (
f"/api/v1/laboratory/e46/results/{e46_result_id}"
f"/annotation-source/frames/{sequence}/camera"
),
"ground_truth": False,
"access": "read-only-source-scoped-temporal-motion",
}
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
identity = frozen["manifest"]["identity"]
return {
"schema_version": "missioncore.e46b-temporal-motion-view/v1",
"result_id": frozen["result_id"],
"created_at_utc": report["created_at_utc"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"source_e46a_result_id": identity["e46a_source"]["result_id"],
"source_e26_result_id": identity["e26_motion_source"]["result_id"],
"status": report["status"],
"metrics": copy.deepcopy(report["metrics"]),
"tracks": copy.deepcopy(report["tracks"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"ground_truth": False,
"access": "read-only-engineering-evidence",
}
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,396 @@
"""Read-only LAB projection for E46C full-replay world tracks."""
from __future__ import annotations
import copy
import hashlib
import json
import math
import re
from collections.abc import Callable
from functools import lru_cache
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from k1link.compute.e46c_full_replay_world_tracks import (
E46CFullReplayWorldTracksError,
read_e46c_full_replay_world_tracks,
)
_RESULT_ID = re.compile(r"^e46c-full-replay-world-tracks-[a-f0-9]{64}$")
_E26_RESULT_ID = re.compile(r"^e10-integrated-perception-[a-f0-9]{64}$")
_SAFE_SESSION_ID = re.compile(r"^[A-Za-z0-9._:-]{1,128}$")
RootProvider = Callable[[], Path | None]
def build_e46c_full_replay_world_tracks_router(
*,
root_provider: RootProvider = lambda: None,
e26_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46c", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46C result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46C result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46C result не найден")
try:
return read_e46c_full_replay_world_tracks(path)
except (E46CFullReplayWorldTracksError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46C result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46c-full-replay-world-tracks-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-diagnostic",
}
@router.get("/results/{result_id}/cases/{sequence}")
def get_case(result_id: str, sequence: int) -> dict[str, object]:
frozen = result(result_id)
case = next(
(item for item in frozen["cases"] if item.get("truth_island_sequence") == sequence),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="E46C frame не найден")
e46_result_id = frozen["manifest"]["identity"]["e46_source"]["result_id"]
return {
**copy.deepcopy(case),
"result_id": result_id,
"camera_url": (
f"/api/v1/laboratory/e46/results/{e46_result_id}"
f"/annotation-source/frames/{sequence}/camera"
),
"ground_truth": False,
"access": "read-only-full-route-diagnostic-sample",
}
@router.get("/results/{result_id}/video-overlay")
def get_video_overlay(result_id: str) -> dict[str, object]:
frozen = result(result_id)
e26_root = _configured_root(e26_root_provider)
if e26_root is None:
raise HTTPException(status_code=404, detail="E46C video overlay не найден")
identity = frozen["manifest"]["identity"]["e26_full_replay"]
source_result_id = identity.get("result_id")
expected_result_sha256 = identity.get("result_sha256")
expected_fusion_sha256 = identity.get("fusion_frames_sha256")
if (
not isinstance(source_result_id, str)
or _E26_RESULT_ID.fullmatch(source_result_id) is None
or not isinstance(expected_result_sha256, str)
or not isinstance(expected_fusion_sha256, str)
):
raise HTTPException(status_code=404, detail="E46C video overlay не найден")
source_path = (e26_root / source_result_id).resolve()
if source_path.parent != e26_root or source_path.is_symlink():
raise HTTPException(status_code=404, detail="E46C video overlay не найден")
try:
return _cached_video_overlay(
result_id,
str(source_path),
expected_result_sha256,
expected_fusion_sha256,
)
except (OSError, ValueError, json.JSONDecodeError):
raise HTTPException(
status_code=404,
detail="E46C video overlay не найден",
) from None
return router
@lru_cache(maxsize=4)
def _cached_video_overlay(
e46c_result_id: str,
source_root_value: str,
expected_result_sha256: str,
expected_fusion_sha256: str,
) -> dict[str, object]:
source_root = Path(source_root_value).resolve(strict=True)
if source_root.is_symlink() or not source_root.is_dir():
raise ValueError("E26 source root is invalid")
result_path = source_root / "result.json"
if _sha256(result_path) != expected_result_sha256:
raise ValueError("E26 result identity changed")
result = _read_json(result_path)
identity = result.get("identity")
artifacts = result.get("artifacts")
if (
result.get("schema_version")
!= "missioncore.e10-integrated-perception-result/v1"
or result.get("acceptance_state") != "accepted"
or not isinstance(identity, dict)
or not isinstance(artifacts, list)
):
raise ValueError("E26 result contract is invalid")
selection = identity.get("selection")
configuration = identity.get("configuration")
if not isinstance(selection, dict) or not isinstance(configuration, dict):
raise ValueError("E26 timeline contract is invalid")
recorded_session_id = configuration.get("source_session_id")
if (
not isinstance(recorded_session_id, str)
or _SAFE_SESSION_ID.fullmatch(recorded_session_id) is None
or identity.get("source_id") != "sensor.camera.right"
or selection.get("frame_count") != 4489
):
raise ValueError("E26 recorded source binding is invalid")
fusion_artifact = next(
(
item
for item in artifacts
if isinstance(item, dict) and item.get("path") == "fusion-frames.jsonl"
),
None,
)
fusion_path = _validated_source_artifact(
source_root,
fusion_artifact,
expected_fusion_sha256,
)
frames: list[dict[str, object]] = []
previous_seconds = -math.inf
for expected_frame_index, row in enumerate(_read_jsonl(fusion_path)):
frame_index = row.get("source_frame_index")
session_seconds = row.get("session_seconds")
raw_objects = row.get("objects")
if (
frame_index != expected_frame_index
or not isinstance(session_seconds, int | float)
or isinstance(session_seconds, bool)
or not math.isfinite(float(session_seconds))
or float(session_seconds) <= previous_seconds
or not isinstance(raw_objects, list)
):
raise ValueError("E26 video frame sequence is invalid")
previous_seconds = float(session_seconds)
frames.append(
{
"frame_index": frame_index,
"session_seconds": float(session_seconds),
"fusion_state": str(row.get("fusion_state", "unknown")),
"objects": [
_video_object(item)
for item in raw_objects
if isinstance(item, dict)
],
}
)
timeline_start = float(selection.get("timeline_start_seconds"))
timeline_end = float(selection.get("timeline_end_seconds"))
if (
len(frames) != 4489
or frames[0]["session_seconds"] != timeline_start
or frames[-1]["session_seconds"] != timeline_end
):
raise ValueError("E26 video timeline changed")
benchmark = configuration.get("benchmark")
benchmark_events = benchmark.get("events") if isinstance(benchmark, dict) else None
review_windows = []
if isinstance(benchmark_events, list):
for event in benchmark_events:
if not isinstance(event, dict):
continue
window = event.get("window_seconds")
if (
not isinstance(window, list)
or len(window) != 2
or not all(isinstance(item, int | float) for item in window)
):
continue
review_windows.append(
{
"id": str(event.get("id", "review-window")),
"kind": str(event.get("kind", "diagnostic")),
"class_group": str(event.get("class_group", "all")),
"start_seconds": float(window[0]),
"end_seconds": float(window[1]),
"target_source_track_ids": [
int(value)
for value in event.get("target_source_track_ids", [])
if isinstance(value, int) and not isinstance(value, bool)
],
}
)
return {
"schema_version": "missioncore.e46c-recorded-video-overlay/v1",
"result_id": e46c_result_id,
"recorded_source": {
"session_id": recorded_session_id,
"source_id": "sensor.camera.right",
"input_sha256": identity.get("input_sha256"),
"synchronization": "host-arrival-best-effort",
},
"image_width": 800,
"image_height": 600,
"timeline_start_seconds": timeline_start,
"timeline_end_seconds": timeline_end,
"frame_count": len(frames),
"frames": frames,
"review_windows": review_windows,
"ground_truth": False,
"access": "read-only-full-route-diagnostic-video",
}
def _video_object(item: dict[str, Any]) -> dict[str, object]:
box = item.get("bbox_xyxy")
if (
not isinstance(box, list)
or len(box) != 4
or not all(
isinstance(value, int | float)
and not isinstance(value, bool)
and math.isfinite(float(value))
for value in box
)
):
raise ValueError("E26 video object box is invalid")
source_track_id = item.get("source_track_id")
world_track_id = item.get("track_id")
if not isinstance(source_track_id, int) or isinstance(source_track_id, bool):
raise ValueError("E26 video object track is invalid")
if not isinstance(world_track_id, int) or isinstance(world_track_id, bool):
world_track_id = source_track_id
return {
"bbox_xyxy": [float(value) for value in box],
"category": str(item.get("label", "unknown")),
"score": float(item.get("score") or 0.0),
"route_track_id": source_track_id,
"world_track_id": (
world_track_id if world_track_id != source_track_id else None
),
"motion_state": str(item.get("motion_state", "unknown")),
"motion_confidence": float(item.get("motion_confidence") or 0.0),
"track_hits": int(item.get("track_hits") or 0),
"track_age_seconds": float(item.get("track_age_s") or 0.0),
"camera_evidence_current": item.get("camera_evidence_current") is True,
"world_evidence_current": item.get("occupancy_evidence_current") is True,
}
def _validated_source_artifact(
root: Path,
raw: object,
expected_sha256: str,
) -> Path:
if not isinstance(raw, dict) or raw.get("sha256") != expected_sha256:
raise ValueError("E26 fusion artifact identity changed")
relative = raw.get("path")
if not isinstance(relative, str):
raise ValueError("E26 fusion artifact path is invalid")
path = (root / relative).resolve(strict=True)
expected_size = raw.get("byte_length", raw.get("size_bytes"))
if (
path.parent != root
or path.is_symlink()
or not path.is_file()
or path.stat().st_size != expected_size
or _sha256(path) != expected_sha256
):
raise ValueError("E26 fusion artifact changed")
return path
def _read_json(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise ValueError("JSON document is invalid")
return value
def _read_jsonl(path: Path):
with path.open("r", encoding="utf-8") as handle:
for line in handle:
if line.strip():
value = json.loads(line)
if not isinstance(value, dict):
raise ValueError("JSONL row is invalid")
yield value
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for block in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
identity = frozen["manifest"]["identity"]
return {
"schema_version": "missioncore.e46c-full-replay-world-tracks-view/v1",
"result_id": frozen["result_id"],
"created_at_utc": report["created_at_utc"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"source_e46a_result_id": identity["e46a_visual_sample"]["result_id"],
"source_e26_result_id": identity["e26_full_replay"]["result_id"],
"status": report["status"],
"metrics": copy.deepcopy(report["metrics"]),
"acceptance": copy.deepcopy(report["acceptance"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"ground_truth": False,
"access": "read-only-diagnostic",
}
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir()
and not item.is_symlink()
and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,114 @@
"""Read-only LAB projection for the E46D full-route temporal audit."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from k1link.compute.e46d_temporal_failure_audit import (
E46DTemporalFailureAuditError,
read_e46d_temporal_failure_audit,
)
_RESULT_ID = re.compile(r"^e46d-temporal-failure-audit-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
def build_e46d_temporal_failure_audit_router(
*, root_provider: RootProvider = lambda: None
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46d", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46D result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46D result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46D result не найден")
try:
return read_e46d_temporal_failure_audit(path)
except (E46DTemporalFailureAuditError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46D result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46d-temporal-failure-audit-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-recorded-temporal-diagnostic",
}
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
identity = frozen["manifest"]["identity"]
return {
"schema_version": "missioncore.e46d-temporal-failure-audit-view/v1",
"result_id": frozen["result_id"],
"created_at_utc": report["created_at_utc"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"source_e46c_result_id": identity["e46c_source"]["result_id"],
"source_e26_result_id": identity["e26_source"]["result_id"],
"status": report["status"],
"metrics": copy.deepcopy(report["metrics"]),
"acceptance": copy.deepcopy(report["acceptance"]),
"decision": copy.deepcopy(report["decision"]),
"method": copy.deepcopy(report["method"]),
"limitations": copy.deepcopy(report["limitations"]),
"review_clips": copy.deepcopy(frozen["clips"]),
"ground_truth": False,
"access": "read-only-recorded-temporal-diagnostic",
}
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
+149
View File
@@ -0,0 +1,149 @@
"""Read-only LAB projection and video delivery for the E46E NVIDIA ready stack."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.e46e_ready_stack import (
E46EReadyStackError,
read_e46e_ready_stack,
)
_RESULT_ID = re.compile(r"^e46e-ready-stack-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
def build_e46e_ready_stack_router(
*, root_provider: RootProvider = lambda: None
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46e", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46E result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46E result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46E result не найден")
try:
return read_e46e_ready_stack(path)
except (E46EReadyStackError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46E result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46e-ready-stack-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-stock-nvidia-recorded-diagnostic",
}
@router.get("/results/{result_id}/overlay.mp4")
def get_overlay_video(result_id: str) -> FileResponse:
frozen = result(result_id)
overlay = frozen["overlay_path"]
descriptor = next(
(
row
for row in frozen["manifest"]["artifacts"]
if row.get("role") == "visual-overlay-video"
),
None,
)
if not isinstance(descriptor, dict):
raise HTTPException(status_code=404, detail="E46E video не найден")
return FileResponse(
overlay,
media_type="video/mp4",
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"ETag": f'"{descriptor["sha256"]}"',
"X-Content-Type-Options": "nosniff",
},
)
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
overlay = next(
row
for row in frozen["manifest"]["artifacts"]
if row.get("role") == "visual-overlay-video"
)
result_id = frozen["result_id"]
return {
"schema_version": "missioncore.e46e-ready-stack-view/v1",
"result_id": result_id,
"created_at_utc": report["created_at_utc"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"status": report["status"],
"metrics": copy.deepcopy(report["metrics"]),
"acceptance": copy.deepcopy(report["acceptance"]),
"decision": copy.deepcopy(report["decision"]),
"method": copy.deepcopy(report["method"]),
"limitations": copy.deepcopy(report["limitations"]),
"video": {
"url": f"/api/v1/laboratory/e46e/results/{result_id}/overlay.mp4",
"media_type": "video/mp4",
"byte_length": overlay["byte_length"],
"sha256": overlay["sha256"],
"width": 800,
"height": 600,
},
"ground_truth": False,
"access": "read-only-stock-nvidia-recorded-diagnostic",
}
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
+230
View File
@@ -0,0 +1,230 @@
"""Read-only LAB projection for the E46F DashCamNet detector bake-off."""
from __future__ import annotations
import copy
import re
from collections import Counter
from collections.abc import Callable, Iterable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.e46e_ready_stack import (
E46EReadyStackError,
read_e46e_ready_stack,
)
from k1link.compute.e46f_dashcam_bakeoff import (
E46FDashCamBakeoffError,
read_e46f_dashcam_bakeoff,
)
_RESULT_ID = re.compile(r"^e46f-dashcam-bakeoff-[a-f0-9]{64}$")
_BASELINE_ID = re.compile(r"^e46e-ready-stack-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
def build_e46f_dashcam_bakeoff_router(
*,
root_provider: RootProvider = lambda: None,
e46e_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46f", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46F result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46F result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46F result не найден")
try:
return read_e46f_dashcam_bakeoff(path)
except (E46FDashCamBakeoffError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46F result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen, e46e_root_provider))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46f-dashcam-bakeoff-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-rejected-detector-bakeoff",
}
@router.get("/results/{result_id}/overlay.mp4")
def get_overlay_video(result_id: str) -> FileResponse:
frozen = result(result_id)
descriptor = next(
(
row
for row in frozen["manifest"]["artifacts"]
if row.get("role") == "visual-overlay-video"
),
None,
)
if not isinstance(descriptor, dict):
raise HTTPException(status_code=404, detail="E46F video не найден")
return FileResponse(
frozen["overlay_path"],
media_type="video/mp4",
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"ETag": f'"{descriptor["sha256"]}"',
"X-Content-Type-Options": "nosniff",
},
)
return router
def _project_result(frozen: dict[str, Any], e46e_root_provider: RootProvider) -> dict[str, object]:
report = frozen["report"]
overlay = next(
row for row in frozen["manifest"]["artifacts"] if row.get("role") == "visual-overlay-video"
)
baseline_id = report["comparison_contract"]["baseline_result_id"]
baseline = _read_baseline(e46e_root_provider, baseline_id)
baseline_metrics = baseline["report"]["metrics"]
metrics = report["metrics"]
candidate_triage = _large_box_triage(frozen["frames"])
baseline_triage = _large_box_triage(baseline["frames"])
result_id = frozen["result_id"]
return {
"schema_version": "missioncore.e46f-dashcam-bakeoff-view/v1",
"result_id": result_id,
"created_at_utc": report["created_at_utc"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"status": report["status"],
"metrics": copy.deepcopy(metrics),
"acceptance": copy.deepcopy(report["acceptance"]),
"decision": copy.deepcopy(report["decision"]),
"method": copy.deepcopy(report["method"]),
"limitations": copy.deepcopy(report["limitations"]),
"comparison": {
"controlled_change": "detector-only",
"baseline_result_id": baseline_id,
"baseline_metrics": copy.deepcopy(baseline_metrics),
"delta": {
"zero_track_frame_count": metrics["zero_track_frame_count"]
- baseline_metrics["zero_track_frame_count"],
"full_layer_blackout_event_count": metrics["full_layer_blackout_event_count"]
- baseline_metrics["full_layer_blackout_event_count"],
"unique_track_count": metrics["unique_track_count"]
- baseline_metrics["unique_track_count"],
"short_track_fraction": metrics["short_track_fraction"]
- baseline_metrics["short_track_fraction"],
},
"large_box_visual_triage": {
"area_ratio_threshold": 0.2,
"candidate": candidate_triage,
"baseline": baseline_triage,
"interpretation": "diagnostic visual triage; not precision/recall",
},
"visual_review": {
"status": "rejected-semantic-regression",
"sample_video_seconds": [4.2, 9.0, 22.0, 44.0, 264.0, 418.0],
"finding": (
"DashCamNet repeatedly turns the fisheye black rim and edge geometry "
"into very large person tracks; temporal continuity improves, but the "
"semantic object layer is less trustworthy than E46E"
),
"next_action": (
"insert one calibration-derived rectification and valid-FOV projection "
"before any perspective ready detector, then repeat the controlled bake-off"
),
},
"verdict": "reject-dashcamnet-on-unrectified-fisheye",
},
"video": {
"url": f"/api/v1/laboratory/e46f/results/{result_id}/overlay.mp4",
"media_type": "video/mp4",
"byte_length": overlay["byte_length"],
"sha256": overlay["sha256"],
"width": 800,
"height": 600,
},
"ground_truth": False,
"access": "read-only-rejected-detector-bakeoff",
}
def _read_baseline(provider: RootProvider, result_id: str) -> dict[str, Any]:
root = _configured_root(provider)
if root is None or _BASELINE_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46E baseline не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46E baseline не найден")
try:
return read_e46e_ready_stack(path)
except (E46EReadyStackError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46E baseline не найден") from None
def _large_box_triage(frames: Iterable[dict[str, Any]]) -> dict[str, object]:
observation_count = 0
frame_ids: set[int] = set()
track_ids: set[int] = set()
classes: Counter[str] = Counter()
for frame in frames:
for item in frame["objects"]:
_, _, width, height = item["bbox"]
if float(width) * float(height) < 800 * 600 * 0.2:
continue
observation_count += 1
frame_ids.add(int(frame["frame_index"]))
track_ids.add(int(item["source_track_id"]))
classes.update((str(item["class_name"]),))
return {
"observation_count": observation_count,
"frame_count": len(frame_ids),
"track_id_count": len(track_ids),
"class_observations": dict(sorted(classes.items())),
}
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,185 @@
"""Read-only LAB projection for the calibrated E46G ready-detector bake-off."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.e46g_rectified_detector_bakeoff import (
E46GRectifiedDetectorBakeoffError,
read_e46g_rectified_detector_bakeoff,
)
_RESULT_ID = re.compile(r"^e46g-rectified-detector-bakeoff-[a-f0-9]{64}$")
_CANDIDATES = ("trafficcamnet", "dashcamnet")
RootProvider = Callable[[], Path | None]
def build_e46g_rectified_detector_bakeoff_router(
*, root_provider: RootProvider = lambda: None
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46g", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46G result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46G result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46G result не найден")
try:
return read_e46g_rectified_detector_bakeoff(path)
except (E46GRectifiedDetectorBakeoffError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46G result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46g-rectified-detector-bakeoff-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-diagnostic-selection",
}
@router.get("/results/{result_id}/{candidate}.mp4")
def get_comparison_video(result_id: str, candidate: str) -> FileResponse:
if candidate not in _CANDIDATES:
raise HTTPException(status_code=404, detail="E46G video не найден")
frozen = result(result_id)
descriptor = _video_descriptor(frozen, candidate)
return FileResponse(
frozen["comparison_paths"][candidate],
media_type="video/mp4",
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"ETag": f'"{descriptor["sha256"]}"',
"X-Content-Type-Options": "nosniff",
},
)
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
result_id = frozen["result_id"]
videos = {
candidate: {
"url": f"/api/v1/laboratory/e46g/results/{result_id}/{candidate}.mp4",
"media_type": "video/mp4",
"byte_length": descriptor["byte_length"],
"sha256": descriptor["sha256"],
"width": 2880,
"height": 544,
"duration_seconds": 60.0,
"view_order": ["left", "front", "right"],
}
for candidate in _CANDIDATES
for descriptor in (_video_descriptor(frozen, candidate),)
}
return {
"schema_version": "missioncore.e46g-rectified-detector-bakeoff-view/v1",
"result_id": result_id,
"created_at_utc": report["created_at_utc"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"status": "selected-for-next-diagnostic-full-route",
"selection": copy.deepcopy(report["selection"]),
"rectification": copy.deepcopy(report["rectification"]),
"metrics": copy.deepcopy(report["metrics"]),
"acceptance": copy.deepcopy(report["acceptance"]),
"method": copy.deepcopy(report["method"]),
"limitations": copy.deepcopy(report["limitations"]),
"comparison": {
"controlled_change": "detector-provider-only",
"visual_review": {
"status": "selected-for-next-diagnostic",
"reviewed_video_seconds": [0.0, 10.0, 20.0, 30.0, 40.0, 50.0],
"selected_candidate": "trafficcamnet",
"selected_view": "front",
"excluded_views": ["left", "right"],
"finding": (
"The calibrated FRONT projection is useful. TrafficCamNet preserves "
"substantially more visible vehicles and people than DashCamNet, while "
"DashCamNet repeatedly leaves visible road objects undetected."
),
"risk": (
"TrafficCamNet still produces duplicate or stale boxes around some "
"vehicles. LEFT and RIGHT projections are dominated by the camera mount "
"and trigger large semantic false tracks, so they are excluded."
),
"next_action": (
"run TrafficCamNet with stock NvDCF over the complete retained FRONT "
"projection and review the full temporal overlay before motion-state work"
),
},
"verdict": "select-trafficcamnet-front-only-for-e46h",
},
"videos": videos,
"ground_truth": False,
"authority": copy.deepcopy(report["authority"]),
"access": "read-only-diagnostic-selection",
}
def _video_descriptor(frozen: dict[str, Any], candidate: str) -> dict[str, Any]:
descriptor = next(
(
row
for row in frozen["manifest"]["artifacts"]
if row.get("role") == f"comparison-video-{candidate}"
),
None,
)
if not isinstance(descriptor, dict):
raise HTTPException(status_code=404, detail="E46G video не найден")
return descriptor
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,224 @@
"""Read-only LAB projection and video delivery for E46H."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.e46h_full_rectified_front_replay import (
E46HFullRectifiedFrontReplayError,
read_e46h_full_rectified_front_replay,
)
_RESULT_ID = re.compile(r"^e46h-full-rectified-front-replay-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
_REVIEW_WINDOWS = [
{
"id": "large-false-car-wall",
"label": "6.010.9 с · false car на стене",
"start_seconds": 6.0,
"end_seconds": 10.9,
"source_track_id": 6,
"verdict": "semantic-false-positive",
},
{
"id": "large-false-car-shrub",
"label": "178.6180.3 с · false car на кусте",
"start_seconds": 178.6,
"end_seconds": 180.3,
"source_track_id": 371,
"verdict": "semantic-false-positive",
},
{
"id": "large-false-car-ground",
"label": "250.7265.6 с · false car на полотне",
"start_seconds": 250.7,
"end_seconds": 265.6,
"source_track_id": 481,
"verdict": "semantic-false-positive",
},
{
"id": "large-false-car-road",
"label": "392.2400.6 с · false car на дороге",
"start_seconds": 392.2,
"end_seconds": 400.6,
"source_track_id": 822,
"verdict": "semantic-false-positive",
},
{
"id": "empty-scene-not-blackout",
"label": "419.4–426.9 с · пустая сцена, не сбой",
"start_seconds": 419.4,
"end_seconds": 426.9,
"source_track_id": None,
"verdict": "empty-scene-expected",
},
{
"id": "large-false-car-terrace",
"label": "440.8448.4 с · false car на террасе",
"start_seconds": 440.8,
"end_seconds": 448.4,
"source_track_id": 927,
"verdict": "semantic-false-positive",
},
]
def build_e46h_full_rectified_front_replay_router(
*, root_provider: RootProvider = lambda: None
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46h", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46H result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46H result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46H result не найден")
try:
return read_e46h_full_rectified_front_replay(path)
except (E46HFullRectifiedFrontReplayError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46H result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46h-full-rectified-front-replay-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-full-route-diagnostic",
}
@router.get("/results/{result_id}/overlay.mp4")
def get_overlay_video(result_id: str) -> FileResponse:
frozen = result(result_id)
descriptor = _video_descriptor(frozen)
return FileResponse(
frozen["overlay_path"],
media_type="video/mp4",
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"ETag": f'"{descriptor["sha256"]}"',
"X-Content-Type-Options": "nosniff",
},
)
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
descriptor = _video_descriptor(frozen)
result_id = frozen["result_id"]
return {
"schema_version": "missioncore.e46h-full-rectified-front-replay-view/v1",
"result_id": result_id,
"created_at_utc": report["created_at_utc"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"status": "diagnostic-regression-large-semantic-false-tracks",
"baseline_result_id": report["baseline_result_id"],
"selection": copy.deepcopy(report["selection"]),
"rectification": copy.deepcopy(report["rectification"]),
"metrics": copy.deepcopy(report["metrics"]),
"acceptance": copy.deepcopy(report["acceptance"]),
"decision": copy.deepcopy(report["decision"]),
"method": copy.deepcopy(report["method"]),
"limitations": copy.deepcopy(report["limitations"]),
"visual_review": {
"status": "full-continuous-and-targeted-review-completed",
"complete_video_reviewed": True,
"reviewed_video_range_seconds": [0.0, 448.8],
"verdict": "useful-front-continuity-but-semantic-regression-blocks-promotion",
"review_windows": copy.deepcopy(_REVIEW_WINDOWS),
"finding": (
"FRONT is readable and most route objects are tracked, but five large false "
"car tracks attach to a wall, shrub, road surface and terrace."
),
"blackout_interpretation": (
"The two zero-track intervals at 419.4..426.9 video seconds show an actually "
"empty scene and are not object-layer failures."
),
"next_action": (
"do not tune the detector to this route; isolate a provider-level semantic "
"suppression or stronger ready model on the same immutable FRONT adapter"
),
},
"video": {
"url": f"/api/v1/laboratory/e46h/results/{result_id}/overlay.mp4",
"media_type": "video/mp4",
"byte_length": descriptor["byte_length"],
"sha256": descriptor["sha256"],
"width": 960,
"height": 544,
"duration_seconds": 448.8,
},
"ground_truth": False,
"authority": copy.deepcopy(report["authority"]),
"access": "read-only-full-route-diagnostic",
}
def _video_descriptor(frozen: dict[str, Any]) -> dict[str, Any]:
descriptor = next(
(
row
for row in frozen["manifest"]["artifacts"]
if row.get("role") == "visual-overlay-video"
),
None,
)
if not isinstance(descriptor, dict):
raise HTTPException(status_code=404, detail="E46H video не найден")
return descriptor
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,194 @@
"""Read-only LAB projection and visual evidence delivery for E46I."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.e46i_grounding_dino_full_replay import (
E46IGroundingDinoFullReplayError,
read_e46i_grounding_dino_full_replay,
)
_RESULT_ID = re.compile(r"^e46i-grounding-dino-full-replay-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
def build_e46i_grounding_dino_full_replay_router(
*, root_provider: RootProvider = lambda: None
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46i", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46I result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46I result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46I result не найден")
try:
return read_e46i_grounding_dino_full_replay(path)
except (E46IGroundingDinoFullReplayError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46I result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46i-grounding-dino-full-replay-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-full-route-diagnostic",
}
@router.get("/results/{result_id}/overlay.mp4")
def get_overlay_video(result_id: str) -> FileResponse:
frozen = result(result_id)
descriptor = _artifact_descriptor(frozen, "visual-overlay-video")
return _file_response(frozen["overlay_path"], descriptor, "video/mp4")
@router.get("/results/{result_id}/visual/{role}.png")
def get_visual(result_id: str, role: str) -> FileResponse:
roles = {
"shadow-gate": ("shadow-gate-contact-sheet", "shadow_sheet_path"),
"full-route": ("full-route-contact-sheet", "route_sheet_path"),
"targeted-windows": (
"targeted-windows-contact-sheet",
"targeted_sheet_path",
),
}
selected = roles.get(role)
if selected is None:
raise HTTPException(status_code=404, detail="E46I visual не найден")
frozen = result(result_id)
descriptor = _artifact_descriptor(frozen, selected[0])
return _file_response(frozen[selected[1]], descriptor, "image/png")
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
result_id = frozen["result_id"]
video = _artifact_descriptor(frozen, "visual-overlay-video")
visual_roles = {
"shadow_gate": "shadow-gate-contact-sheet",
"full_route": "full-route-contact-sheet",
"targeted_windows": "targeted-windows-contact-sheet",
}
visuals = {}
for key, role in visual_roles.items():
descriptor = _artifact_descriptor(frozen, role)
slug = role.removesuffix("-contact-sheet")
visuals[key] = {
"url": f"/api/v1/laboratory/e46i/results/{result_id}/visual/{slug}.png",
"media_type": "image/png",
"byte_length": descriptor["byte_length"],
"sha256": descriptor["sha256"],
}
return {
"schema_version": "missioncore.e46i-grounding-dino-full-replay-view/v1",
"result_id": result_id,
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"baseline_result_id": report["baseline_result_id"],
"source": copy.deepcopy(report["source"]),
"provider": copy.deepcopy(report["provider"]),
"inference": copy.deepcopy(report["inference"]),
"metrics": copy.deepcopy(report["metrics"]),
"shadow_gate": copy.deepcopy(report["shadow_gate"]),
"visual_review": copy.deepcopy(report["visual_review"]),
"acceptance": copy.deepcopy(report["acceptance"]),
"decision": copy.deepcopy(report["decision"]),
"method": copy.deepcopy(report["method"]),
"limitations": copy.deepcopy(report["limitations"]),
"video": {
"url": f"/api/v1/laboratory/e46i/results/{result_id}/overlay.mp4",
"media_type": "video/mp4",
"byte_length": video["byte_length"],
"sha256": video["sha256"],
"width": 960,
"height": 544,
"frame_rate": 10.0,
"frame_count": 4488,
"duration_seconds": 448.8,
},
"visuals": visuals,
"ground_truth": False,
"authority": copy.deepcopy(report["authority"]),
"access": "read-only-full-route-diagnostic",
}
def _artifact_descriptor(frozen: dict[str, Any], role: str) -> dict[str, Any]:
descriptor = next(
(
row
for row in frozen["manifest"]["artifacts"]
if isinstance(row, dict) and row.get("role") == role
),
None,
)
if not isinstance(descriptor, dict):
raise HTTPException(status_code=404, detail="E46I artifact не найден")
return descriptor
def _file_response(path: Path, descriptor: dict[str, Any], media_type: str) -> FileResponse:
return FileResponse(
path,
media_type=media_type,
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"ETag": f'"{descriptor["sha256"]}"',
"X-Content-Type-Options": "nosniff",
},
)
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,196 @@
"""Read-only LAB projection and visual evidence delivery for E46J."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.e46j_raw_fisheye_realtime import (
E46JRawFisheyeRealtimeError,
read_e46j_raw_fisheye_realtime,
)
_RESULT_ID = re.compile(r"^e46j-raw-fisheye-realtime-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
def build_e46j_raw_fisheye_realtime_router(
*, root_provider: RootProvider = lambda: None
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/e46j", tags=["laboratory"])
def result(result_id: str) -> dict[str, Any]:
if _RESULT_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="E46J result не найден")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="E46J result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="E46J result не найден")
try:
return read_e46j_raw_fisheye_realtime(path)
except (E46JRawFisheyeRealtimeError, OSError, ValueError):
raise HTTPException(status_code=404, detail="E46J result не найден") from None
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _candidates(root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
frozen = result(path.name)
if len(items) < limit:
items.append(_project_result(frozen))
except HTTPException:
invalid_total += 1
return {
"schema_version": "missioncore.e46j-raw-fisheye-realtime-catalog/v1",
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only-full-route-diagnostic",
}
@router.get("/results/{result_id}/overlay.mp4")
def get_overlay_video(result_id: str) -> FileResponse:
frozen = result(result_id)
descriptor = _artifact_descriptor(frozen, "visual-overlay-video")
return _file_response(frozen["overlay_path"], descriptor, "video/mp4")
@router.get("/results/{result_id}/visual/{role}.png")
def get_visual(result_id: str, role: str) -> FileResponse:
roles = {
"full-route": ("full-route-contact-sheet", "route_sheet_path"),
"targeted-windows": (
"targeted-windows-contact-sheet",
"targeted_sheet_path",
),
"operator-shadow": (
"operator-shadow-contact-sheet",
"shadow_sheet_path",
),
}
selected = roles.get(role)
if selected is None:
raise HTTPException(status_code=404, detail="E46J visual не найден")
frozen = result(result_id)
descriptor = _artifact_descriptor(frozen, selected[0])
return _file_response(frozen[selected[1]], descriptor, "image/png")
return router
def _project_result(frozen: dict[str, Any]) -> dict[str, object]:
report = frozen["report"]
result_id = frozen["result_id"]
video = _artifact_descriptor(frozen, "visual-overlay-video")
visual_roles = {
"full_route": "full-route-contact-sheet",
"targeted_windows": "targeted-windows-contact-sheet",
"operator_shadow": "operator-shadow-contact-sheet",
}
visuals = {}
for key, role in visual_roles.items():
descriptor = _artifact_descriptor(frozen, role)
slug = role.removesuffix("-contact-sheet")
visuals[key] = {
"url": f"/api/v1/laboratory/e46j/results/{result_id}/visual/{slug}.png",
"media_type": "image/png",
"byte_length": descriptor["byte_length"],
"sha256": descriptor["sha256"],
}
return {
"schema_version": "missioncore.e46j-raw-fisheye-realtime-view/v1",
"result_id": result_id,
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"source": copy.deepcopy(report["source"]),
"detector": copy.deepcopy(report["detector"]),
"preprocessing": copy.deepcopy(report["preprocessing"]),
"detection": copy.deepcopy(report["detection"]),
"metrics": copy.deepcopy(report["metrics"]),
"visual_review": copy.deepcopy(report["visual_review"]),
"acceptance": copy.deepcopy(report["acceptance"]),
"decision": copy.deepcopy(report["decision"]),
"method": copy.deepcopy(report["method"]),
"limitations": copy.deepcopy(report["limitations"]),
"video": {
"url": f"/api/v1/laboratory/e46j/results/{result_id}/overlay.mp4",
"media_type": "video/mp4",
"byte_length": video["byte_length"],
"sha256": video["sha256"],
"width": 800,
"height": 600,
"frame_rate": 10.003944527024467,
"frame_count": 4489,
"duration_seconds": 448.723,
},
"visuals": visuals,
"ground_truth": False,
"authority": copy.deepcopy(report["authority"]),
"access": "read-only-full-route-diagnostic",
}
def _artifact_descriptor(frozen: dict[str, Any], role: str) -> dict[str, Any]:
descriptor = next(
(
row
for row in frozen["manifest"]["artifacts"]
if isinstance(row, dict) and row.get("role") == role
),
None,
)
if not isinstance(descriptor, dict):
raise HTTPException(status_code=404, detail="E46J artifact не найден")
return descriptor
def _file_response(path: Path, descriptor: dict[str, Any], media_type: str) -> FileResponse:
return FileResponse(
path,
media_type=media_type,
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"ETag": f'"{descriptor["sha256"]}"',
"X-Content-Type-Options": "nosniff",
},
)
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
item
for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and _RESULT_ID.fullmatch(item.name)
),
key=lambda item: item.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,323 @@
"""Read-only API for sealed L3.2 camera-bound PointPillars evidence."""
from __future__ import annotations
import copy
import hashlib
import json
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any, Final
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
RootProvider = Callable[[], Path | None]
RESULT_SCHEMA: Final = "missioncore.l32-pointpillars-camera-review/v1"
CATALOG_SCHEMA: Final = "missioncore.l32-pointpillars-camera-review-catalog/v1"
FRAME_SCHEMA: Final = "missioncore.l32-pointpillars-camera-review-frame/v1"
RESULT_PROJECTION_SCHEMA: Final = (
"missioncore.l32-pointpillars-camera-review-result/v1"
)
RESULT_CATALOG_SCHEMA: Final = (
"missioncore.l32-pointpillars-camera-review-catalog-results/v1"
)
RESULT_ID: Final = re.compile(
r"^l32-pointpillars-camera-review-[a-f0-9]{64}$"
)
FRAME_ID: Final = re.compile(r"^[0-9]{6}$")
SHA256: Final = re.compile(r"^[a-f0-9]{64}$")
MAX_JSON_BYTES: Final = 16 * 1024 * 1024
MAX_FRAMES: Final = 18
def build_l32_pointpillars_camera_review_router(
*,
root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(
prefix="/api/v1/laboratory/l32/pointpillars-camera-review",
tags=["laboratory"],
)
@router.get("/results")
def list_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
root = _configured_root(root_provider)
if root is None:
return _empty_catalog(False)
candidates = _candidates(root)
items: list[dict[str, object]] = []
invalid_total = 0
for candidate in candidates:
try:
items.append(_project_result(candidate))
except RuntimeError:
invalid_total += 1
items.sort(
key=lambda item: (str(item["created_at_utc"]), str(item["result_id"])),
reverse=True,
)
return {
"schema_version": RESULT_CATALOG_SCHEMA,
"configured": True,
"items": items[:limit],
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/{result_id}/frames/{frame_id}")
def get_frame(result_id: str, frame_id: str) -> dict[str, object]:
candidate, descriptor = _resolve_frame(
root_provider, result_id=result_id, frame_id=frame_id
)
path = candidate / str(descriptor["detail_path"])
payload = _read_json(path)
if (
payload.get("schema_version") != FRAME_SCHEMA
or payload.get("frame_id") != frame_id
or descriptor.get("detail_sha256") != _sha256(path)
or descriptor.get("detail_byte_length") != path.stat().st_size
or not _valid_frame_payload(payload)
):
raise HTTPException(status_code=404, detail="L3.2 frame not found")
return {**copy.deepcopy(payload), "access": "read-only"}
@router.get("/{result_id}/frames/{frame_id}/camera")
def get_camera(result_id: str, frame_id: str) -> FileResponse:
candidate, descriptor = _resolve_frame(
root_provider, result_id=result_id, frame_id=frame_id
)
path = (candidate / str(descriptor["camera_path"])).resolve()
if (
not path.is_relative_to(candidate)
or path.is_symlink()
or not path.is_file()
or descriptor.get("camera_sha256") != _sha256(path)
):
raise HTTPException(status_code=404, detail="L3.2 camera not found")
return FileResponse(path, media_type="image/jpeg")
return router
def latest_l32_identity(root_provider: RootProvider) -> dict[str, str] | None:
root = _configured_root(root_provider)
if root is None:
return None
valid: list[dict[str, object]] = []
for candidate in _candidates(root):
try:
valid.append(_project_result(candidate))
except RuntimeError:
continue
if not valid:
return None
latest = max(
valid,
key=lambda item: (str(item["created_at_utc"]), str(item["result_id"])),
)
return {
"result_id": str(latest["result_id"]),
"created_at_utc": str(latest["created_at_utc"]),
}
def _resolve_frame(
root_provider: RootProvider,
*,
result_id: str,
frame_id: str,
) -> tuple[Path, dict[str, Any]]:
if not RESULT_ID.fullmatch(result_id) or not FRAME_ID.fullmatch(frame_id):
raise HTTPException(status_code=404, detail="L3.2 frame not found")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.2 result not found")
candidate = root / result_id
try:
result = _load_result(candidate)
descriptor = next(
item for item in result["catalog"]["frames"]
if item["frame_id"] == frame_id
)
except (RuntimeError, StopIteration):
raise HTTPException(status_code=404, detail="L3.2 frame not found") from None
return candidate, descriptor
def _project_result(candidate: Path) -> dict[str, object]:
result = _load_result(candidate)
manifest = result["manifest"]
identity = manifest["identity"]
return {
"schema_version": RESULT_PROJECTION_SCHEMA,
"result_id": manifest["result_id"],
"created_at_utc": manifest["created_at_utc"],
"status": "camera-bound-review-rejects-current-candidate",
"source_session_id": identity["source_session_id"],
"source_l31_result_id": identity["source_l31_result_id"],
"source_e10_pack_id": identity["source_e10_pack_id"],
"projection": copy.deepcopy(identity["projection"]),
"metrics": copy.deepcopy(manifest["metrics"]),
"frames": copy.deepcopy(result["catalog"]["frames"]),
"limitations": copy.deepcopy(manifest["limitations"]),
"authority": copy.deepcopy(manifest["authority"]),
"access": "read-only",
}
def _load_result(candidate: Path) -> dict[str, Any]:
if (
not candidate.is_dir()
or candidate.is_symlink()
or not RESULT_ID.fullmatch(candidate.name)
):
raise RuntimeError("L3.2 candidate is invalid")
manifest = _read_json(candidate / "manifest.json")
identity = manifest.get("identity")
authority = manifest.get("authority")
catalog_descriptor = manifest.get("catalog")
if (
manifest.get("schema_version") != RESULT_SCHEMA
or manifest.get("result_id") != candidate.name
or manifest.get("status") != "camera-bound-review-rejects-current-candidate"
or not isinstance(manifest.get("created_at_utc"), str)
or not isinstance(identity, dict)
or identity.get("schema_version") != RESULT_SCHEMA
or identity.get("source_session_id") != "20260720T065719Z_viewer_live"
or manifest.get("identity_sha256")
!= hashlib.sha256(_canonical_json(identity)).hexdigest()
or candidate.name
!= f"l32-pointpillars-camera-review-{manifest.get('identity_sha256')}"
or not isinstance(authority, dict)
or authority.get("shadow_only") is not True
or authority.get("accuracy_accepted") is not False
or authority.get("commands_enabled") is not False
or not isinstance(manifest.get("metrics"), dict)
or not isinstance(manifest.get("limitations"), list)
or not isinstance(catalog_descriptor, dict)
or catalog_descriptor.get("path") != "catalog.json"
):
raise RuntimeError("L3.2 manifest is invalid")
catalog_path = candidate / "catalog.json"
if (
catalog_descriptor.get("sha256") != _sha256(catalog_path)
or catalog_descriptor.get("byte_length") != catalog_path.stat().st_size
):
raise RuntimeError("L3.2 catalog changed")
catalog = _read_json(catalog_path)
frames = catalog.get("frames")
if (
catalog.get("schema_version") != CATALOG_SCHEMA
or catalog.get("result_id") != candidate.name
or not isinstance(frames, list)
or not 1 <= len(frames) <= MAX_FRAMES
or catalog.get("frame_count") != len(frames)
or len({item.get("frame_id") for item in frames if isinstance(item, dict)})
!= len(frames)
or any(not _valid_descriptor(item) for item in frames)
):
raise RuntimeError("L3.2 catalog is invalid")
return {"manifest": manifest, "catalog": catalog}
def _valid_descriptor(value: object) -> bool:
if not isinstance(value, dict):
return False
frame_id = value.get("frame_id")
return (
isinstance(frame_id, str)
and FRAME_ID.fullmatch(frame_id) is not None
and value.get("detail_path") == f"frame-{frame_id}.json"
and isinstance(value.get("detail_sha256"), str)
and SHA256.fullmatch(value["detail_sha256"]) is not None
and isinstance(value.get("detail_byte_length"), int)
and 0 < value["detail_byte_length"] <= MAX_JSON_BYTES
and isinstance(value.get("camera_path"), str)
and value["camera_path"].startswith("frames/frame-")
and isinstance(value.get("camera_sha256"), str)
and SHA256.fullmatch(value["camera_sha256"]) is not None
and isinstance(value.get("camera_delta_ms"), (int, float))
and abs(float(value["camera_delta_ms"])) <= 100.0
)
def _valid_frame_payload(value: dict[str, Any]) -> bool:
projection = value.get("camera_projection")
camera = value.get("camera")
interpretation = value.get("interpretation")
return (
isinstance(value.get("summary"), dict)
and isinstance(value.get("points"), dict)
and isinstance(value.get("prediction_boxes"), list)
and isinstance(projection, dict)
and projection.get("point_layout") == "flat-xy-depth-m"
and isinstance(projection.get("point_count"), int)
and isinstance(projection.get("point_values"), list)
and len(projection["point_values"]) == projection["point_count"] * 3
and isinstance(projection.get("boxes"), list)
and isinstance(camera, dict)
and camera.get("media_type") == "image/jpeg"
and camera.get("exact_source_frame") is True
and isinstance(interpretation, dict)
and interpretation.get("camera_is_semantic_reference") is True
and interpretation.get("boxes_are_model_hypotheses") is True
and interpretation.get("accuracy_claim_allowed") is False
)
def _configured_root(provider: RootProvider) -> Path | None:
configured = provider()
if configured is None:
return None
root = configured.expanduser().resolve()
return root if root.is_dir() and not root.is_symlink() else None
def _candidates(root: Path) -> list[Path]:
return [
item for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and RESULT_ID.fullmatch(item.name)
]
def _empty_catalog(configured: bool) -> dict[str, object]:
return {
"schema_version": RESULT_CATALOG_SCHEMA,
"configured": configured,
"items": [],
"candidate_total": 0,
"invalid_total": 0,
"access": "read-only",
}
def _read_json(path: Path) -> dict[str, Any]:
if path.is_symlink() or not path.is_file() or path.stat().st_size > MAX_JSON_BYTES:
raise RuntimeError("L3.2 JSON artifact is invalid")
try:
value = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise RuntimeError("L3.2 JSON artifact is invalid") from exc
if not isinstance(value, dict):
raise RuntimeError("L3.2 JSON artifact is invalid")
return value
def _canonical_json(value: object) -> bytes:
return json.dumps(
value, ensure_ascii=False, sort_keys=True, separators=(",", ":")
).encode("utf-8")
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
while chunk := stream.read(1024 * 1024):
digest.update(chunk)
return digest.hexdigest()
@@ -0,0 +1,394 @@
"""Read-only API for sealed L3.3 camera-first detector evidence."""
from __future__ import annotations
import copy
import hashlib
import json
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any, Final
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.l33_camera_first_admission import is_admitted_l33_identity
RootProvider = Callable[[], Path | None]
RESULT_SCHEMA: Final = "missioncore.l33-camera-first-detector-review/v1"
CATALOG_SCHEMA: Final = "missioncore.l33-camera-first-detector-review-catalog/v1"
FRAME_SCHEMA: Final = "missioncore.l33-camera-first-detector-review-frame/v1"
RESULT_PROJECTION_SCHEMA: Final = "missioncore.l33-camera-first-detector-review-result/v1"
RESULT_CATALOG_SCHEMA: Final = "missioncore.l33-camera-first-detector-review-catalog-results/v1"
RESULT_ID: Final = re.compile(r"^l33-camera-first-detector-review-[a-f0-9]{64}$")
FRAME_ID: Final = re.compile(r"^[0-9]{6}$")
SHA256: Final = re.compile(r"^[a-f0-9]{64}$")
MAX_JSON_BYTES: Final = 16 * 1024 * 1024
MAX_FRAMES: Final = 18
def build_l33_camera_first_detector_review_router(
*,
root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(
prefix="/api/v1/laboratory/l33/camera-first-detector-review",
tags=["laboratory"],
)
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
root = _configured_root(root_provider)
if root is None:
return _empty_catalog(False)
candidates = _candidates(root)
items: list[dict[str, object]] = []
invalid_total = 0
for candidate in candidates:
try:
items.append(_project_result(candidate))
except RuntimeError:
invalid_total += 1
items.sort(
key=lambda item: (str(item["created_at_utc"]), str(item["result_id"])),
reverse=True,
)
return {
"schema_version": RESULT_CATALOG_SCHEMA,
"configured": True,
"items": items[:limit],
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/{result_id}/frames/{frame_id}")
def get_frame(result_id: str, frame_id: str) -> dict[str, object]:
candidate, descriptor = _resolve_frame(
root_provider, result_id=result_id, frame_id=frame_id
)
path = candidate / str(descriptor["detail_path"])
payload = _read_json(path)
if (
payload.get("schema_version") != FRAME_SCHEMA
or payload.get("frame_id") != frame_id
or descriptor.get("detail_sha256") != _sha256(path)
or descriptor.get("detail_byte_length") != path.stat().st_size
or not _valid_frame_payload(payload)
):
raise HTTPException(status_code=404, detail="L3.3 frame not found")
return {**copy.deepcopy(payload), "access": "read-only"}
@router.get("/{result_id}/frames/{frame_id}/camera")
def get_camera(result_id: str, frame_id: str) -> FileResponse:
candidate, descriptor = _resolve_frame(
root_provider, result_id=result_id, frame_id=frame_id
)
path = (candidate / str(descriptor["camera_path"])).resolve()
if (
not path.is_relative_to(candidate)
or path.is_symlink()
or not path.is_file()
or descriptor.get("camera_sha256") != _sha256(path)
):
raise HTTPException(status_code=404, detail="L3.3 camera not found")
return FileResponse(path, media_type="image/jpeg")
return router
def latest_l33_identity(root_provider: RootProvider) -> dict[str, str] | None:
root = _configured_root(root_provider)
if root is None:
return None
valid: list[dict[str, object]] = []
for candidate in _candidates(root):
try:
valid.append(_project_result(candidate))
except RuntimeError:
continue
if not valid:
return None
latest = max(
valid,
key=lambda item: (str(item["created_at_utc"]), str(item["result_id"])),
)
return {
"result_id": str(latest["result_id"]),
"created_at_utc": str(latest["created_at_utc"]),
}
def _resolve_frame(
root_provider: RootProvider,
*,
result_id: str,
frame_id: str,
) -> tuple[Path, dict[str, Any]]:
if not RESULT_ID.fullmatch(result_id) or not FRAME_ID.fullmatch(frame_id):
raise HTTPException(status_code=404, detail="L3.3 frame not found")
root = _configured_root(root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.3 result not found")
candidate = root / result_id
try:
result = _load_result(candidate)
descriptor = next(
item for item in result["catalog"]["frames"] if item["frame_id"] == frame_id
)
except (RuntimeError, StopIteration):
raise HTTPException(status_code=404, detail="L3.3 frame not found") from None
return candidate, descriptor
def _project_result(candidate: Path) -> dict[str, object]:
result = _load_result(candidate)
manifest = result["manifest"]
identity = manifest["identity"]
return {
"schema_version": RESULT_PROJECTION_SCHEMA,
"result_id": manifest["result_id"],
"created_at_utc": manifest["created_at_utc"],
"status": manifest["status"],
"source_session_id": identity["source_session_id"],
"source_l32_result_id": identity["source_l32_result_id"],
"source_e26_result_id": identity["source_e26_result_id"],
"source_e29_result_id": identity["source_e29_result_id"],
"source_e10_pack_id": identity["source_e10_pack_id"],
"source_world_state_result_id": identity.get("source_world_state_result_id"),
"detector": copy.deepcopy(identity["detector"]),
"semantic_contract": copy.deepcopy(identity["semantic_contract"]),
"geometry_contract": copy.deepcopy(identity["geometry_contract"]),
"metrics": copy.deepcopy(manifest["metrics"]),
"frames": copy.deepcopy(result["catalog"]["frames"]),
"limitations": copy.deepcopy(manifest["limitations"]),
"authority": copy.deepcopy(manifest["authority"]),
"access": "read-only",
}
def _load_result(candidate: Path) -> dict[str, Any]:
if (
not candidate.is_dir()
or candidate.is_symlink()
or not RESULT_ID.fullmatch(candidate.name)
):
raise RuntimeError("L3.3 candidate is invalid")
manifest = _read_json(candidate / "manifest.json")
identity = manifest.get("identity")
authority = manifest.get("authority")
catalog_descriptor = manifest.get("catalog")
if (
manifest.get("schema_version") != RESULT_SCHEMA
or manifest.get("result_id") != candidate.name
or manifest.get("status") != "camera-first-boundary-restored-shadow-only"
or not isinstance(manifest.get("created_at_utc"), str)
or manifest.get("ground_truth") is not False
or not isinstance(identity, dict)
or identity.get("schema_version") != RESULT_SCHEMA
or not is_admitted_l33_identity(identity)
or manifest.get("identity_sha256")
!= hashlib.sha256(_canonical_json(identity)).hexdigest()
or candidate.name
!= f"l33-camera-first-detector-review-{manifest.get('identity_sha256')}"
or not isinstance(authority, dict)
or authority.get("shadow_only") is not True
or authority.get("accuracy_accepted") is not False
or authority.get("commands_enabled") is not False
or authority.get("navigation_or_safety_accepted") is not False
or not isinstance(manifest.get("metrics"), dict)
or not isinstance(manifest.get("limitations"), list)
or not isinstance(catalog_descriptor, dict)
or catalog_descriptor.get("path") != "catalog.json"
):
raise RuntimeError("L3.3 manifest is invalid")
catalog_path = candidate / "catalog.json"
if (
catalog_descriptor.get("sha256") != _sha256(catalog_path)
or catalog_descriptor.get("byte_length") != catalog_path.stat().st_size
):
raise RuntimeError("L3.3 catalog changed")
catalog = _read_json(catalog_path)
frames = catalog.get("frames")
if (
catalog.get("schema_version") != CATALOG_SCHEMA
or catalog.get("result_id") != candidate.name
or not isinstance(frames, list)
or not 1 <= len(frames) <= MAX_FRAMES
or catalog.get("frame_count") != len(frames)
or len({item.get("frame_id") for item in frames if isinstance(item, dict)})
!= len(frames)
or any(not _valid_descriptor(item) for item in frames)
):
raise RuntimeError("L3.3 catalog is invalid")
return {"manifest": manifest, "catalog": catalog}
def _valid_descriptor(value: object) -> bool:
if not isinstance(value, dict):
return False
frame_id = value.get("frame_id")
return (
isinstance(frame_id, str)
and FRAME_ID.fullmatch(frame_id) is not None
and value.get("detail_path") == f"frame-{frame_id}.json"
and isinstance(value.get("detail_sha256"), str)
and SHA256.fullmatch(value["detail_sha256"]) is not None
and isinstance(value.get("detail_byte_length"), int)
and 0 < value["detail_byte_length"] <= MAX_JSON_BYTES
and isinstance(value.get("camera_path"), str)
and value["camera_path"].startswith("frames/frame-")
and isinstance(value.get("camera_sha256"), str)
and SHA256.fullmatch(value["camera_sha256"]) is not None
and value.get("semantic_provenance")
in (
"recorded-current",
"bounded-track-interpolation",
"rectified-detector-current",
"e23-temporal-hold",
)
)
def _valid_frame_payload(value: dict[str, Any]) -> bool:
projection = value.get("camera_projection")
camera = value.get("camera")
detections = value.get("detections")
prediction_boxes = value.get("prediction_boxes", [])
interpretation = value.get("interpretation")
return (
isinstance(value.get("summary"), dict)
and isinstance(value.get("points"), dict)
and isinstance(projection, dict)
and projection.get("point_layout") == "flat-xy-depth-m"
and isinstance(projection.get("point_count"), int)
and isinstance(projection.get("point_values"), list)
and len(projection["point_values"]) == projection["point_count"] * 3
and isinstance(camera, dict)
and camera.get("media_type") == "image/jpeg"
and camera.get("exact_source_frame") is True
and isinstance(detections, list)
and all(_valid_detection(item) for item in detections)
and isinstance(prediction_boxes, list)
and all(_valid_prediction_box(item) for item in prediction_boxes)
and isinstance(interpretation, dict)
and interpretation.get("camera_owns_semantic_identity") is True
and interpretation.get("lidar_owns_metric_range") is True
and interpretation.get("missing_lidar_erases_camera_detection") is False
and interpretation.get("ground_truth_available") is False
and interpretation.get("accuracy_claim_allowed") is False
)
def _valid_detection(value: object) -> bool:
if not isinstance(value, dict):
return False
bbox = value.get("bbox_xyxy")
camera_ray = value.get("camera_ray_lidar")
geometry_anchor = value.get("geometry_anchor_xyz_m")
return (
isinstance(value.get("source_track_id"), int)
and isinstance(value.get("label"), str)
and isinstance(value.get("score"), (int, float))
and 0.25 <= float(value["score"]) <= 1.0
and isinstance(bbox, list)
and len(bbox) == 4
and all(isinstance(item, (int, float)) for item in bbox)
and value.get("semantic_provenance")
in (
"recorded-current",
"bounded-track-interpolation",
"rectified-detector-current",
"e23-temporal-hold",
)
and isinstance(value.get("geometry_status"), str)
and (value.get("range_m") is None or isinstance(value.get("range_m"), (int, float)))
and (
value.get("source_e29_optical_depth_m") is None
or isinstance(value.get("source_e29_optical_depth_m"), (int, float))
)
and isinstance(camera_ray, dict)
and _valid_vector(camera_ray.get("origin_xyz_m"), 3)
and _valid_vector(camera_ray.get("direction_xyz"), 3)
and (geometry_anchor is None or _valid_vector(geometry_anchor, 3))
and ((value.get("range_m") is None) == (geometry_anchor is None))
)
def _valid_prediction_box(value: object) -> bool:
if not isinstance(value, dict):
return False
return (
isinstance(value.get("benchmark_class"), str)
and _valid_vector(value.get("center_xyz_m"), 3)
and _valid_vector(value.get("size_lwh_m"), 3)
and all(float(item) > 0 for item in value["size_lwh_m"])
and isinstance(value.get("yaw_rad"), (int, float))
and value.get("status") == "model-prediction"
and isinstance(value.get("score"), (int, float))
and 0 <= float(value["score"]) <= 1
and isinstance(value.get("track_id"), int)
and isinstance(value.get("temporal_status"), str)
)
def _valid_vector(value: object, length: int) -> bool:
return (
isinstance(value, list)
and len(value) == length
and all(isinstance(item, (int, float)) for item in value)
)
def _configured_root(provider: RootProvider) -> Path | None:
configured = provider()
if configured is None:
return None
root = configured.expanduser().resolve()
return root if root.is_dir() and not root.is_symlink() else None
def _candidates(root: Path) -> list[Path]:
return [
item for item in root.iterdir()
if item.is_dir() and not item.is_symlink() and RESULT_ID.fullmatch(item.name)
]
def _empty_catalog(configured: bool) -> dict[str, object]:
return {
"schema_version": RESULT_CATALOG_SCHEMA,
"configured": configured,
"items": [],
"candidate_total": 0,
"invalid_total": 0,
"access": "read-only",
}
def _read_json(path: Path) -> dict[str, Any]:
if path.is_symlink() or not path.is_file() or path.stat().st_size > MAX_JSON_BYTES:
raise RuntimeError("L3.3 JSON artifact is invalid")
try:
value = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise RuntimeError("L3.3 JSON artifact is invalid") from exc
if not isinstance(value, dict):
raise RuntimeError("L3.3 JSON artifact is invalid")
return value
def _canonical_json(value: object) -> bytes:
return json.dumps(
value, ensure_ascii=False, sort_keys=True, separators=(",", ":")
).encode("utf-8")
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,450 @@
from __future__ import annotations
import copy
import hashlib
import json
import math
import re
import struct
from collections.abc import Callable
from pathlib import Path, PurePosixPath
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.e46_detector_truth_island import (
E46_MANIFEST_NAME,
E46_REFERENCES_NAME,
E46DetectorTruthIslandError,
read_e46_detector_truth_island,
)
from k1link.compute.l34_right_yolox_truth_island_freeze import (
L34_MANIFEST_NAME,
L34_PREDICTION_SCHEMA,
L34RightYoloxTruthIsland,
L34RightYoloxTruthIslandError,
read_l34_right_yolox_truth_island_freeze,
)
RootProvider = Callable[[], Path | None]
_RESULT_ID = re.compile(r"^l34-right-yolox-truth-island-freeze-[a-f0-9]{64}$")
_TRUTH_ID = re.compile(r"^e46-detector-truth-island-[a-f0-9]{64}$")
_PACK_ID = re.compile(r"^evaluation-pack-[a-f0-9]{64}$")
_PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n"
_MAX_VISUAL_FRAMES = 32
def latest_l34_identity(provider: RootProvider) -> dict[str, object] | None:
for candidate in _candidates(provider):
try:
result = read_l34_right_yolox_truth_island_freeze(candidate)
except L34RightYoloxTruthIslandError:
continue
created_at_utc = result.manifest.get("created_at_utc")
if not isinstance(created_at_utc, str) or not created_at_utc.strip():
continue
return {
"result_id": result.result_id,
"created_at_utc": created_at_utc,
"access": "read-only",
}
return None
def build_l34_right_yolox_truth_island_freeze_router(
*,
root_provider: RootProvider = lambda: None,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@router.get("/l34/results")
def list_l34_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
items: list[dict[str, object]] = []
invalid_total = 0
for candidate in _candidates(root_provider):
try:
result = read_l34_right_yolox_truth_island_freeze(candidate)
items.append(_project(result))
except L34RightYoloxTruthIslandError:
invalid_total += 1
continue
if len(items) >= limit:
break
return {
"schema_version": (
"missioncore.l34-right-yolox-truth-island-catalog/v1"
),
"configured": _configured_root(root_provider) is not None,
"items": items,
"candidate_total": len(items),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/l34/results/{result_id}/frames/{sequence}")
def get_l34_frame(result_id: str, sequence: int) -> dict[str, object]:
result, prediction, reference, image_path = _resolve_visual_frame(
root_provider=root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
width, height = _png_dimensions(image_path)
predictions = _validated_predictions(prediction, width=width, height=height)
identity = result.manifest["identity"]
candidate = identity["candidate"]
return {
"schema_version": "missioncore.l34-right-yolox-truth-island-frame/v1",
"result_id": result.result_id,
"truth_island_sequence": sequence,
"image_id": prediction["image_id"],
"frame_index": prediction["frame_index"],
"group_id": prediction["group_id"],
"role": reference["role"],
"session_seconds": reference["session_seconds"],
"camera": {
"width": width,
"height": height,
"byte_length": image_path.stat().st_size,
"sha256": reference["sha256"],
},
"prediction_rows_sha256": candidate["prediction_rows_sha256"],
"predictions": predictions,
"truth_labels_read": False,
"access": "read-only",
}
@router.get("/l34/results/{result_id}/frames/{sequence}/camera")
def get_l34_camera(result_id: str, sequence: int) -> FileResponse:
_, _, _, image_path = _resolve_visual_frame(
root_provider=root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return FileResponse(image_path, media_type="image/png")
return router
def _project(result: L34RightYoloxTruthIsland) -> dict[str, object]:
identity = result.manifest["identity"]
report = result.report
return {
"result_id": result.result_id,
"created_at_utc": result.manifest["created_at_utc"],
"status": report["status"],
"profile_id": report["profile_id"],
"pipeline_id": report["pipeline_id"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"candidate": {
**copy.deepcopy(identity["profile"]["candidate"]),
"l33_result_id": identity["candidate"]["l33_result_id"],
},
"truth_island": {
"result_id": identity["truth_island"]["result_id"],
"truth_state": identity["truth_island"]["truth_state"],
},
"metrics": copy.deepcopy(report["metrics"]),
"frames": [_frame_summary(row) for row in result.predictions],
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"authority": copy.deepcopy(report["authority"]),
"access": "read-only",
}
def _frame_summary(row: dict[str, Any]) -> dict[str, object]:
sequence = _nonnegative_integer(row.get("truth_island_sequence"), "sequence")
image_id = _nonnegative_integer(row.get("image_id"), "image id")
frame_index = _nonnegative_integer(row.get("frame_index"), "frame index")
group_id = row.get("group_id")
predictions = row.get("predictions")
if (
row.get("schema_version") != L34_PREDICTION_SCHEMA
or not 1 <= sequence <= _MAX_VISUAL_FRAMES
or not isinstance(group_id, str)
or not group_id.strip()
or not isinstance(predictions, list)
):
raise L34RightYoloxTruthIslandError("L34 visual frame is invalid")
scores = [
float(prediction["score"])
for prediction in predictions
if isinstance(prediction, dict)
and isinstance(prediction.get("score"), (int, float))
and not isinstance(prediction.get("score"), bool)
]
if len(scores) != len(predictions) or any(not math.isfinite(score) for score in scores):
raise L34RightYoloxTruthIslandError("L34 visual scores are invalid")
return {
"truth_island_sequence": sequence,
"image_id": image_id,
"frame_index": frame_index,
"group_id": group_id,
"prediction_count": len(predictions),
"maximum_score": max(scores, default=0.0),
}
def _resolve_visual_frame(
*,
root_provider: RootProvider,
truth_root_provider: RootProvider,
evaluation_pack_root_provider: RootProvider,
result_id: str,
sequence: int,
) -> tuple[L34RightYoloxTruthIsland, dict[str, Any], dict[str, Any], Path]:
if _RESULT_ID.fullmatch(result_id) is None or not 1 <= sequence <= _MAX_VISUAL_FRAMES:
raise HTTPException(status_code=404, detail="L34 frame not found")
result_root = _configured_root(root_provider)
if result_root is None:
raise HTTPException(status_code=404, detail="L34 result not found")
result_path = (result_root / result_id).resolve()
if result_path.parent != result_root or result_path.is_symlink():
raise HTTPException(status_code=404, detail="L34 result not found")
try:
result = read_l34_right_yolox_truth_island_freeze(result_path)
except (L34RightYoloxTruthIslandError, OSError):
raise HTTPException(status_code=404, detail="L34 result not found") from None
prediction = next(
(
row
for row in result.predictions
if row.get("truth_island_sequence") == sequence
),
None,
)
if prediction is None:
raise HTTPException(status_code=404, detail="L34 frame not found")
identity = result.manifest["identity"]
truth_identity = identity["truth_island"]
truth_id = truth_identity.get("result_id")
truth_root = _configured_root(truth_root_provider)
if (
truth_root is None
or not isinstance(truth_id, str)
or _TRUTH_ID.fullmatch(truth_id) is None
):
raise HTTPException(status_code=404, detail="L34 truth island not found")
truth_path = (truth_root / truth_id).resolve()
if truth_path.parent != truth_root or truth_path.is_symlink():
raise HTTPException(status_code=404, detail="L34 truth island not found")
try:
truth = read_e46_detector_truth_island(truth_path)
except (E46DetectorTruthIslandError, OSError):
raise HTTPException(status_code=404, detail="L34 truth island not found") from None
if _sha256(truth.result_root / E46_MANIFEST_NAME) != truth_identity.get(
"manifest_sha256"
):
raise HTTPException(status_code=404, detail="L34 truth island changed")
references = _read_jsonl(truth.result_root / E46_REFERENCES_NAME)
reference = next(
(row for row in references if row.get("truth_island_sequence") == sequence),
None,
)
if (
reference is None
or prediction.get("candidate_id") != "yolox-s-kb4-core3"
or prediction.get("truth_joined") is not False
or reference.get("frame_index") != prediction.get("frame_index")
or reference.get("image_id") != prediction.get("image_id")
or reference.get("group_id") != prediction.get("group_id")
or reference.get("session_seconds")
!= prediction.get("session_seconds")
or reference.get("sha256")
!= prediction.get("source_image_sha256")
or reference.get("role") not in {"anchor", "temporal"}
or not isinstance(reference.get("session_seconds"), (int, float))
):
raise HTTPException(status_code=404, detail="L34 frame binding is invalid")
truth_source = truth.manifest["identity"]["source"]
pack_id = truth_source.get("evaluation_pack_id")
pack_root = _configured_root(evaluation_pack_root_provider)
if (
pack_root is None
or not isinstance(pack_id, str)
or _PACK_ID.fullmatch(pack_id) is None
):
raise HTTPException(status_code=404, detail="L34 image source not found")
pack_path = (pack_root / pack_id).resolve()
if pack_path.parent != pack_root or pack_path.is_symlink() or not pack_path.is_dir():
raise HTTPException(status_code=404, detail="L34 image source not found")
relative = reference.get("source_path")
if not isinstance(relative, str):
raise HTTPException(status_code=404, detail="L34 image source not found")
pure = PurePosixPath(relative)
if (
pure.is_absolute()
or ".." in pure.parts
or pure.parts[:2] != ("images", "valid-fov-fill")
or pure.suffix.lower() != ".png"
):
raise HTTPException(status_code=404, detail="L34 image source not found")
image_path = (pack_path / Path(*pure.parts)).resolve()
if (
not image_path.is_relative_to(pack_path)
or image_path.is_symlink()
or not image_path.is_file()
or image_path.stat().st_size != reference.get("byte_length")
or _sha256(image_path) != reference.get("sha256")
):
raise HTTPException(status_code=404, detail="L34 image source changed")
return result, prediction, reference, image_path
def resolve_l34_frame_source(
*,
root_provider: RootProvider,
truth_root_provider: RootProvider,
evaluation_pack_root_provider: RootProvider,
result_id: str,
sequence: int,
) -> tuple[L34RightYoloxTruthIsland, dict[str, Any], dict[str, Any], Path]:
"""Resolve one immutable L3.4 source frame for bounded sibling APIs.
The caller receives the server-side binding. Prediction-free source routes
project only the source reference; explicitly assisted routes may project a
bounded, provenance-marked subset of ``prediction``.
"""
return _resolve_visual_frame(
root_provider=root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
def _validated_predictions(
row: dict[str, Any],
*,
width: int,
height: int,
) -> list[dict[str, object]]:
predictions = row.get("predictions")
if not isinstance(predictions, list):
raise HTTPException(status_code=404, detail="L34 predictions not found")
projected: list[dict[str, object]] = []
for prediction in predictions:
if not isinstance(prediction, dict):
raise HTTPException(status_code=404, detail="L34 prediction is invalid")
label = prediction.get("label")
score = prediction.get("score")
bbox = prediction.get("bbox_xyxy")
if (
label not in {
"person",
"bicycle",
"motorcycle",
"car",
"heavy_vehicle",
"static_obstacle",
"animal",
}
or not isinstance(score, (int, float))
or isinstance(score, bool)
or not math.isfinite(float(score))
or not 0.25 <= float(score) <= 1.0
or not isinstance(bbox, list)
or len(bbox) != 4
or any(
not isinstance(value, (int, float))
or isinstance(value, bool)
or not math.isfinite(float(value))
for value in bbox
)
):
raise HTTPException(status_code=404, detail="L34 prediction is invalid")
left, top, right, bottom = (float(value) for value in bbox)
if not (0 <= left < right <= width and 0 <= top < bottom <= height):
raise HTTPException(status_code=404, detail="L34 prediction box is invalid")
projected.append(
{
"label": label,
"score": float(score),
"bbox_xyxy": [left, top, right, bottom],
}
)
return projected
def _png_dimensions(path: Path) -> tuple[int, int]:
try:
with path.open("rb") as stream:
header = stream.read(24)
except OSError:
raise HTTPException(status_code=404, detail="L34 camera not found") from None
if len(header) != 24 or header[:8] != _PNG_SIGNATURE or header[12:16] != b"IHDR":
raise HTTPException(status_code=404, detail="L34 camera is invalid")
width, height = struct.unpack(">II", header[16:24])
if not 1 <= width <= 8192 or not 1 <= height <= 8192:
raise HTTPException(status_code=404, detail="L34 camera is invalid")
return width, height
def _read_jsonl(path: Path) -> list[dict[str, Any]]:
try:
rows = [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines() if line]
except (json.JSONDecodeError, OSError):
raise HTTPException(status_code=404, detail="L34 frame index not found") from None
if not rows or len(rows) > _MAX_VISUAL_FRAMES or any(not isinstance(row, dict) for row in rows):
raise HTTPException(status_code=404, detail="L34 frame index is invalid")
return rows
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def _nonnegative_integer(value: object, label: str) -> int:
if not isinstance(value, int) or isinstance(value, bool) or value < 0:
raise L34RightYoloxTruthIslandError(f"L34 {label} is invalid")
return value
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
resolved = candidate.resolve(strict=True)
except OSError:
return None
return resolved if resolved.is_dir() else None
def _candidates(provider: RootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
candidate
for candidate in root.iterdir()
if candidate.is_dir()
and not candidate.is_symlink()
and _RESULT_ID.fullmatch(candidate.name) is not None
and (candidate / L34_MANIFEST_NAME).is_file()
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,207 @@
"""Read-only API for the L3.4A assisted YOLOX error audit."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.l34a_assisted_yolox_error_audit import (
L34A_MANIFEST_NAME,
L34AAssistedYoloxErrorAuditError,
read_l34a_assisted_yolox_error_audit,
)
from k1link.web.l34_right_yolox_truth_island_api import (
RootProvider,
resolve_l34_frame_source,
)
_RESULT_ID = re.compile(r"^l34a-assisted-yolox-error-audit-[a-f0-9]{64}$")
AuditRootProvider = Callable[[], Path | None]
def build_l34a_assisted_yolox_error_audit_router(
*,
audit_root_provider: AuditRootProvider = lambda: None,
l34_root_provider: RootProvider = lambda: None,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@router.get("/l34a/results")
def list_l34a_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
items: list[dict[str, object]] = []
invalid_total = 0
candidates = _candidates(audit_root_provider)
for candidate in candidates:
try:
result = read_l34a_assisted_yolox_error_audit(candidate)
if len(items) < limit:
items.append(_project(result))
except (L34AAssistedYoloxErrorAuditError, OSError, ValueError):
invalid_total += 1
return {
"schema_version": "missioncore.l34a-assisted-yolox-error-catalog/v1",
"configured": _configured_root(audit_root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/l34a/results/{result_id}/cases/{sequence}")
def get_l34a_case(result_id: str, sequence: int) -> dict[str, object]:
result, case, _, _ = _resolve_case(
audit_root_provider=audit_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return {
**copy.deepcopy(case),
"result_id": result["result_id"],
"ground_truth": False,
"access": "read-only",
}
@router.get("/l34a/results/{result_id}/cases/{sequence}/camera")
def get_l34a_case_camera(result_id: str, sequence: int) -> FileResponse:
_, _, _, image_path = _resolve_case(
audit_root_provider=audit_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return FileResponse(image_path, media_type="image/png")
return router
def _project(result: dict[str, Any]) -> dict[str, object]:
report = result["report"]
identity = result["manifest"]["identity"]
annotation = identity["assisted_annotation"]
return {
"result_id": result["result_id"],
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"profile_id": report["profile"]["profile_id"],
"pipeline_id": report["method"]["pipeline_id"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"assisted_annotation": copy.deepcopy(annotation),
"metrics": copy.deepcopy(report["metrics"]),
"cases": [_case_summary(case) for case in result["cases"]],
"case_order": copy.deepcopy(report["case_order"]),
"method": copy.deepcopy(report["method"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"authority": copy.deepcopy(report["authority"]),
"ground_truth": False,
"access": "read-only",
}
def _case_summary(case: dict[str, Any]) -> dict[str, object]:
return {
"truth_island_sequence": case["truth_island_sequence"],
"image_id": case["image_id"],
"frame_index": case["frame_index"],
"group_id": case["group_id"],
"session_seconds": case["session_seconds"],
"source_image_sha256": case["source_image_sha256"],
"summary": copy.deepcopy(case["summary"]),
}
def _resolve_case(
*,
audit_root_provider: AuditRootProvider,
l34_root_provider: RootProvider,
truth_root_provider: RootProvider,
evaluation_pack_root_provider: RootProvider,
result_id: str,
sequence: int,
) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any], Path]:
if _RESULT_ID.fullmatch(result_id) is None or not 1 <= sequence <= 32:
raise HTTPException(status_code=404, detail="L3.4A case not found")
root = _configured_root(audit_root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.4A result not found")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="L3.4A result not found")
try:
result = read_l34a_assisted_yolox_error_audit(path)
except (L34AAssistedYoloxErrorAuditError, OSError):
raise HTTPException(status_code=404, detail="L3.4A result not found") from None
case = next(
(
item
for item in result["cases"]
if item.get("truth_island_sequence") == sequence
),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="L3.4A case not found")
l34_result_id = result["manifest"]["identity"]["l34_freeze"]["result_id"]
_, prediction, reference, image_path = resolve_l34_frame_source(
root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=l34_result_id,
sequence=sequence,
)
if (
prediction.get("source_image_sha256") != case.get("source_image_sha256")
or reference.get("sha256") != case.get("source_image_sha256")
or prediction.get("image_id") != case.get("image_id")
or prediction.get("frame_index") != case.get("frame_index")
):
raise HTTPException(status_code=404, detail="L3.4A case binding changed")
return result, case, prediction, image_path
def _configured_root(provider: AuditRootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: AuditRootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
candidate
for candidate in root.iterdir()
if candidate.is_dir()
and not candidate.is_symlink()
and _RESULT_ID.fullmatch(candidate.name) is not None
and (candidate / L34A_MANIFEST_NAME).is_file()
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,202 @@
"""Read-only API for the L3.4B nested-box consolidation shadow."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.l34b_nested_box_consolidation_shadow import (
L34B_MANIFEST_NAME,
L34BNestedBoxConsolidationError,
read_l34b_nested_box_consolidation_shadow,
)
from k1link.web.l34_right_yolox_truth_island_api import (
RootProvider,
resolve_l34_frame_source,
)
_RESULT_ID = re.compile(r"^l34b-nested-box-consolidation-shadow-[a-f0-9]{64}$")
ShadowRootProvider = Callable[[], Path | None]
def build_l34b_nested_box_consolidation_router(
*,
shadow_root_provider: ShadowRootProvider = lambda: None,
l34_root_provider: RootProvider = lambda: None,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@router.get("/l34b/results")
def list_l34b_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
items: list[dict[str, object]] = []
invalid_total = 0
candidates = _candidates(shadow_root_provider)
for candidate in candidates:
try:
result = read_l34b_nested_box_consolidation_shadow(candidate)
if len(items) < limit:
items.append(_project(result))
except (L34BNestedBoxConsolidationError, OSError, ValueError):
invalid_total += 1
return {
"schema_version": "missioncore.l34b-nested-box-consolidation-catalog/v1",
"configured": _configured_root(shadow_root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/l34b/results/{result_id}/cases/{sequence}")
def get_l34b_case(result_id: str, sequence: int) -> dict[str, object]:
result, case, _, _ = _resolve_case(
shadow_root_provider=shadow_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return {
**copy.deepcopy(case),
"result_id": result["result_id"],
"ground_truth": False,
"access": "read-only",
}
@router.get("/l34b/results/{result_id}/cases/{sequence}/camera")
def get_l34b_case_camera(result_id: str, sequence: int) -> FileResponse:
_, _, _, image_path = _resolve_case(
shadow_root_provider=shadow_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return FileResponse(image_path, media_type="image/png")
return router
def _project(result: dict[str, Any]) -> dict[str, object]:
report = result["report"]
return {
"result_id": result["result_id"],
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"profile": copy.deepcopy(report["profile"]),
"pipeline_id": report["method"]["pipeline_id"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"metrics": copy.deepcopy(report["metrics"]),
"cases": [_case_summary(case) for case in result["cases"]],
"case_order": copy.deepcopy(report["case_order"]),
"method": copy.deepcopy(report["method"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"authority": copy.deepcopy(report["authority"]),
"ground_truth": False,
"access": "read-only",
}
def _case_summary(case: dict[str, Any]) -> dict[str, object]:
return {
"truth_island_sequence": case["truth_island_sequence"],
"image_id": case["image_id"],
"frame_index": case["frame_index"],
"group_id": case["group_id"],
"session_seconds": case["session_seconds"],
"source_image_sha256": case["source_image_sha256"],
"before_summary": copy.deepcopy(case["before_summary"]),
"after_summary": copy.deepcopy(case["after_summary"]),
"consolidation_count": len(case["consolidations"]),
}
def _resolve_case(
*,
shadow_root_provider: ShadowRootProvider,
l34_root_provider: RootProvider,
truth_root_provider: RootProvider,
evaluation_pack_root_provider: RootProvider,
result_id: str,
sequence: int,
) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any], Path]:
if _RESULT_ID.fullmatch(result_id) is None or not 1 <= sequence <= 32:
raise HTTPException(status_code=404, detail="L3.4B case not found")
root = _configured_root(shadow_root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.4B result not found")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="L3.4B result not found")
try:
result = read_l34b_nested_box_consolidation_shadow(path)
except (L34BNestedBoxConsolidationError, OSError):
raise HTTPException(status_code=404, detail="L3.4B result not found") from None
case = next(
(item for item in result["cases"] if item.get("truth_island_sequence") == sequence),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="L3.4B case not found")
l34_result_id = result["manifest"]["identity"]["l34_freeze"]["result_id"]
_, prediction, reference, image_path = resolve_l34_frame_source(
root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=l34_result_id,
sequence=sequence,
)
if (
prediction.get("source_image_sha256") != case.get("source_image_sha256")
or reference.get("sha256") != case.get("source_image_sha256")
or prediction.get("image_id") != case.get("image_id")
or prediction.get("frame_index") != case.get("frame_index")
):
raise HTTPException(status_code=404, detail="L3.4B case binding changed")
return result, case, prediction, image_path
def _configured_root(provider: ShadowRootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: ShadowRootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
candidate
for candidate in root.iterdir()
if candidate.is_dir()
and not candidate.is_symlink()
and _RESULT_ID.fullmatch(candidate.name) is not None
and (candidate / L34B_MANIFEST_NAME).is_file()
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
+206
View File
@@ -0,0 +1,206 @@
"""Read-only API for the L3.4C temporal tile-seam stitch shadow."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.l34c_tile_seam_stitch_shadow import (
L34C_MANIFEST_NAME,
L34CTileSeamStitchError,
read_l34c_tile_seam_stitch_shadow,
)
from k1link.web.l34_right_yolox_truth_island_api import (
RootProvider,
resolve_l34_frame_source,
)
_RESULT_ID = re.compile(r"^l34c-tile-seam-stitch-shadow-[a-f0-9]{64}$")
ShadowRootProvider = Callable[[], Path | None]
def build_l34c_tile_seam_stitch_router(
*,
shadow_root_provider: ShadowRootProvider = lambda: None,
l34_root_provider: RootProvider = lambda: None,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@router.get("/l34c/results")
def list_l34c_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
items: list[dict[str, object]] = []
invalid_total = 0
candidates = _candidates(shadow_root_provider)
for candidate in candidates:
try:
result = read_l34c_tile_seam_stitch_shadow(candidate)
if len(items) < limit:
items.append(_project(result))
except (L34CTileSeamStitchError, OSError, ValueError):
invalid_total += 1
return {
"schema_version": "missioncore.l34c-tile-seam-stitch-catalog/v1",
"configured": _configured_root(shadow_root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/l34c/results/{result_id}/cases/{sequence}")
def get_l34c_case(result_id: str, sequence: int) -> dict[str, object]:
result, case, _, _ = _resolve_case(
shadow_root_provider=shadow_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return {
**copy.deepcopy(case),
"result_id": result["result_id"],
"ground_truth": False,
"access": "read-only",
}
@router.get("/l34c/results/{result_id}/cases/{sequence}/camera")
def get_l34c_case_camera(result_id: str, sequence: int) -> FileResponse:
_, _, _, image_path = _resolve_case(
shadow_root_provider=shadow_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return FileResponse(image_path, media_type="image/png")
return router
def _project(result: dict[str, Any]) -> dict[str, object]:
report = result["report"]
return {
"result_id": result["result_id"],
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"profile": copy.deepcopy(report["profile"]),
"pipeline_id": report["method"]["pipeline_id"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"metrics": copy.deepcopy(report["metrics"]),
"cases": [_case_summary(case) for case in result["cases"]],
"case_order": copy.deepcopy(report["case_order"]),
"method": copy.deepcopy(report["method"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"authority": copy.deepcopy(report["authority"]),
"ground_truth": False,
"access": "read-only",
}
def _case_summary(case: dict[str, Any]) -> dict[str, object]:
return {
"truth_island_sequence": case["truth_island_sequence"],
"image_id": case["image_id"],
"frame_index": case["frame_index"],
"group_id": case["group_id"],
"session_seconds": case["session_seconds"],
"source_image_sha256": case["source_image_sha256"],
"before_summary": copy.deepcopy(case["before_summary"]),
"after_summary": copy.deepcopy(case["after_summary"]),
"stitch_count": len(case["stitches"]),
}
def _resolve_case(
*,
shadow_root_provider: ShadowRootProvider,
l34_root_provider: RootProvider,
truth_root_provider: RootProvider,
evaluation_pack_root_provider: RootProvider,
result_id: str,
sequence: int,
) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any], Path]:
if _RESULT_ID.fullmatch(result_id) is None or not 1 <= sequence <= 32:
raise HTTPException(status_code=404, detail="L3.4C case not found")
root = _configured_root(shadow_root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.4C result not found")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="L3.4C result not found")
try:
result = read_l34c_tile_seam_stitch_shadow(path)
except (L34CTileSeamStitchError, OSError):
raise HTTPException(status_code=404, detail="L3.4C result not found") from None
case = next(
(
item
for item in result["cases"]
if item.get("truth_island_sequence") == sequence
),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="L3.4C case not found")
l34_result_id = result["manifest"]["identity"]["l34_freeze"]["result_id"]
_, prediction, reference, image_path = resolve_l34_frame_source(
root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=l34_result_id,
sequence=sequence,
)
if (
prediction.get("source_image_sha256") != case.get("source_image_sha256")
or reference.get("sha256") != case.get("source_image_sha256")
or prediction.get("image_id") != case.get("image_id")
or prediction.get("frame_index") != case.get("frame_index")
):
raise HTTPException(status_code=404, detail="L3.4C case binding changed")
return result, case, prediction, image_path
def _configured_root(provider: ShadowRootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: ShadowRootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
candidate
for candidate in root.iterdir()
if candidate.is_dir()
and not candidate.is_symlink()
and _RESULT_ID.fullmatch(candidate.name) is not None
and (candidate / L34C_MANIFEST_NAME).is_file()
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,207 @@
"""Read-only API for the L3.4D cumulative post-processing candidate."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.l34d_cumulative_postprocessing_candidate import (
L34D_MANIFEST_NAME,
L34DCumulativeCandidateError,
read_l34d_cumulative_postprocessing_candidate,
)
from k1link.web.l34_right_yolox_truth_island_api import (
RootProvider,
resolve_l34_frame_source,
)
_RESULT_ID = re.compile(r"^l34d-cumulative-postprocessing-candidate-[a-f0-9]{64}$")
CandidateRootProvider = Callable[[], Path | None]
def build_l34d_cumulative_postprocessing_router(
*,
candidate_root_provider: CandidateRootProvider = lambda: None,
l34_root_provider: RootProvider = lambda: None,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@router.get("/l34d/results")
def list_l34d_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
items: list[dict[str, object]] = []
invalid_total = 0
candidates = _candidates(candidate_root_provider)
for candidate in candidates:
try:
result = read_l34d_cumulative_postprocessing_candidate(candidate)
if len(items) < limit:
items.append(_project(result))
except (L34DCumulativeCandidateError, OSError, ValueError):
invalid_total += 1
return {
"schema_version": ("missioncore.l34d-cumulative-postprocessing-catalog/v1"),
"configured": _configured_root(candidate_root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/l34d/results/{result_id}/cases/{sequence}")
def get_l34d_case(result_id: str, sequence: int) -> dict[str, object]:
result, case, _, _, _ = resolve_l34d_case_source(
candidate_root_provider=candidate_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return {
**copy.deepcopy(case),
"result_id": result["result_id"],
"ground_truth": False,
"access": "read-only",
}
@router.get("/l34d/results/{result_id}/cases/{sequence}/camera")
def get_l34d_case_camera(result_id: str, sequence: int) -> FileResponse:
_, _, _, _, image_path = resolve_l34d_case_source(
candidate_root_provider=candidate_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return FileResponse(image_path, media_type="image/png")
return router
def _project(result: dict[str, Any]) -> dict[str, object]:
report = result["report"]
return {
"result_id": result["result_id"],
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"profile": copy.deepcopy(report["profile"]),
"pipeline_id": report["method"]["pipeline_id"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"metrics": copy.deepcopy(report["metrics"]),
"cases": [_case_summary(case) for case in result["cases"]],
"case_order": copy.deepcopy(report["case_order"]),
"method": copy.deepcopy(report["method"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"authority": copy.deepcopy(report["authority"]),
"ground_truth": False,
"access": "read-only",
}
def _case_summary(case: dict[str, Any]) -> dict[str, object]:
operations = case["operations"]
return {
"truth_island_sequence": case["truth_island_sequence"],
"image_id": case["image_id"],
"frame_index": case["frame_index"],
"group_id": case["group_id"],
"session_seconds": case["session_seconds"],
"source_image_sha256": case["source_image_sha256"],
"before_summary": copy.deepcopy(case["before_summary"]),
"after_summary": copy.deepcopy(case["after_summary"]),
"operation_count": len(operations),
"operation_types": [item["operation_type"] for item in operations],
}
def resolve_l34d_case_source(
*,
candidate_root_provider: CandidateRootProvider,
l34_root_provider: RootProvider,
truth_root_provider: RootProvider,
evaluation_pack_root_provider: RootProvider,
result_id: str,
sequence: int,
) -> tuple[dict[str, Any], dict[str, Any], Any, dict[str, Any], Path]:
if _RESULT_ID.fullmatch(result_id) is None or not 1 <= sequence <= 32:
raise HTTPException(status_code=404, detail="L3.4D case not found")
root = _configured_root(candidate_root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.4D result not found")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="L3.4D result not found")
try:
result = read_l34d_cumulative_postprocessing_candidate(path)
except (L34DCumulativeCandidateError, OSError):
raise HTTPException(
status_code=404,
detail="L3.4D result not found",
) from None
case = next(
(item for item in result["cases"] if item.get("truth_island_sequence") == sequence),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="L3.4D case not found")
l34_result_id = result["manifest"]["identity"]["l34_freeze"]["result_id"]
l34_result, prediction, reference, image_path = resolve_l34_frame_source(
root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=l34_result_id,
sequence=sequence,
)
if (
prediction.get("source_image_sha256") != case.get("source_image_sha256")
or reference.get("sha256") != case.get("source_image_sha256")
or prediction.get("image_id") != case.get("image_id")
or prediction.get("frame_index") != case.get("frame_index")
):
raise HTTPException(status_code=404, detail="L3.4D case binding changed")
return result, case, l34_result, reference, image_path
def _configured_root(provider: CandidateRootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: CandidateRootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
candidate
for candidate in root.iterdir()
if candidate.is_dir()
and not candidate.is_symlink()
and _RESULT_ID.fullmatch(candidate.name) is not None
and (candidate / L34D_MANIFEST_NAME).is_file()
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
@@ -0,0 +1,219 @@
"""Read-only API for the L3.4E manual self-review diagnostic."""
from __future__ import annotations
import copy
import re
from collections.abc import Callable
from pathlib import Path
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse
from k1link.compute.l34e_self_review_diagnostic import (
L34E_MANIFEST_NAME,
L34ESelfReviewDiagnosticError,
read_l34e_self_review_diagnostic,
)
from k1link.web.l34_right_yolox_truth_island_api import RootProvider
from k1link.web.l34d_cumulative_postprocessing_api import (
CandidateRootProvider,
resolve_l34d_case_source,
)
_RESULT_ID = re.compile(r"^l34e-self-review-diagnostic-[a-f0-9]{64}$")
DiagnosticRootProvider = Callable[[], Path | None]
def build_l34e_self_review_diagnostic_router(
*,
diagnostic_root_provider: DiagnosticRootProvider = lambda: None,
candidate_root_provider: CandidateRootProvider = lambda: None,
l34_root_provider: RootProvider = lambda: None,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@router.get("/l34e/results")
def list_l34e_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
items: list[dict[str, object]] = []
invalid_total = 0
candidates = _candidates(diagnostic_root_provider)
for candidate in candidates:
try:
result = read_l34e_self_review_diagnostic(candidate)
if len(items) < limit:
items.append(_project(result))
except (L34ESelfReviewDiagnosticError, OSError, ValueError):
invalid_total += 1
return {
"schema_version": "missioncore.l34e-self-review-diagnostic-catalog/v1",
"configured": _configured_root(diagnostic_root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/l34e/results/{result_id}/cases/{sequence}")
def get_l34e_case(result_id: str, sequence: int) -> dict[str, object]:
result, case, _ = resolve_l34e_case_source(
diagnostic_root_provider=diagnostic_root_provider,
candidate_root_provider=candidate_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return {
**copy.deepcopy(case),
"result_id": result["result_id"],
"ground_truth": False,
"access": "read-only",
}
@router.get("/l34e/results/{result_id}/cases/{sequence}/camera")
def get_l34e_case_camera(result_id: str, sequence: int) -> FileResponse:
_, _, image_path = resolve_l34e_case_source(
diagnostic_root_provider=diagnostic_root_provider,
candidate_root_provider=candidate_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
return FileResponse(image_path, media_type="image/png")
return router
def resolve_l34e_case_source(
*,
diagnostic_root_provider: DiagnosticRootProvider,
candidate_root_provider: CandidateRootProvider,
l34_root_provider: RootProvider,
truth_root_provider: RootProvider,
evaluation_pack_root_provider: RootProvider,
result_id: str,
sequence: int,
) -> tuple[dict[str, Any], dict[str, Any], Path]:
if _RESULT_ID.fullmatch(result_id) is None or not 1 <= sequence <= 32:
raise HTTPException(status_code=404, detail="L3.4E case not found")
root = _configured_root(diagnostic_root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.4E result not found")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="L3.4E result not found")
try:
result = read_l34e_self_review_diagnostic(path)
except (L34ESelfReviewDiagnosticError, OSError):
raise HTTPException(
status_code=404,
detail="L3.4E result not found",
) from None
case = next(
(
item
for item in result["cases"]
if item.get("truth_island_sequence") == sequence
),
None,
)
if case is None:
raise HTTPException(status_code=404, detail="L3.4E case not found")
l34d_result_id = result["manifest"]["identity"]["l34d_candidate"][
"result_id"
]
_, l34d_case, _, _, image_path = resolve_l34d_case_source(
candidate_root_provider=candidate_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=l34d_result_id,
sequence=sequence,
)
if any(
case.get(key) != l34d_case.get(key)
for key in (
"truth_island_sequence",
"image_id",
"frame_index",
"source_image_sha256",
)
):
raise HTTPException(status_code=404, detail="L3.4E case binding changed")
return result, case, image_path
def _project(result: dict[str, Any]) -> dict[str, object]:
report = result["report"]
return {
"result_id": result["result_id"],
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"profile": copy.deepcopy(report["profile"]),
"pipeline_id": report["method"]["pipeline_id"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"metrics": copy.deepcopy(report["metrics"]),
"cases": [_case_summary(case) for case in result["cases"]],
"case_order": copy.deepcopy(report["case_order"]),
"method": copy.deepcopy(report["method"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"authority": copy.deepcopy(report["authority"]),
"ground_truth": False,
"access": "read-only",
}
def _case_summary(case: dict[str, Any]) -> dict[str, object]:
return {
"truth_island_sequence": case["truth_island_sequence"],
"image_id": case["image_id"],
"frame_index": case["frame_index"],
"group_id": case["group_id"],
"session_seconds": case["session_seconds"],
"source_image_sha256": case["source_image_sha256"],
"strict_summary": copy.deepcopy(case["strict_summary"]),
"diagnostic_summary": copy.deepcopy(case["diagnostic_summary"]),
}
def _configured_root(provider: DiagnosticRootProvider) -> Path | None:
value = provider()
if value is None:
return None
candidate = value.expanduser().absolute()
if candidate.is_symlink():
return None
try:
root = candidate.resolve(strict=True)
except OSError:
return None
return root if root.is_dir() else None
def _candidates(provider: DiagnosticRootProvider) -> list[Path]:
root = _configured_root(provider)
if root is None:
return []
return sorted(
(
candidate
for candidate in root.iterdir()
if candidate.is_dir()
and not candidate.is_symlink()
and _RESULT_ID.fullmatch(candidate.name) is not None
and (candidate / L34E_MANIFEST_NAME).is_file()
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
+601
View File
@@ -0,0 +1,601 @@
"""Revisioned L3.4F disagreement adjudication and immutable freeze API."""
from __future__ import annotations
import copy
import hashlib
import json
import math
import re
import threading
from collections.abc import Callable
from datetime import UTC, datetime
from pathlib import Path
from typing import Annotated, Any, Final, Literal
from fastapi import APIRouter, HTTPException, Query
from fastapi import Path as ApiPath
from fastapi.responses import FileResponse
from pydantic import BaseModel, ConfigDict, Field
from k1link.artifacts import write_json_atomic
from k1link.compute.l34e_self_review_diagnostic import (
L34ESelfReviewDiagnosticError,
read_l34e_self_review_diagnostic,
)
from k1link.compute.l34f_adjudicated_reference import (
L34F_MANIFEST_NAME,
L34F_SESSION_SCHEMA,
L34FAdjudicatedReferenceError,
build_l34f_adjudicated_reference,
read_l34f_adjudicated_reference,
)
from k1link.web.l34_right_yolox_truth_island_api import RootProvider
from k1link.web.l34d_cumulative_postprocessing_api import CandidateRootProvider
from k1link.web.l34e_self_review_diagnostic_api import (
DiagnosticRootProvider,
resolve_l34e_case_source,
)
_DIAGNOSTIC_ID = re.compile(r"^l34e-self-review-diagnostic-[a-f0-9]{64}$")
_SESSION_ID = re.compile(r"^l34f-adjudication-session-[a-f0-9]{64}$")
_RESULT_ID = re.compile(r"^l34f-adjudicated-reference-[a-f0-9]{64}$")
_OBJECT_ID = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,95}$")
_OPERATION_KEY = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$")
_TARGET_CLASSES: Final = (
"person",
"bicycle",
"motorcycle",
"car",
"heavy_vehicle",
"static_obstacle",
"animal",
)
_AUTHORITY: Final = {
"ground_truth": False,
"independent_truth": False,
"metric_grade_reference": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
_BLINDNESS: Final = {
"candidate_identity_seen": True,
"model_prelabels_seen": False,
"model_predictions_seen": True,
"model_scores_seen": False,
"source_self_review_seen": True,
}
_ASSISTANCE: Final = {
"mode": "candidate-visible-human-adjudication",
"independent_truth_eligible": False,
"metric_grade_reference": False,
}
AdjudicationRootProvider = Callable[[], Path | None]
ResultRootProvider = Callable[[], Path | None]
class L34FCreateRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
idempotency_key: str = Field(min_length=1, max_length=128)
class L34FObjectRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
object_id: str = Field(min_length=1, max_length=96)
category: Literal[
"person",
"bicycle",
"motorcycle",
"car",
"heavy_vehicle",
"static_obstacle",
"animal",
"unmapped",
]
proposed_label: str | None = Field(default=None, max_length=80)
origin: Literal["self_review_seed", "adjudicated_manual"]
box_xyxy: list[float] = Field(min_length=4, max_length=4)
occluded: bool
truncated: bool
class L34FFrameRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
truth_island_sequence: int = Field(ge=1, le=32)
reviewed: bool
objects: list[L34FObjectRequest] = Field(max_length=256)
class L34FSaveRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
expected_revision: int = Field(ge=0)
idempotency_key: str = Field(min_length=1, max_length=128)
title: str = Field(min_length=1, max_length=160)
frames: list[L34FFrameRequest] = Field(min_length=32, max_length=32)
class L34FFreezeRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
expected_revision: int = Field(ge=1)
class _Store:
def __init__(self, provider: AdjudicationRootProvider) -> None:
self.provider = provider
self.lock = threading.Lock()
def list(self, diagnostic_id: str) -> list[dict[str, object]]:
root = self._diagnostic_root(diagnostic_id, create=False)
if root is None:
return []
items: list[dict[str, object]] = []
for path in sorted(root.glob("l34f-adjudication-session-*.json")):
if path.is_symlink() or _SESSION_ID.fullmatch(path.stem) is None:
continue
try:
items.append(_project_session(self._read(path, diagnostic_id), False))
except (OSError, ValueError):
continue
items.sort(key=lambda item: str(item["created_at_utc"]))
return items
def create(self, diagnostic: dict[str, Any], key: str) -> dict[str, object]:
diagnostic_id = diagnostic["result_id"]
_validate_operation_key(key)
digest = hashlib.sha256(f"{diagnostic_id}\n{key}".encode()).hexdigest()
session_id = f"l34f-adjudication-session-{digest}"
with self.lock:
path = self._session_path(diagnostic_id, session_id, create=True)
assert path is not None
if path.exists():
return _project_session(self._read(path, diagnostic_id), True)
now = _utc_now()
frames = []
for case in sorted(diagnostic["cases"], key=lambda row: row["truth_island_sequence"]):
frames.append(
{
"truth_island_sequence": int(case["truth_island_sequence"]),
"image_id": int(case["image_id"]),
"frame_index": int(case["frame_index"]),
"source_sha256": str(case["source_image_sha256"]),
"reviewed": False,
"objects": [
{
"object_id": str(item["object_id"]),
"category": str(item["category"]),
"proposed_label": item.get("proposed_label"),
"origin": "self_review_seed",
"box_xyxy": [float(value) for value in item["box_xyxy"]],
"occluded": bool(item["occluded"]),
"truncated": bool(item["truncated"]),
}
for item in case["references"]
],
}
)
reviewer_slot = len(self.list(diagnostic_id)) + 1
document: dict[str, object] = {
"schema_version": L34F_SESSION_SCHEMA,
"session_id": session_id,
"diagnostic_result_id": diagnostic_id,
"source_session_id": str(diagnostic["report"]["source_session_id"]),
"source_review_session_id": str(
diagnostic["manifest"]["identity"]["self_review"]["session_id"]
),
"contract_id": "l34e-candidate-visible-adjudication/v1",
"title": f"Разбор конфликтов · LAB L3.4F · Рецензент {reviewer_slot}",
"reviewer_slot": reviewer_slot,
"revision": 0,
"state": "draft",
"created_at_utc": now,
"updated_at_utc": now,
"frames": frames,
"blindness": dict(_BLINDNESS),
"assistance": dict(_ASSISTANCE),
"authority": dict(_AUTHORITY),
"last_save_idempotency_key": None,
}
write_json_atomic(path, document)
return _project_session(document, True)
def get(self, diagnostic_id: str, session_id: str) -> dict[str, object]:
path = self._session_path(diagnostic_id, session_id, create=False)
if path is None or not path.is_file() or path.is_symlink():
raise HTTPException(status_code=404, detail="Сессия adjudication не найдена")
try:
return _project_session(self._read(path, diagnostic_id), True)
except (OSError, ValueError) as exc:
raise HTTPException(status_code=409, detail="Сессия adjudication повреждена") from exc
def save(
self,
diagnostic: dict[str, Any],
session_id: str,
request: L34FSaveRequest,
) -> dict[str, object]:
diagnostic_id = diagnostic["result_id"]
_validate_operation_key(request.idempotency_key)
path = self._session_path(diagnostic_id, session_id, create=False)
if path is None or not path.is_file() or path.is_symlink():
raise HTTPException(status_code=404, detail="Сессия adjudication не найдена")
source_cases = {int(case["truth_island_sequence"]): case for case in diagnostic["cases"]}
seen: set[int] = set()
frames: list[dict[str, object]] = []
for frame in request.frames:
if frame.truth_island_sequence in seen:
raise HTTPException(status_code=422, detail="Кадр передан дважды")
seen.add(frame.truth_island_sequence)
source = source_cases[frame.truth_island_sequence]
frames.append(
{
"truth_island_sequence": frame.truth_island_sequence,
"image_id": int(source["image_id"]),
"frame_index": int(source["frame_index"]),
"source_sha256": str(source["source_image_sha256"]),
"reviewed": frame.reviewed,
"objects": [_normalize_object(item) for item in frame.objects],
}
)
if seen != set(range(1, 33)):
raise HTTPException(status_code=422, detail="Требуются все 32 кадра")
frames.sort(key=lambda item: int(item["truth_island_sequence"]))
with self.lock:
current = self._read(path, diagnostic_id)
if current.get("last_save_idempotency_key") == request.idempotency_key:
return _project_session(current, True)
if current["revision"] != request.expected_revision:
raise HTTPException(status_code=409, detail="Сессия уже изменена в другом окне")
current.update(
{
"title": request.title.strip(),
"revision": request.expected_revision + 1,
"state": "saved",
"updated_at_utc": _utc_now(),
"frames": frames,
"last_save_idempotency_key": request.idempotency_key,
}
)
write_json_atomic(path, current)
return _project_session(current, True)
def session_path(self, diagnostic_id: str, session_id: str) -> Path:
path = self._session_path(diagnostic_id, session_id, create=False)
if path is None or not path.is_file() or path.is_symlink():
raise HTTPException(status_code=404, detail="Сессия adjudication не найдена")
return path
def _diagnostic_root(self, diagnostic_id: str, *, create: bool) -> Path | None:
if _DIAGNOSTIC_ID.fullmatch(diagnostic_id) is None:
raise HTTPException(status_code=404, detail="L3.4E result не найден")
value = self.provider()
if value is None:
raise HTTPException(status_code=503, detail="Хранилище adjudication не настроено")
root = value.expanduser().absolute()
if root.is_symlink():
raise HTTPException(status_code=503, detail="Хранилище adjudication недоступно")
if create:
root.mkdir(mode=0o700, parents=True, exist_ok=True)
if not root.is_dir():
return None
root = root.resolve(strict=True)
child = root / diagnostic_id
if create:
child.mkdir(mode=0o700, exist_ok=True)
if not child.is_dir() or child.is_symlink():
return None
resolved = child.resolve(strict=True)
if resolved.parent != root:
raise HTTPException(status_code=503, detail="Хранилище adjudication недоступно")
return resolved
def _session_path(self, diagnostic_id: str, session_id: str, *, create: bool) -> Path | None:
if _SESSION_ID.fullmatch(session_id) is None:
raise HTTPException(status_code=404, detail="Сессия adjudication не найдена")
root = self._diagnostic_root(diagnostic_id, create=create)
return None if root is None else root / f"{session_id}.json"
def _read(self, path: Path, diagnostic_id: str) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if (
not isinstance(value, dict)
or value.get("schema_version") != L34F_SESSION_SCHEMA
or value.get("session_id") != path.stem
or value.get("diagnostic_result_id") != diagnostic_id
or value.get("contract_id") != "l34e-candidate-visible-adjudication/v1"
or value.get("blindness") != _BLINDNESS
or value.get("assistance") != _ASSISTANCE
or value.get("authority") != _AUTHORITY
or not isinstance(value.get("revision"), int)
or not isinstance(value.get("frames"), list)
or len(value["frames"]) != 32
):
raise ValueError("invalid L3.4F session")
return value
def build_l34f_adjudication_router(
*,
diagnostic_root_provider: DiagnosticRootProvider = lambda: None,
candidate_root_provider: CandidateRootProvider = lambda: None,
l34_root_provider: RootProvider = lambda: None,
truth_root_provider: RootProvider = lambda: None,
evaluation_pack_root_provider: RootProvider = lambda: None,
adjudication_root_provider: AdjudicationRootProvider = lambda: None,
result_root_provider: ResultRootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory/l34f", tags=["laboratory"])
store = _Store(adjudication_root_provider)
def diagnostic(result_id: str) -> dict[str, Any]:
if _DIAGNOSTIC_ID.fullmatch(result_id) is None:
raise HTTPException(status_code=404, detail="L3.4E result не найден")
root = _configured_root(diagnostic_root_provider)
if root is None:
raise HTTPException(status_code=404, detail="L3.4E result не найден")
path = (root / result_id).resolve()
if path.parent != root or path.is_symlink():
raise HTTPException(status_code=404, detail="L3.4E result не найден")
try:
return read_l34e_self_review_diagnostic(path)
except (L34ESelfReviewDiagnosticError, OSError):
raise HTTPException(status_code=404, detail="L3.4E result не найден") from None
def case_source(result_id: str, sequence: int) -> tuple[dict[str, Any], dict[str, Any], Path]:
return resolve_l34e_case_source(
diagnostic_root_provider=diagnostic_root_provider,
candidate_root_provider=candidate_root_provider,
l34_root_provider=l34_root_provider,
truth_root_provider=truth_root_provider,
evaluation_pack_root_provider=evaluation_pack_root_provider,
result_id=result_id,
sequence=sequence,
)
@router.get("/diagnostics/{diagnostic_id}/cases/{sequence}")
def get_case(diagnostic_id: str, sequence: int) -> dict[str, object]:
result, case, image_path = case_source(diagnostic_id, sequence)
width, height = _png_dimensions(image_path)
return {
"schema_version": "missioncore.l34f-adjudication-case/v1",
"diagnostic_result_id": result["result_id"],
"truth_island_sequence": sequence,
"image_id": case["image_id"],
"frame_index": case["frame_index"],
"group_id": case["group_id"],
"session_seconds": case["session_seconds"],
"source_image_sha256": case["source_image_sha256"],
"camera": {"width": width, "height": height},
"camera_url": (
f"/api/v1/laboratory/l34f/diagnostics/{diagnostic_id}/cases/{sequence}/camera"
),
"candidate_objects": [
{
"candidate_id": f"candidate-{sequence}-{item['prediction_index']}",
"prediction_index": item["prediction_index"],
"category": item["category"],
"box_xyxy": copy.deepcopy(item["box_xyxy"]),
"diagnostic_verdict": item["diagnostic_verdict"],
"associated_object_id": item["associated_object_id"],
}
for item in case["predictions"]
],
"diagnostic_summary": copy.deepcopy(case["diagnostic_summary"]),
"model_scores_included": False,
"ground_truth": False,
"access": "candidate-visible-adjudication-read-only-source",
}
@router.get("/diagnostics/{diagnostic_id}/cases/{sequence}/camera")
def get_camera(diagnostic_id: str, sequence: int) -> FileResponse:
_, _, image_path = case_source(diagnostic_id, sequence)
return FileResponse(image_path, media_type="image/png")
@router.get("/diagnostics/{diagnostic_id}/sessions")
def list_sessions(diagnostic_id: str) -> dict[str, object]:
diagnostic(diagnostic_id)
items = store.list(diagnostic_id)
return {
"schema_version": "missioncore.l34f-adjudication-session-catalog/v1",
"diagnostic_result_id": diagnostic_id,
"items": items,
"total": len(items),
"access": "human-adjudication",
}
@router.post("/diagnostics/{diagnostic_id}/sessions")
def create_session(diagnostic_id: str, request: L34FCreateRequest) -> dict[str, object]:
return store.create(diagnostic(diagnostic_id), request.idempotency_key)
@router.get("/diagnostics/{diagnostic_id}/sessions/{session_id}")
def get_session(
diagnostic_id: str, session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)]
) -> dict[str, object]:
diagnostic(diagnostic_id)
return store.get(diagnostic_id, session_id)
@router.put("/diagnostics/{diagnostic_id}/sessions/{session_id}")
def save_session(
diagnostic_id: str,
session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)],
request: L34FSaveRequest,
) -> dict[str, object]:
return store.save(diagnostic(diagnostic_id), session_id, request)
@router.post("/diagnostics/{diagnostic_id}/sessions/{session_id}/freeze")
def freeze_session(
diagnostic_id: str,
session_id: Annotated[str, ApiPath(pattern=_SESSION_ID.pattern)],
request: L34FFreezeRequest,
) -> dict[str, object]:
source = diagnostic(diagnostic_id)
session = store.get(diagnostic_id, session_id)
if session["revision"] != request.expected_revision:
raise HTTPException(status_code=409, detail="Сессия уже изменена")
if not session["progress"]["complete"]:
raise HTTPException(status_code=422, detail="Для freeze нужны 32/32 проверенных кадров")
output = result_root_provider()
if output is None:
raise HTTPException(status_code=503, detail="Хранилище L3.4F не настроено")
try:
frozen = build_l34f_adjudicated_reference(
diagnostic_root=source["result_root"],
adjudication_session_path=store.session_path(diagnostic_id, session_id),
output_root=output,
)
except (L34FAdjudicatedReferenceError, OSError) as exc:
raise HTTPException(status_code=409, detail="L3.4F freeze не прошёл проверку") from exc
return _project_result(frozen)
@router.get("/results")
def list_results(limit: int = Query(default=1, ge=1, le=10)) -> dict[str, object]:
candidates = _result_candidates(result_root_provider)
items: list[dict[str, object]] = []
invalid_total = 0
for path in candidates:
try:
result = read_l34f_adjudicated_reference(path)
if len(items) < limit:
items.append(_project_result(result))
except (L34FAdjudicatedReferenceError, OSError):
invalid_total += 1
return {
"schema_version": "missioncore.l34f-adjudicated-reference-catalog/v1",
"configured": _configured_result_root(result_root_provider) is not None,
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
"access": "read-only",
}
return router
def _normalize_object(item: L34FObjectRequest) -> dict[str, object]:
if _OBJECT_ID.fullmatch(item.object_id) is None:
raise HTTPException(status_code=422, detail="Некорректный id рамки")
if any(not math.isfinite(float(value)) for value in item.box_xyxy):
raise HTTPException(status_code=422, detail="Некорректная геометрия рамки")
left, top, right, bottom = (float(value) for value in item.box_xyxy)
if not (0 <= left < right <= 800 and 0 <= top < bottom <= 600):
raise HTTPException(status_code=422, detail="Рамка выходит за границы кадра")
proposed = item.proposed_label.strip() if isinstance(item.proposed_label, str) else None
if item.category == "unmapped" and not proposed:
raise HTTPException(status_code=422, detail="Для другого объекта требуется название")
if item.category != "unmapped" and proposed is not None:
raise HTTPException(status_code=422, detail="Название допустимо только для другого объекта")
return {
"object_id": item.object_id,
"category": item.category,
"proposed_label": proposed,
"origin": item.origin,
"box_xyxy": [left, top, right, bottom],
"occluded": item.occluded,
"truncated": item.truncated,
}
def _project_session(document: dict[str, Any], include_frames: bool) -> dict[str, object]:
frames = document["frames"]
reviewed = sum(frame.get("reviewed") is True for frame in frames)
objects = sum(len(frame.get("objects", [])) for frame in frames)
value = {
key: copy.deepcopy(document[key])
for key in (
"schema_version",
"session_id",
"diagnostic_result_id",
"contract_id",
"title",
"reviewer_slot",
"revision",
"state",
"created_at_utc",
"updated_at_utc",
"blindness",
"assistance",
"authority",
)
}
value["progress"] = {
"reviewed_frame_count": reviewed,
"frame_count": 32,
"object_count": objects,
"complete": reviewed == 32,
}
if include_frames:
value["frames"] = copy.deepcopy(frames)
return value
def _project_result(result: dict[str, Any]) -> dict[str, object]:
report = result["report"]
identity = result["manifest"]["identity"]
return {
"result_id": result["result_id"],
"created_at_utc": report["created_at_utc"],
"status": report["status"],
"source_session_id": report["source_session_id"],
"camera_source_id": report["camera_source_id"],
"diagnostic_result_id": identity["l34e_diagnostic"]["result_id"],
"adjudication_session_id": identity["adjudication_session"]["session_id"],
"metrics": copy.deepcopy(report["metrics"]),
"decision": copy.deepcopy(report["decision"]),
"limitations": copy.deepcopy(report["limitations"]),
"authority": copy.deepcopy(report["authority"]),
"ground_truth": False,
"access": "read-only",
}
def _configured_root(provider: DiagnosticRootProvider) -> Path | None:
value = provider()
if value is None:
return None
path = value.expanduser().absolute()
if path.is_symlink():
return None
try:
path = path.resolve(strict=True)
except OSError:
return None
return path if path.is_dir() else None
def _configured_result_root(provider: ResultRootProvider) -> Path | None:
return _configured_root(provider)
def _result_candidates(provider: ResultRootProvider) -> list[Path]:
root = _configured_result_root(provider)
if root is None:
return []
return sorted(
(
path
for path in root.iterdir()
if path.is_dir()
and not path.is_symlink()
and _RESULT_ID.fullmatch(path.name) is not None
and (path / L34F_MANIFEST_NAME).is_file()
),
key=lambda path: path.stat().st_mtime_ns,
reverse=True,
)
def _validate_operation_key(value: str) -> None:
if _OPERATION_KEY.fullmatch(value) is None:
raise HTTPException(status_code=422, detail="Некорректный ключ операции")
def _png_dimensions(path: Path) -> tuple[int, int]:
header = path.read_bytes()[:24]
if len(header) != 24 or header[:8] != b"\x89PNG\r\n\x1a\n" or header[12:16] != b"IHDR":
raise HTTPException(status_code=404, detail="Кадр повреждён")
return int.from_bytes(header[16:20], "big"), int.from_bytes(header[20:24], "big")
def _utc_now() -> str:
return datetime.now(UTC).isoformat(timespec="milliseconds").replace("+00:00", "Z")
+246 -5
View File
@@ -53,11 +53,222 @@ def test_advanced_index_is_empty_when_not_configured() -> None:
}
def test_advanced_index_publishes_l31_ravnoves_identity(
def test_advanced_index_publishes_l34b_shadow_identity(tmp_path: Path) -> None:
root = tmp_path / "l34b"
digest = "d" * 64
result_id = f"l34b-nested-box-consolidation-shadow-{digest}"
candidate = root / result_id
candidate.mkdir(parents=True)
(candidate / "manifest.json").write_text(
json.dumps(
{
"schema_version": (
"missioncore.l34b-nested-box-consolidation-shadow/v1"
),
"result_id": result_id,
"identity_sha256": digest,
"identity": {
"authority": {
"ground_truth": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
},
"created_at_utc": "2026-08-03T10:00:00Z",
"ground_truth": False,
}
),
encoding="utf-8",
)
router = build_advanced_laboratory_router(
l34b_root_provider=lambda: root,
)
route = _endpoint(router, "/api/v1/laboratory/advanced-index")
assert route()["items"] == [ # type: ignore[index,operator]
{
"work_id": "l34b-nested-box-consolidation-shadow",
"result_id": result_id,
"created_at_utc": "2026-08-03T10:00:00Z",
"access": "read-only",
}
]
def test_advanced_index_publishes_l34c_shadow_identity(tmp_path: Path) -> None:
root = tmp_path / "l34c"
digest = "c" * 64
result_id = f"l34c-tile-seam-stitch-shadow-{digest}"
candidate = root / result_id
candidate.mkdir(parents=True)
(candidate / "manifest.json").write_text(
json.dumps(
{
"schema_version": "missioncore.l34c-tile-seam-stitch-shadow/v1",
"result_id": result_id,
"identity_sha256": digest,
"identity": {
"authority": {
"ground_truth": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
},
"created_at_utc": "2026-08-03T11:00:00Z",
"ground_truth": False,
}
),
encoding="utf-8",
)
router = build_advanced_laboratory_router(
l34c_root_provider=lambda: root,
)
route = _endpoint(router, "/api/v1/laboratory/advanced-index")
assert route()["items"] == [ # type: ignore[index,operator]
{
"work_id": "l34c-tile-seam-stitch-shadow",
"result_id": result_id,
"created_at_utc": "2026-08-03T11:00:00Z",
"access": "read-only",
}
]
def test_advanced_index_publishes_l34d_candidate_identity(tmp_path: Path) -> None:
root = tmp_path / "l34d"
digest = "e" * 64
result_id = f"l34d-cumulative-postprocessing-candidate-{digest}"
candidate = root / result_id
candidate.mkdir(parents=True)
(candidate / "manifest.json").write_text(
json.dumps(
{
"schema_version": (
"missioncore.l34d-cumulative-postprocessing-candidate/v1"
),
"result_id": result_id,
"identity_sha256": digest,
"identity": {
"authority": {
"ground_truth": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
},
"created_at_utc": "2026-08-03T12:00:00Z",
"ground_truth": False,
}
),
encoding="utf-8",
)
router = build_advanced_laboratory_router(
l34d_root_provider=lambda: root,
)
route = _endpoint(router, "/api/v1/laboratory/advanced-index")
assert route()["items"] == [ # type: ignore[index,operator]
{
"work_id": "l34d-cumulative-postprocessing-candidate",
"result_id": result_id,
"created_at_utc": "2026-08-03T12:00:00Z",
"access": "read-only",
}
]
def test_advanced_index_publishes_l34e_diagnostic_identity(tmp_path: Path) -> None:
root = tmp_path / "l34e"
digest = "f" * 64
result_id = f"l34e-self-review-diagnostic-{digest}"
candidate = root / result_id
candidate.mkdir(parents=True)
(candidate / "manifest.json").write_text(
json.dumps(
{
"schema_version": "missioncore.l34e-self-review-diagnostic/v1",
"result_id": result_id,
"identity_sha256": digest,
"identity": {
"authority": {
"ground_truth": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
},
"created_at_utc": "2026-08-03T13:00:00Z",
"ground_truth": False,
}
),
encoding="utf-8",
)
router = build_advanced_laboratory_router(
l34e_root_provider=lambda: root,
)
route = _endpoint(router, "/api/v1/laboratory/advanced-index")
assert route()["items"] == [ # type: ignore[index,operator]
{
"work_id": "l34e-self-review-diagnostic",
"result_id": result_id,
"created_at_utc": "2026-08-03T13:00:00Z",
"access": "read-only",
}
]
def test_advanced_index_publishes_l34f_adjudicated_reference_identity(
tmp_path: Path,
) -> None:
root = tmp_path / "l34f"
digest = "a" * 64
result_id = f"l34f-adjudicated-reference-{digest}"
candidate = root / result_id
candidate.mkdir(parents=True)
(candidate / "manifest.json").write_text(
json.dumps(
{
"schema_version": "missioncore.l34f-adjudicated-reference/v1",
"result_id": result_id,
"identity_sha256": digest,
"identity": {
"authority": {
"ground_truth": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
},
"created_at_utc": "2026-08-03T14:00:00Z",
"ground_truth": False,
}
),
encoding="utf-8",
)
router = build_advanced_laboratory_router(
l34f_root_provider=lambda: root,
)
route = _endpoint(router, "/api/v1/laboratory/advanced-index")
assert route()["items"] == [ # type: ignore[index,operator]
{
"work_id": "l34f-adjudicated-reference",
"result_id": result_id,
"created_at_utc": "2026-08-03T14:00:00Z",
"access": "read-only",
}
]
def test_advanced_index_publishes_l32_camera_review_identity(
tmp_path: Path,
monkeypatch: MonkeyPatch,
) -> None:
result_id = f"l31-pointpillars-ravnoves-{'b' * 64}"
result_id = f"l32-pointpillars-camera-review-{'b' * 64}"
def fake_latest(provider: object) -> dict[str, str]:
assert callable(provider)
@@ -67,15 +278,15 @@ def test_advanced_index_publishes_l31_ravnoves_identity(
"created_at_utc": "2026-07-31T10:56:45.861Z",
}
monkeypatch.setattr(advanced_api, "latest_l31_identity", fake_latest)
monkeypatch.setattr(advanced_api, "latest_l32_identity", fake_latest)
router = build_advanced_laboratory_router(
l31_ravnoves_root_provider=lambda: tmp_path,
l32_camera_review_root_provider=lambda: tmp_path,
)
route = _endpoint(router, "/api/v1/laboratory/advanced-index")
assert route()["items"] == [ # type: ignore[index,operator]
{
"work_id": "l31-pointpillars-ravnoves",
"work_id": "l32-pointpillars-camera-review",
"result_id": result_id,
"created_at_utc": "2026-07-31T10:56:45.861Z",
"access": "read-only",
@@ -83,6 +294,36 @@ def test_advanced_index_publishes_l31_ravnoves_identity(
]
def test_advanced_index_publishes_l33_camera_first_identity(
tmp_path: Path,
monkeypatch: MonkeyPatch,
) -> None:
result_id = f"l33-camera-first-detector-review-{'c' * 64}"
def fake_latest(provider: object) -> dict[str, str]:
assert callable(provider)
assert provider() == tmp_path # type: ignore[operator]
return {
"result_id": result_id,
"created_at_utc": "2026-07-31T13:42:00.000Z",
}
monkeypatch.setattr(advanced_api, "latest_l33_identity", fake_latest)
router = build_advanced_laboratory_router(
l33_camera_first_review_root_provider=lambda: tmp_path,
)
route = _endpoint(router, "/api/v1/laboratory/advanced-index")
assert route()["items"] == [ # type: ignore[index,operator]
{
"work_id": "l33-camera-first-detector-review",
"result_id": result_id,
"created_at_utc": "2026-07-31T13:42:00.000Z",
"access": "read-only",
}
]
def test_advanced_index_reads_only_bounded_identity_documents(
tmp_path: Path,
) -> None:
+352
View File
@@ -0,0 +1,352 @@
from __future__ import annotations
import hashlib
import json
import struct
import zlib
from pathlib import Path
from types import SimpleNamespace
import pytest
from fastapi import APIRouter, HTTPException
from fastapi.routing import APIRoute
import k1link.compute.e46_lab_review_submission as submission
import k1link.compute.e48_detector_truth_seal as e48
import k1link.web.e46_blind_review_api as api
from k1link.web.l34_annotation_api import (
L34AnnotationCreateRequest,
L34AnnotationFrameRequest,
L34AnnotationObjectRequest,
L34AnnotationSaveRequest,
)
def _endpoint(router: APIRouter, path: str, method: str = "GET") -> object:
for route in router.routes:
if (
isinstance(route, APIRoute)
and route.path == path
and route.methods is not None
and method in route.methods
):
return route.endpoint
raise AssertionError(f"{method} {path} route is missing")
def _png(width: int = 8, height: int = 6) -> bytes:
signature = b"\x89PNG\r\n\x1a\n"
def chunk(kind: bytes, payload: bytes) -> bytes:
return (
struct.pack(">I", len(payload))
+ kind
+ payload
+ struct.pack(">I", zlib.crc32(kind + payload) & 0xFFFFFFFF)
)
pixels = b"".join(b"\x00" + b"\x20\x40\x60" * width for _ in range(height))
return (
signature
+ chunk(b"IHDR", struct.pack(">IIBBBBB", width, height, 8, 2, 0, 0, 0))
+ chunk(b"IDAT", zlib.compress(pixels))
+ chunk(b"IEND", b"")
)
def _fixture(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> tuple[APIRouter, str]:
pack_id = f"evaluation-pack-{'a' * 64}"
pack_root = tmp_path / "packs"
image = pack_root / pack_id / "images" / "valid-fov-fill" / "frame.png"
image.parent.mkdir(parents=True)
image.write_bytes(_png())
image_sha = hashlib.sha256(image.read_bytes()).hexdigest()
truth_id = f"e46-detector-truth-island-{'b' * 64}"
truth_root = tmp_path / "truth" / truth_id
truth_root.mkdir(parents=True)
references = [
{
"truth_island_sequence": sequence,
"image_id": sequence,
"frame_index": sequence * 10,
"session_seconds": float(sequence),
"role": "anchor" if sequence <= 16 else "temporal",
"group_id": (
f"anchor-{sequence:02d}"
if sequence <= 16
else f"clip-{((sequence - 17) // 4) + 1}"
),
"source_path": "images/valid-fov-fill/frame.png",
"byte_length": image.stat().st_size,
"sha256": image_sha,
}
for sequence in range(1, 33)
]
(truth_root / "image-references.jsonl").write_text(
"".join(json.dumps(row) + "\n" for row in references),
encoding="utf-8",
)
(truth_root / "blind-contract.json").write_text(
json.dumps(
{
"annotation": {
"classes": [
"person",
"bicycle",
"motorcycle",
"car",
"heavy_vehicle",
"static_obstacle",
"animal",
]
}
}
),
encoding="utf-8",
)
truth = SimpleNamespace(
result_id=truth_id,
result_root=truth_root,
manifest={
"created_at_utc": "2026-08-04T08:00:00Z",
"identity": {
"source": {
"evaluation_pack_id": pack_id,
"session_id": "ravnoves00",
"source_id": "sensor.camera.right",
}
},
},
report={
"status": "prepared-awaiting-independent-human-review",
"blindness": {"truth_labels_available": False},
"selection": {
"anchor_count": 16,
"temporal_frame_count": 16,
"temporal_group_count": 4,
},
},
)
monkeypatch.setattr(api, "read_e46_detector_truth_island", lambda _: truth)
monkeypatch.setattr(submission, "read_e46_detector_truth_island", lambda _: truth)
monkeypatch.setattr(e48, "read_e46_detector_truth_island", lambda _: truth)
router = api.build_e46_blind_review_router(
truth_root_provider=lambda: truth_root.parent,
evaluation_pack_root_provider=lambda: pack_root,
annotation_root_provider=lambda: tmp_path / "annotations",
submission_root_provider=lambda: tmp_path / "submissions",
)
return router, truth_id
def _complete_frames() -> list[L34AnnotationFrameRequest]:
return [
L34AnnotationFrameRequest(
truth_island_sequence=sequence,
reviewed=True,
hard_negative=True,
objects=[],
)
for sequence in range(1, 33)
]
def test_e46_source_is_candidate_free_and_limits_reviewer_slots(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
router, truth_id = _fixture(tmp_path, monkeypatch)
source = _endpoint(
router,
"/api/v1/laboratory/e46/results/{result_id}/annotation-source",
)(result_id=truth_id) # type: ignore[operator]
assert source["frame_count"] == 32
assert source["contract"]["unmapped_class"] is None
assert source["candidate_identity_included"] is False
assert source["candidate_predictions_included"] is False
assert source["prelabels_included"] is False
assert all("candidate_id" not in frame for frame in source["frames"])
create = _endpoint(
router,
"/api/v1/laboratory/e46/results/{result_id}/annotation-sessions",
"POST",
)
first = create( # type: ignore[operator]
result_id=truth_id,
request=L34AnnotationCreateRequest(idempotency_key="reviewer-slot-a"),
)
second = create( # type: ignore[operator]
result_id=truth_id,
request=L34AnnotationCreateRequest(idempotency_key="reviewer-slot-b"),
)
assert first["reviewer_slot"] == 1
assert second["reviewer_slot"] == 2
get_session = _endpoint(
router,
(
"/api/v1/laboratory/e46/results/{result_id}"
"/annotation-sessions/{session_id}"
),
)
with pytest.raises(HTTPException) as private:
get_session( # type: ignore[operator]
result_id=truth_id,
session_id=first["session_id"],
x_e46_review_capability=second["review_capability"],
)
assert private.value.status_code == 403
with pytest.raises(HTTPException) as caught:
create( # type: ignore[operator]
result_id=truth_id,
request=L34AnnotationCreateRequest(idempotency_key="reviewer-slot-c"),
)
assert caught.value.status_code == 409
def test_e46_complete_session_freezes_as_valid_e48_input(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
router, truth_id = _fixture(tmp_path, monkeypatch)
create = _endpoint(
router,
"/api/v1/laboratory/e46/results/{result_id}/annotation-sessions",
"POST",
)
session = create( # type: ignore[operator]
result_id=truth_id,
request=L34AnnotationCreateRequest(idempotency_key="reviewer-slot-a"),
)
save = _endpoint(
router,
(
"/api/v1/laboratory/e46/results/{result_id}"
"/annotation-sessions/{session_id}"
),
"PUT",
)
saved = save( # type: ignore[operator]
result_id=truth_id,
session_id=session["session_id"],
x_e46_review_capability=session["review_capability"],
request=L34AnnotationSaveRequest(
expected_revision=0,
idempotency_key="save-complete-review-a",
title="E46 review A",
assistance_mode="prediction-free-manual",
frames=_complete_frames(),
),
)
assert saved["progress"]["complete"] is True
freeze = _endpoint(
router,
(
"/api/v1/laboratory/e46/results/{result_id}"
"/annotation-sessions/{session_id}/freeze"
),
"POST",
)
frozen = freeze( # type: ignore[operator]
result_id=truth_id,
session_id=session["session_id"],
x_e46_review_capability=session["review_capability"],
request=api.E46ReviewFreezeRequest(
expected_revision=1,
reviewer_id="reviewer-a",
independent_attestation=True,
candidate_identity_not_seen=True,
model_material_not_seen=True,
),
)
assert frozen["state"] == "completed-e48-review-input-not-truth"
assert frozen["frame_count"] == 32
assert frozen["blindness"]["candidate_identity_seen"] is False
assert frozen["ground_truth"] is False
with pytest.raises(HTTPException) as locked:
save( # type: ignore[operator]
result_id=truth_id,
session_id=session["session_id"],
x_e46_review_capability=session["review_capability"],
request=L34AnnotationSaveRequest(
expected_revision=1,
idempotency_key="cannot-edit-frozen-review-a",
title="E46 review A changed",
assistance_mode="prediction-free-manual",
frames=_complete_frames(),
),
)
assert locked.value.status_code == 409
review_path = (
tmp_path
/ "submissions"
/ frozen["result_id"]
/ submission.E46_LAB_REVIEW_DOCUMENT
)
validated = e48.validate_e48_detector_review_submission(
truth_island_root=tmp_path / "truth" / truth_id,
review_path=review_path,
)
assert validated["reviewer_id"] == "reviewer-a"
assert len(validated["images"]) == 32
def test_e46_rejects_unmapped_object(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
router, truth_id = _fixture(tmp_path, monkeypatch)
create = _endpoint(
router,
"/api/v1/laboratory/e46/results/{result_id}/annotation-sessions",
"POST",
)
session = create( # type: ignore[operator]
result_id=truth_id,
request=L34AnnotationCreateRequest(idempotency_key="reviewer-slot-a"),
)
save = _endpoint(
router,
(
"/api/v1/laboratory/e46/results/{result_id}"
"/annotation-sessions/{session_id}"
),
"PUT",
)
frame = L34AnnotationFrameRequest(
truth_island_sequence=1,
reviewed=True,
hard_negative=False,
objects=[
L34AnnotationObjectRequest(
object_id="object-1",
category="unmapped",
proposed_label="stroller",
origin="manual",
box_xyxy=[1.0, 1.0, 5.0, 5.0],
occluded=False,
truncated=False,
)
],
)
with pytest.raises(HTTPException) as caught:
save( # type: ignore[operator]
result_id=truth_id,
session_id=session["session_id"],
x_e46_review_capability=session["review_capability"],
request=L34AnnotationSaveRequest(
expected_revision=0,
idempotency_key="reject-unmapped",
title="E46 review A",
assistance_mode="prediction-free-manual",
frames=[frame],
),
)
assert caught.value.status_code == 422
@@ -0,0 +1,126 @@
from __future__ import annotations
import hashlib
import json
from pathlib import Path
import pytest
from k1link.web.e46c_full_replay_world_tracks_api import _cached_video_overlay
def _canonical(value: object) -> bytes:
return json.dumps(
value,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
).encode()
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def _source(tmp_path: Path) -> tuple[Path, str, str]:
root = tmp_path / f"e10-integrated-perception-{'1' * 64}"
root.mkdir()
start, end = 35.421857292, 484.044857292
step = (end - start) / 4488
fusion = root / "fusion-frames.jsonl"
with fusion.open("wb") as handle:
for frame_index in range(4489):
objects = []
if frame_index == 20:
objects.append(
{
"bbox_xyxy": [100.0, 120.0, 240.0, 360.0],
"label": "person",
"score": 0.91,
"source_track_id": 83,
"track_id": 240001,
"motion_state": "dynamic",
"motion_confidence": 0.88,
"track_hits": 12,
"track_age_s": 1.2,
"camera_evidence_current": True,
"occupancy_evidence_current": False,
}
)
row = {
"source_frame_index": frame_index,
"session_seconds": end if frame_index == 4488 else start + frame_index * step,
"fusion_state": "fused",
"objects": objects,
}
handle.write(_canonical(row) + b"\n")
fusion_sha256 = _sha256(fusion)
result = {
"schema_version": "missioncore.e10-integrated-perception-result/v1",
"acceptance_state": "accepted",
"identity": {
"input_sha256": "4" * 64,
"source_id": "sensor.camera.right",
"selection": {
"frame_count": 4489,
"timeline_start_seconds": start,
"timeline_end_seconds": end,
},
"configuration": {
"source_session_id": "20260720T065719Z_viewer_live",
"benchmark": {
"events": [
{
"id": "dynamic-person-window",
"kind": "target-motion",
"class_group": "person",
"window_seconds": [54.0, 62.0],
"target_source_track_ids": [83],
}
]
},
},
},
"artifacts": [
{
"path": fusion.name,
"byte_length": fusion.stat().st_size,
"sha256": fusion_sha256,
}
],
}
result_path = root / "result.json"
result_path.write_bytes(_canonical(result) + b"\n")
return root, _sha256(result_path), fusion_sha256
def test_e46c_video_overlay_projects_all_frames_without_paths(tmp_path: Path) -> None:
root, result_sha256, fusion_sha256 = _source(tmp_path)
result_id = f"e46c-full-replay-world-tracks-{'a' * 64}"
overlay = _cached_video_overlay(
result_id,
str(root),
result_sha256,
fusion_sha256,
)
assert overlay["result_id"] == result_id
assert overlay["frame_count"] == 4489
frames = overlay["frames"]
assert isinstance(frames, list)
assert frames[20]["objects"][0]["route_track_id"] == 83
assert overlay["review_windows"][0]["target_source_track_ids"] == [83]
assert "/" not in json.dumps(overlay["recorded_source"])
def test_e46c_video_overlay_rejects_a_replaced_fusion_artifact(tmp_path: Path) -> None:
root, result_sha256, fusion_sha256 = _source(tmp_path)
with pytest.raises(ValueError, match="identity changed"):
_cached_video_overlay(
f"e46c-full-replay-world-tracks-{'b' * 64}",
str(root),
result_sha256,
"0" * 64 if fusion_sha256 != "0" * 64 else "f" * 64,
)
+90
View File
@@ -0,0 +1,90 @@
from __future__ import annotations
from pathlib import Path
from fastapi import FastAPI
from fastapi.testclient import TestClient
from k1link.web import e46e_ready_stack_api
def test_e46e_catalog_and_overlay_are_read_only_hash_bound(
tmp_path: Path,
monkeypatch,
) -> None:
result_id = f"e46e-ready-stack-{'a' * 64}"
result_root = tmp_path / result_id
result_root.mkdir()
overlay = result_root / "overlay.mp4"
overlay.write_bytes(b"0123456789abcdef")
frozen = {
"result_id": result_id,
"result_root": result_root,
"overlay_path": overlay,
"manifest": {
"artifacts": [
{
"role": "visual-overlay-video",
"path": "overlay.mp4",
"byte_length": 16,
"sha256": "b" * 64,
}
]
},
"report": {
"created_at_utc": "2026-08-04T09:00:00Z",
"source_session_id": "RAVNOVES00",
"camera_source_id": "sensor.camera.right",
"status": "completed-stock-nvidia-recorded-right-replay",
"metrics": {"frame_count": 4489},
"acceptance": {"full_route_accounted": True},
"decision": {"custom_temporal_logic_used": False},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "complete",
"execution_class": "hybrid",
},
"limitations": ["not truth"],
},
}
monkeypatch.setattr(e46e_ready_stack_api, "read_e46e_ready_stack", lambda _: frozen)
app = FastAPI()
app.include_router(
e46e_ready_stack_api.build_e46e_ready_stack_router(
root_provider=lambda: tmp_path
)
)
client = TestClient(app)
catalog = client.get("/api/v1/laboratory/e46e/results?limit=1")
assert catalog.status_code == 200
item = catalog.json()["items"][0]
assert item["result_id"] == result_id
assert item["video"] == {
"url": f"/api/v1/laboratory/e46e/results/{result_id}/overlay.mp4",
"media_type": "video/mp4",
"byte_length": 16,
"sha256": "b" * 64,
"width": 800,
"height": 600,
}
assert item["ground_truth"] is False
video = client.get(
f"/api/v1/laboratory/e46e/results/{result_id}/overlay.mp4",
headers={"Range": "bytes=4-9"},
)
assert video.status_code == 206
assert video.content == b"456789"
assert video.headers["content-range"] == "bytes 4-9/16"
assert video.headers["etag"] == f'"{"b" * 64}"'
assert video.headers["cache-control"].endswith("immutable")
def test_e46e_catalog_is_empty_when_not_configured() -> None:
app = FastAPI()
app.include_router(e46e_ready_stack_api.build_e46e_ready_stack_router())
response = TestClient(app).get("/api/v1/laboratory/e46e/results")
assert response.status_code == 200
assert response.json()["configured"] is False
assert response.json()["items"] == []
+155
View File
@@ -0,0 +1,155 @@
from __future__ import annotations
from pathlib import Path
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from k1link.web import e46f_dashcam_bakeoff_api
def test_e46f_projects_visual_rejection_against_e46e(tmp_path: Path, monkeypatch) -> None:
result_id = f"e46f-dashcam-bakeoff-{'a' * 64}"
baseline_id = f"e46e-ready-stack-{'b' * 64}"
candidate_root = tmp_path / "candidate"
baseline_root = tmp_path / "baseline"
(candidate_root / result_id).mkdir(parents=True)
(baseline_root / baseline_id).mkdir(parents=True)
overlay = candidate_root / result_id / "overlay.mp4"
overlay.write_bytes(b"0123456789abcdef")
candidate = _frozen(
result_id=result_id,
result_root=candidate_root / result_id,
overlay=overlay,
baseline_id=baseline_id,
metrics=_metrics(zero_tracks=25, blackouts=1, unique_tracks=545, short_fraction=0.06789),
objects=[_large_object("person", 17)],
)
baseline = {
"report": {
"metrics": _metrics(
zero_tracks=28,
blackouts=2,
unique_tracks=909,
short_fraction=0.093509,
)
},
"frames": ({"frame_index": 0, "objects": []},),
}
monkeypatch.setattr(
e46f_dashcam_bakeoff_api,
"read_e46f_dashcam_bakeoff",
lambda _: candidate,
)
monkeypatch.setattr(
e46f_dashcam_bakeoff_api,
"read_e46e_ready_stack",
lambda _: baseline,
)
app = FastAPI()
app.include_router(
e46f_dashcam_bakeoff_api.build_e46f_dashcam_bakeoff_router(
root_provider=lambda: candidate_root,
e46e_root_provider=lambda: baseline_root,
)
)
client = TestClient(app)
response = client.get("/api/v1/laboratory/e46f/results?limit=1")
assert response.status_code == 200
item = response.json()["items"][0]
delta = item["comparison"]["delta"]
assert delta["zero_track_frame_count"] == -3
assert delta["full_layer_blackout_event_count"] == -1
assert delta["unique_track_count"] == -364
assert delta["short_track_fraction"] == pytest.approx(-0.025619)
assert item["comparison"]["large_box_visual_triage"]["candidate"] == {
"observation_count": 1,
"frame_count": 1,
"track_id_count": 1,
"class_observations": {"person": 1},
}
assert item["comparison"]["verdict"] == ("reject-dashcamnet-on-unrectified-fisheye")
assert item["ground_truth"] is False
video = client.get(
f"/api/v1/laboratory/e46f/results/{result_id}/overlay.mp4",
headers={"Range": "bytes=4-9"},
)
assert video.status_code == 206
assert video.content == b"456789"
assert video.headers["etag"] == f'"{"c" * 64}"'
assert video.headers["cache-control"].endswith("immutable")
def test_e46f_catalog_is_empty_when_not_configured() -> None:
app = FastAPI()
app.include_router(e46f_dashcam_bakeoff_api.build_e46f_dashcam_bakeoff_router())
response = TestClient(app).get("/api/v1/laboratory/e46f/results")
assert response.status_code == 200
assert response.json()["configured"] is False
assert response.json()["items"] == []
def _metrics(
*, zero_tracks: int, blackouts: int, unique_tracks: int, short_fraction: float
) -> dict[str, int | float]:
return {
"frame_count": 4489,
"zero_track_frame_count": zero_tracks,
"full_layer_blackout_event_count": blackouts,
"unique_track_count": unique_tracks,
"short_track_fraction": short_fraction,
}
def _large_object(label: str, track_id: int) -> dict[str, object]:
return {
"bbox": [0.0, 0.0, 400.0, 300.0],
"source_track_id": track_id,
"class_name": label,
}
def _frozen(
*,
result_id: str,
result_root: Path,
overlay: Path,
baseline_id: str,
metrics: dict[str, int | float],
objects: list[dict[str, object]],
) -> dict[str, object]:
return {
"result_id": result_id,
"result_root": result_root,
"overlay_path": overlay,
"manifest": {
"artifacts": [
{
"role": "visual-overlay-video",
"path": "overlay.mp4",
"byte_length": 16,
"sha256": "c" * 64,
}
]
},
"report": {
"created_at_utc": "2026-08-04T09:00:00Z",
"source_session_id": "RAVNOVES00",
"camera_source_id": "sensor.camera.right",
"status": "completed-stock-nvidia-detector-only-bakeoff",
"comparison_contract": {"baseline_result_id": baseline_id},
"metrics": metrics,
"acceptance": {"full_route_accounted": True},
"decision": {"custom_temporal_logic_used": False},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "complete",
"execution_class": "hybrid",
},
"limitations": ["not truth"],
},
"frames": ({"frame_index": 0, "objects": objects},),
}
@@ -0,0 +1,130 @@
from __future__ import annotations
from pathlib import Path
from fastapi import FastAPI
from fastapi.testclient import TestClient
from k1link.web import e46g_rectified_detector_bakeoff_api
def test_e46g_projects_visual_front_only_selection(tmp_path: Path, monkeypatch) -> None:
result_id = f"e46g-rectified-detector-bakeoff-{'a' * 64}"
root = tmp_path / "results"
result_root = root / result_id
result_root.mkdir(parents=True)
traffic = result_root / "trafficcamnet.mp4"
dash = result_root / "dashcamnet.mp4"
traffic.write_bytes(b"traffic-comparison")
dash.write_bytes(b"dash-comparison")
frozen = _frozen(result_id, result_root, traffic, dash)
monkeypatch.setattr(
e46g_rectified_detector_bakeoff_api,
"read_e46g_rectified_detector_bakeoff",
lambda _: frozen,
)
app = FastAPI()
app.include_router(
e46g_rectified_detector_bakeoff_api.build_e46g_rectified_detector_bakeoff_router(
root_provider=lambda: root
)
)
client = TestClient(app)
response = client.get("/api/v1/laboratory/e46g/results?limit=1")
assert response.status_code == 200
item = response.json()["items"][0]
review = item["comparison"]["visual_review"]
assert review["selected_candidate"] == "trafficcamnet"
assert review["selected_view"] == "front"
assert review["excluded_views"] == ["left", "right"]
assert item["comparison"]["verdict"] == "select-trafficcamnet-front-only-for-e46h"
assert item["ground_truth"] is False
assert item["authority"]["navigation_or_safety_accepted"] is False
assert item["videos"]["trafficcamnet"]["view_order"] == ["left", "front", "right"]
video = client.get(
f"/api/v1/laboratory/e46g/results/{result_id}/trafficcamnet.mp4",
headers={"Range": "bytes=2-8"},
)
assert video.status_code == 206
assert video.content == b"affic-c"
assert video.headers["etag"] == f'"{"b" * 64}"'
assert video.headers["cache-control"].endswith("immutable")
def test_e46g_catalog_is_empty_when_not_configured() -> None:
app = FastAPI()
app.include_router(
e46g_rectified_detector_bakeoff_api.build_e46g_rectified_detector_bakeoff_router()
)
response = TestClient(app).get("/api/v1/laboratory/e46g/results")
assert response.status_code == 200
assert response.json()["configured"] is False
assert response.json()["items"] == []
def _frozen(
result_id: str,
result_root: Path,
traffic: Path,
dash: Path,
) -> dict[str, object]:
return {
"result_id": result_id,
"result_root": result_root,
"comparison_paths": {"trafficcamnet": traffic, "dashcamnet": dash},
"manifest": {
"artifacts": [
{
"role": "comparison-video-trafficcamnet",
"path": traffic.name,
"byte_length": traffic.stat().st_size,
"sha256": "b" * 64,
},
{
"role": "comparison-video-dashcamnet",
"path": dash.name,
"byte_length": dash.stat().st_size,
"sha256": "c" * 64,
},
]
},
"report": {
"created_at_utc": "2026-08-04T13:28:23.707Z",
"source_session_id": "20260720T065719Z_viewer_live",
"camera_source_id": "sensor.camera.right",
"selection": {
"first_source_frame_index": 1000,
"last_source_frame_index": 1599,
"frame_count": 600,
},
"rectification": {
"provider": "NVIDIA Gst-nvdewarper",
"output_resolution": [960, 544],
"view_order": ["left", "front", "right"],
},
"metrics": {
"trafficcamnet": {"views": {"front": {"zero_track_frame_count": 0}}},
"dashcamnet": {"views": {"front": {"zero_track_frame_count": 34}}},
},
"acceptance": {"official_nvidia_dewarper_executed": True},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "complete",
"execution_class": "hybrid",
"pipeline_id": "e46g-test/v1",
"components": [],
},
"limitations": ["not truth"],
"authority": {
"ground_truth": False,
"independent_truth": False,
"metric_grade_reference": False,
"candidate_accepted": False,
"free_space_authority": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
},
}
@@ -0,0 +1,130 @@
from __future__ import annotations
from pathlib import Path
from fastapi import FastAPI
from fastapi.testclient import TestClient
from k1link.web import e46h_full_rectified_front_replay_api
def test_e46h_projects_full_video_and_visual_exception_windows(
tmp_path: Path,
monkeypatch,
) -> None:
result_id = f"e46h-full-rectified-front-replay-{'a' * 64}"
root = tmp_path / "results"
result_root = root / result_id
result_root.mkdir(parents=True)
overlay = result_root / "overlay.mp4"
overlay.write_bytes(b"0123456789abcdef")
frozen = _frozen(result_id, result_root, overlay)
monkeypatch.setattr(
e46h_full_rectified_front_replay_api,
"read_e46h_full_rectified_front_replay",
lambda _: frozen,
)
app = FastAPI()
app.include_router(
e46h_full_rectified_front_replay_api.build_e46h_full_rectified_front_replay_router(
root_provider=lambda: root
)
)
client = TestClient(app)
response = client.get("/api/v1/laboratory/e46h/results?limit=1")
assert response.status_code == 200
item = response.json()["items"][0]
assert item["selection"]["frame_count"] == 4488
assert item["rectification"]["view"] == "front"
assert (
item["visual_review"]["status"]
== "full-continuous-and-targeted-review-completed"
)
assert item["visual_review"]["complete_video_reviewed"] is True
assert item["visual_review"]["reviewed_video_range_seconds"] == [0.0, 448.8]
assert len(item["visual_review"]["review_windows"]) == 6
assert sum(
row["verdict"] == "semantic-false-positive"
for row in item["visual_review"]["review_windows"]
) == 5
assert item["ground_truth"] is False
assert item["authority"]["candidate_accepted"] is False
video = client.get(
f"/api/v1/laboratory/e46h/results/{result_id}/overlay.mp4",
headers={"Range": "bytes=4-9"},
)
assert video.status_code == 206
assert video.content == b"456789"
assert video.headers["etag"] == f'"{"b" * 64}"'
assert video.headers["cache-control"].endswith("immutable")
def test_e46h_catalog_is_empty_when_not_configured() -> None:
app = FastAPI()
app.include_router(
e46h_full_rectified_front_replay_api.build_e46h_full_rectified_front_replay_router()
)
response = TestClient(app).get("/api/v1/laboratory/e46h/results")
assert response.status_code == 200
assert response.json()["configured"] is False
assert response.json()["items"] == []
def _frozen(result_id: str, result_root: Path, overlay: Path) -> dict[str, object]:
return {
"result_id": result_id,
"result_root": result_root,
"overlay_path": overlay,
"manifest": {
"artifacts": [
{
"role": "visual-overlay-video",
"path": overlay.name,
"byte_length": overlay.stat().st_size,
"sha256": "b" * 64,
}
]
},
"report": {
"created_at_utc": "2026-08-04T14:17:42.899Z",
"source_session_id": "20260720T065719Z_viewer_live",
"camera_source_id": "sensor.camera.right",
"baseline_result_id": f"e46g-rectified-detector-bakeoff-{'c' * 64}",
"selection": {
"first_source_frame_index": 0,
"last_source_frame_index": 4487,
"frame_count": 4488,
"excluded_source_tail_frame_count": 1,
},
"rectification": {
"provider": "NVIDIA Gst-nvdewarper",
"provider_version": "DeepStream 9.1",
"projection": "fisheye-to-perspective",
"view": "front",
"output_resolution": [960, 544],
"horizontal_fov_degrees": 100,
},
"metrics": {"frame_count": 4488},
"acceptance": {"candidate_accepted": False},
"decision": {"provider_promoted": False},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "complete",
"execution_class": "hybrid",
"pipeline_id": "e46h-test/v1",
"components": [],
},
"limitations": ["not truth"],
"authority": {
"ground_truth": False,
"independent_truth": False,
"metric_grade_reference": False,
"candidate_accepted": False,
"free_space_authority": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
},
}
@@ -0,0 +1,146 @@
from __future__ import annotations
from pathlib import Path
from fastapi import FastAPI
from fastapi.testclient import TestClient
from k1link.web import e46i_grounding_dino_full_replay_api
def test_e46i_projects_full_video_and_visual_comparison(
tmp_path: Path,
monkeypatch,
) -> None:
result_id = f"e46i-grounding-dino-full-replay-{'a' * 64}"
root = tmp_path / "results"
result_root = root / result_id
result_root.mkdir(parents=True)
paths = {
"overlay_path": result_root / "overlay.mp4",
"shadow_sheet_path": result_root / "shadow.png",
"route_sheet_path": result_root / "route.png",
"targeted_sheet_path": result_root / "targeted.png",
}
for index, path in enumerate(paths.values(), 1):
path.write_bytes(bytes(range(index, index + 16)))
frozen = _frozen(result_id, result_root, paths)
monkeypatch.setattr(
e46i_grounding_dino_full_replay_api,
"read_e46i_grounding_dino_full_replay",
lambda _: frozen,
)
app = FastAPI()
app.include_router(
e46i_grounding_dino_full_replay_api.build_e46i_grounding_dino_full_replay_router(
root_provider=lambda: root
)
)
client = TestClient(app)
response = client.get("/api/v1/laboratory/e46i/results?limit=1")
assert response.status_code == 200
item = response.json()["items"][0]
assert item["status"] == "semantic-regression-suppressed-awaiting-temporal-layer"
assert item["source"]["video_frame_count"] == 4488
assert item["shadow_gate"]["legacy_large_false_background_cases_suppressed"] == 5
assert item["visual_review"]["complete_video_playback_completed"] is True
assert len(item["visual_review"]["review_windows"]) == 6
assert item["video"]["duration_seconds"] == 448.8
assert set(item["visuals"]) == {"shadow_gate", "full_route", "targeted_windows"}
assert item["ground_truth"] is False
assert item["authority"]["candidate_accepted"] is False
video = client.get(
f"/api/v1/laboratory/e46i/results/{result_id}/overlay.mp4",
headers={"Range": "bytes=4-9"},
)
assert video.status_code == 206
assert video.content == bytes(range(5, 11))
assert video.headers["cache-control"].endswith("immutable")
visual = client.get(
f"/api/v1/laboratory/e46i/results/{result_id}/visual/targeted-windows.png"
)
assert visual.status_code == 200
assert visual.headers["content-type"] == "image/png"
def test_e46i_catalog_is_empty_when_not_configured() -> None:
app = FastAPI()
app.include_router(
e46i_grounding_dino_full_replay_api.build_e46i_grounding_dino_full_replay_router()
)
response = TestClient(app).get("/api/v1/laboratory/e46i/results")
assert response.status_code == 200
assert response.json()["configured"] is False
assert response.json()["items"] == []
def _frozen(
result_id: str,
result_root: Path,
paths: dict[str, Path],
) -> dict[str, object]:
roles = {
"overlay_path": "visual-overlay-video",
"shadow_sheet_path": "shadow-gate-contact-sheet",
"route_sheet_path": "full-route-contact-sheet",
"targeted_sheet_path": "targeted-windows-contact-sheet",
}
artifacts = [
{
"role": role,
"path": paths[key].name,
"byte_length": paths[key].stat().st_size,
"sha256": f"{index:x}" * 64,
}
for index, (key, role) in enumerate(roles.items(), 1)
]
return {
"result_id": result_id,
"result_root": result_root,
**paths,
"manifest": {"artifacts": artifacts},
"report": {
"created_at_utc": "2026-08-04T16:10:00.000Z",
"status": "semantic-regression-suppressed-awaiting-temporal-layer",
"baseline_result_id": f"e46h-full-rectified-front-replay-{'b' * 64}",
"source": {
"camera_source_id": "sensor.camera.right",
"session_id": "20260720T065719Z_viewer_live",
"view": "front",
"projection_resolution": [960, 544],
"video_frame_count": 4488,
"video_frame_rate": 10.0,
"video_duration_seconds": 448.8,
},
"provider": {"name": "NVIDIA Grounding DINO"},
"inference": {"confidence_threshold": 0.5},
"metrics": {"frame_count": 4488},
"shadow_gate": {
"legacy_large_false_background_cases_suppressed": 5,
},
"visual_review": {
"complete_video_playback_completed": True,
"review_windows": [{"id": str(index)} for index in range(6)],
},
"acceptance": {"candidate_accepted": False},
"decision": {"provider_promoted": False},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "complete",
"execution_class": "hybrid",
"pipeline_id": "e46i-test/v1",
"components": [],
},
"limitations": ["not truth"],
"authority": {
"ground_truth": False,
"independent_truth": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
},
}
+149
View File
@@ -0,0 +1,149 @@
from __future__ import annotations
from pathlib import Path
from fastapi import FastAPI
from fastapi.testclient import TestClient
from k1link.web import e46j_raw_fisheye_realtime_api
def test_e46j_projects_full_raw_video_and_known_shadow_exception(
tmp_path: Path,
monkeypatch,
) -> None:
result_id = f"e46j-raw-fisheye-realtime-{'a' * 64}"
root = tmp_path / "results"
result_root = root / result_id
result_root.mkdir(parents=True)
paths = {
"overlay_path": result_root / "overlay.mp4",
"route_sheet_path": result_root / "route.png",
"targeted_sheet_path": result_root / "targeted.png",
"shadow_sheet_path": result_root / "shadow.png",
}
for index, path in enumerate(paths.values(), 1):
path.write_bytes(bytes(range(index, index + 16)))
frozen = _frozen(result_id, result_root, paths)
monkeypatch.setattr(
e46j_raw_fisheye_realtime_api,
"read_e46j_raw_fisheye_realtime",
lambda _: frozen,
)
app = FastAPI()
app.include_router(
e46j_raw_fisheye_realtime_api.build_e46j_raw_fisheye_realtime_router(
root_provider=lambda: root
)
)
client = TestClient(app)
response = client.get("/api/v1/laboratory/e46j/results?limit=1")
assert response.status_code == 200
item = response.json()["items"][0]
assert item["status"] == "realtime-capacity-passed-awaiting-temporal-layer"
assert item["source"]["resolution"] == [800, 600]
assert item["metrics"]["core_capacity_fps"] == 47.84049
assert item["metrics"]["operator_shadow_person_frame_count"] == 35
assert item["video"]["frame_count"] == 4489
assert item["video"]["duration_seconds"] == 448.723
assert set(item["visuals"]) == {
"full_route",
"targeted_windows",
"operator_shadow",
}
assert item["ground_truth"] is False
assert item["authority"]["provider_promoted"] is False
video = client.get(
f"/api/v1/laboratory/e46j/results/{result_id}/overlay.mp4",
headers={"Range": "bytes=4-9"},
)
assert video.status_code == 206
assert video.content == bytes(range(5, 11))
assert video.headers["cache-control"].endswith("immutable")
visual = client.get(
f"/api/v1/laboratory/e46j/results/{result_id}/visual/operator-shadow.png"
)
assert visual.status_code == 200
assert visual.headers["content-type"] == "image/png"
def test_e46j_catalog_is_empty_when_not_configured() -> None:
app = FastAPI()
app.include_router(
e46j_raw_fisheye_realtime_api.build_e46j_raw_fisheye_realtime_router()
)
response = TestClient(app).get("/api/v1/laboratory/e46j/results")
assert response.status_code == 200
assert response.json()["configured"] is False
assert response.json()["items"] == []
def _frozen(
result_id: str,
result_root: Path,
paths: dict[str, Path],
) -> dict[str, object]:
roles = {
"overlay_path": "visual-overlay-video",
"route_sheet_path": "full-route-contact-sheet",
"targeted_sheet_path": "targeted-windows-contact-sheet",
"shadow_sheet_path": "operator-shadow-contact-sheet",
}
artifacts = [
{
"role": role,
"path": paths[key].name,
"byte_length": paths[key].stat().st_size,
"sha256": f"{index:x}" * 64,
}
for index, (key, role) in enumerate(roles.items(), 1)
]
authority = {
"ground_truth": False,
"provider_promoted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
return {
"result_id": result_id,
"result_root": result_root,
**paths,
"manifest": {"artifacts": artifacts},
"report": {
"created_at_utc": "2026-08-04T18:20:00.000Z",
"status": "realtime-capacity-passed-awaiting-temporal-layer",
"source": {
"camera_source_id": "sensor.camera.right",
"session_id": "20260720T065719Z_viewer_live",
"resolution": [800, 600],
"frame_count": 4489,
"frame_rate": 10.003944527024467,
"calibration_model": "KB4",
},
"detector": {"architecture": "YOLOX-S"},
"preprocessing": {"resize": "bilinear-letterbox-top-left"},
"detection": {"minimum_score": 0.5},
"metrics": {
"frame_count": 4489,
"core_capacity_fps": 47.84049,
"operator_shadow_person_frame_count": 35,
},
"visual_review": {
"review_windows": [{"id": str(index)} for index in range(6)],
},
"acceptance": {"ten_hz_capacity_gate_passed": True},
"decision": {"provider_promoted": False},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "complete",
"execution_class": "hybrid",
"pipeline_id": "e46j-test/v1",
"components": [],
},
"limitations": ["not truth"],
"authority": authority,
},
}
@@ -0,0 +1,156 @@
from __future__ import annotations
import hashlib
import json
from pathlib import Path
import pytest
from fastapi import APIRouter
from fastapi.routing import APIRoute
from k1link.compute.l33_camera_first_admission import (
RAVNOVES00_ADMITTED_WORLD_STATE_RESULT_ID,
RAVNOVES00_SESSION_ID,
)
from k1link.compute.l33_camera_first_detector_review import (
L33CameraFirstDetectorReviewError,
build_l33_camera_first_detector_review,
)
from k1link.web.l33_camera_first_detector_review_api import (
build_l33_camera_first_detector_review_router,
latest_l33_identity,
)
def _canonical_json(value: object) -> bytes:
return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode(
"utf-8"
)
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def _endpoint(router: APIRouter, path: str) -> object:
for route in router.routes:
if (
isinstance(route, APIRoute)
and route.path == path
and route.methods is not None
and "GET" in route.methods
):
return route.endpoint
raise AssertionError(f"GET {path} route is missing")
def _write_candidate(
root: Path,
*,
world_state_result_id: str,
created_at_utc: str,
) -> Path:
identity = {
"schema_version": "missioncore.l33-camera-first-detector-review/v1",
"source_session_id": RAVNOVES00_SESSION_ID,
"source_l32_result_id": f"l32-pointpillars-camera-review-{'1' * 64}",
"source_e26_result_id": f"e10-integrated-perception-{'2' * 64}",
"source_e29_result_id": f"e29-camera-geometry-{'3' * 64}",
"source_e10_pack_id": f"e10-lidar-pack-{'4' * 64}",
"source_world_state_result_id": world_state_result_id,
"detector": {"id": "yolox_s"},
"semantic_contract": {"owner": "camera"},
"geometry_contract": {"owner": "lidar"},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"l33-camera-first-detector-review-{identity_sha256}"
candidate = root / result_id
candidate.mkdir(parents=True)
catalog = {
"schema_version": "missioncore.l33-camera-first-detector-review-catalog/v1",
"result_id": result_id,
"source_session_id": RAVNOVES00_SESSION_ID,
"frame_count": 1,
"frames": [
{
"frame_id": "000001",
"detail_path": "frame-000001.json",
"detail_sha256": "5" * 64,
"detail_byte_length": 1,
"camera_path": "frames/frame-000001.jpg",
"camera_sha256": "6" * 64,
"semantic_provenance": "rectified-detector-current",
}
],
}
catalog_path = candidate / "catalog.json"
catalog_path.write_text(json.dumps(catalog), encoding="utf-8")
manifest = {
"schema_version": "missioncore.l33-camera-first-detector-review/v1",
"result_id": result_id,
"identity": identity,
"identity_sha256": identity_sha256,
"created_at_utc": created_at_utc,
"status": "camera-first-boundary-restored-shadow-only",
"metrics": {},
"catalog": {
"path": "catalog.json",
"sha256": _sha256(catalog_path),
"byte_length": catalog_path.stat().st_size,
},
"limitations": [],
"authority": {
"shadow_only": True,
"accuracy_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
"ground_truth": False,
}
(candidate / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
return candidate
def test_catalog_and_latest_ignore_newer_unadmitted_parent(tmp_path: Path) -> None:
admitted = _write_candidate(
tmp_path,
world_state_result_id=RAVNOVES00_ADMITTED_WORLD_STATE_RESULT_ID,
created_at_utc="2026-07-31T17:23:36.806+00:00",
)
_write_candidate(
tmp_path,
world_state_result_id=f"rectified-camera-world-state-{'b' * 64}",
created_at_utc="2026-07-31T18:19:40.451+00:00",
)
router = build_l33_camera_first_detector_review_router(root_provider=lambda: tmp_path)
catalog = _endpoint(router, "/api/v1/laboratory/l33/camera-first-detector-review/results")(
limit=10
) # type: ignore[operator]
assert catalog["candidate_total"] == 2
assert catalog["invalid_total"] == 1
assert [item["result_id"] for item in catalog["items"]] == [admitted.name]
assert latest_l33_identity(lambda: tmp_path) == {
"result_id": admitted.name,
"created_at_utc": "2026-07-31T17:23:36.806+00:00",
}
def test_builder_rejects_unadmitted_world_state_before_reading_sources(
tmp_path: Path,
) -> None:
wrong_world_state = tmp_path / f"rectified-camera-world-state-{'b' * 64}"
wrong_world_state.mkdir()
with pytest.raises(
L33CameraFirstDetectorReviewError,
match="not admitted for RAVNOVES00",
):
build_l33_camera_first_detector_review(
l32_result_root=tmp_path / "missing-l32",
e26_result_root=tmp_path / "missing-e26",
e29_result_root=tmp_path / "missing-e29",
e10_pack_root=tmp_path / "missing-pack",
output_root=tmp_path / "output",
rectified_world_state_root=wrong_world_state,
)
@@ -0,0 +1,593 @@
from __future__ import annotations
import hashlib
import json
import struct
import zlib
from pathlib import Path
import pytest
from fastapi import APIRouter, HTTPException
from fastapi.routing import APIRoute
from k1link.compute.e46_detector_truth_island import (
E46_CONTRACT_NAME,
E46_MANIFEST_NAME,
E46_REFERENCES_NAME,
E46_REPORT_NAME,
E46_REVIEW_NAME,
)
from k1link.compute.l34_right_yolox_truth_island_freeze import (
L34_MANIFEST_NAME,
L34_PREDICTIONS_NAME,
L34_REPORT_NAME,
)
from k1link.web.advanced_laboratory_api import build_advanced_laboratory_router
from k1link.web.l34_annotation_api import (
L34AnnotationCreateRequest,
L34AnnotationFrameRequest,
L34AnnotationObjectRequest,
L34AnnotationSaveRequest,
build_l34_annotation_router,
)
from k1link.web.l34_right_yolox_truth_island_api import (
build_l34_right_yolox_truth_island_freeze_router,
)
def _canonical_json(value: object) -> bytes:
return json.dumps(
value,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
).encode("utf-8")
def _sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def _endpoint(router: APIRouter, path: str, method: str = "GET") -> object:
for route in router.routes:
if (
isinstance(route, APIRoute)
and route.path == path
and route.methods is not None
and method in route.methods
):
return route.endpoint
raise AssertionError(f"{method} {path} route is missing")
def _write_result(
root: Path,
*,
truth_result_id: str | None = None,
truth_manifest_sha256: str | None = None,
source_image_sha256: str = "6" * 64,
) -> Path:
identity = {
"schema_version": "missioncore.l34-right-yolox-truth-island-freeze/v1",
"profile": {
"profile_id": "RAVNOVES00_RIGHT_YOLOX_TRUTH_ISLAND_V1",
"candidate": {
"architecture": "YOLOX-S",
"model_sha256": "1" * 64,
"minimum_score": 0.25,
},
},
"source": {
"session_id": "20260720T065719Z_viewer_live",
"source_id": "sensor.camera.right",
"mode": "recorded-replay-only",
},
"truth_island": {
"result_id": truth_result_id
or f"e46-detector-truth-island-{'2' * 64}",
"manifest_sha256": truth_manifest_sha256 or "4" * 64,
"truth_state": "labels-unavailable",
},
"candidate": {
"l33_result_id": f"l33-camera-first-detector-review-{'3' * 64}",
"prediction_rows_sha256": "5" * 64,
},
"authority": {
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"l34-right-yolox-truth-island-freeze-{identity_sha256}"
candidate = root / result_id
candidate.mkdir(parents=True)
report = {
"schema_version": "missioncore.l34-right-yolox-truth-island-report/v1",
"result_id": result_id,
"identity_sha256": identity_sha256,
"status": "predictions-frozen-awaiting-independent-truth",
"profile_id": "RAVNOVES00_RIGHT_YOLOX_TRUTH_ISLAND_V1",
"pipeline_id": "kb4-core3-yolox-eomt-k1-lidar-e23-temporal/v1",
"source_session_id": "20260720T065719Z_viewer_live",
"camera_source_id": "sensor.camera.right",
"metrics": {
"frame_count": 1,
"temporal_group_count": 1,
"prediction_count": 1,
"frames_with_predictions": 1,
"class_counts": {"car": 1},
"accuracy_metrics_available": False,
},
"decision": {
"candidate_predictions_frozen": True,
"truth_labels_read": False,
"candidate_accepted": False,
"model_retraining_authorized": False,
"next_gate": "independent truth",
},
"limitations": ["recorded right camera only"],
"authority": identity["authority"],
"access": "read-only",
}
prediction = {
"schema_version": "missioncore.l34-right-yolox-truth-island-prediction/v1",
"candidate_id": "yolox-s-kb4-core3",
"truth_island_sequence": 1,
"image_id": 1,
"frame_index": 1,
"session_seconds": 1.25,
"source_image_sha256": source_image_sha256,
"group_id": "anchor-test",
"predictions": [
{
"label": "car",
"score": 0.9,
"bbox_xyxy": [1.0, 1.0, 6.0, 5.0],
}
],
"truth_joined": False,
}
report_path = candidate / L34_REPORT_NAME
prediction_path = candidate / L34_PREDICTIONS_NAME
report_path.write_text(json.dumps(report), encoding="utf-8")
prediction_path.write_text(json.dumps(prediction) + "\n", encoding="utf-8")
manifest = {
"schema_version": "missioncore.l34-right-yolox-truth-island-freeze/v1",
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"created_at_utc": "2026-08-01T00:30:00Z",
"ground_truth": False,
"artifacts": [
{
"path": L34_REPORT_NAME,
"byte_length": report_path.stat().st_size,
"sha256": _sha256(report_path),
},
{
"path": L34_PREDICTIONS_NAME,
"byte_length": prediction_path.stat().st_size,
"sha256": _sha256(prediction_path),
},
],
"authority": identity["authority"],
}
(candidate / L34_MANIFEST_NAME).write_text(
json.dumps(manifest),
encoding="utf-8",
)
return candidate
def _png(width: int, height: int) -> bytes:
signature = b"\x89PNG\r\n\x1a\n"
def chunk(kind: bytes, payload: bytes) -> bytes:
return (
struct.pack(">I", len(payload))
+ kind
+ payload
+ struct.pack(">I", zlib.crc32(kind + payload) & 0xFFFFFFFF)
)
pixels = b"".join(b"\x00" + b"\x20\x40\x60" * width for _ in range(height))
return (
signature
+ chunk(b"IHDR", struct.pack(">IIBBBBB", width, height, 8, 2, 0, 0, 0))
+ chunk(b"IDAT", zlib.compress(pixels))
+ chunk(b"IEND", b"")
)
def _write_visual_sources(root: Path) -> tuple[Path, Path, Path]:
pack_id = f"evaluation-pack-{'a' * 64}"
pack_root = root / "packs"
image_path = pack_root / pack_id / "images" / "valid-fov-fill" / "frame.png"
image_path.parent.mkdir(parents=True)
image_path.write_bytes(_png(8, 6))
reference = {
"schema_version": "missioncore.e46-truth-island-image-reference/v1",
"truth_island_sequence": 1,
"image_id": 1,
"frame_index": 1,
"group_id": "anchor-test",
"role": "anchor",
"session_seconds": 1.25,
"source_path": "images/valid-fov-fill/frame.png",
"byte_length": image_path.stat().st_size,
"sha256": _sha256(image_path),
}
truth_parent = root / "truth"
truth_parent.mkdir()
identity = {
"source": {
"evaluation_pack_id": pack_id,
"source_id": "sensor.camera.right",
},
"authority": {
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
truth_id = f"e46-detector-truth-island-{identity_sha256}"
truth_root = truth_parent / truth_id
truth_root.mkdir()
documents = {
E46_REPORT_NAME: {
"schema_version": "missioncore.e46-truth-island-preparation-report/v1",
"result_id": truth_id,
"identity_sha256": identity_sha256,
"blindness": {
"candidate_comparison_authorized": False,
"model_prelabels_included": False,
"predictions_included": False,
"truth_labels_available": False,
},
"selection": {"frame_count": 1},
},
E46_REFERENCES_NAME: None,
E46_CONTRACT_NAME: {
"schema_version": "missioncore.e46-detector-blind-contract/v1",
"truth_state": "labels-unavailable",
"reviewer_package": {
"model_prelabels_included": False,
"model_predictions_included": False,
},
},
E46_REVIEW_NAME: {
"schema_version": "missioncore.e46-detector-review-template/v1",
"state": "prepared-unreviewed-no-prelabels",
"images": [],
},
}
for name, document in documents.items():
path = truth_root / name
if name == E46_REFERENCES_NAME:
path.write_text(json.dumps(reference) + "\n", encoding="utf-8")
else:
path.write_text(json.dumps(document), encoding="utf-8")
authority = identity["authority"]
manifest = {
"schema_version": "missioncore.e46-detector-truth-island/v1",
"result_id": truth_id,
"identity_sha256": identity_sha256,
"identity": identity,
"acceptance_state": "prepared-not-truth",
"artifacts": [
{
"path": name,
"byte_length": (truth_root / name).stat().st_size,
"sha256": _sha256(truth_root / name),
}
for name in documents
],
"authority": authority,
}
manifest_path = truth_root / E46_MANIFEST_NAME
manifest_path.write_text(json.dumps(manifest), encoding="utf-8")
result_root = root / "results"
result_root.mkdir()
result = _write_result(
result_root,
truth_result_id=truth_id,
truth_manifest_sha256=_sha256(manifest_path),
source_image_sha256=_sha256(image_path),
)
return result, truth_parent, pack_root
def test_l34_catalog_is_path_free_and_truth_closed(tmp_path: Path) -> None:
result = _write_result(tmp_path)
router = build_l34_right_yolox_truth_island_freeze_router(
root_provider=lambda: tmp_path,
)
catalog = _endpoint(router, "/api/v1/laboratory/l34/results")(
limit=1
) # type: ignore[operator]
item = catalog["items"][0]
assert item["result_id"] == result.name
assert item["camera_source_id"] == "sensor.camera.right"
assert item["metrics"]["accuracy_metrics_available"] is False
assert item["decision"]["truth_labels_read"] is False
assert item["frames"] == [
{
"truth_island_sequence": 1,
"image_id": 1,
"frame_index": 1,
"group_id": "anchor-test",
"prediction_count": 1,
"maximum_score": 0.9,
}
]
assert "result_root" not in json.dumps(item)
def test_l34_visual_frame_is_hash_bound_and_path_free(tmp_path: Path) -> None:
result, truth_root, pack_root = _write_visual_sources(tmp_path)
router = build_l34_right_yolox_truth_island_freeze_router(
root_provider=lambda: result.parent,
truth_root_provider=lambda: truth_root,
evaluation_pack_root_provider=lambda: pack_root,
)
frame = _endpoint(
router,
"/api/v1/laboratory/l34/results/{result_id}/frames/{sequence}",
)(result_id=result.name, sequence=1) # type: ignore[operator]
assert frame["camera"]["width"] == 8
assert frame["camera"]["height"] == 6
assert frame["predictions"][0]["bbox_xyxy"] == [1.0, 1.0, 6.0, 5.0]
assert frame["truth_labels_read"] is False
assert "source_path" not in json.dumps(frame)
image_path = next(pack_root.rglob("frame.png"))
image_path.write_bytes(image_path.read_bytes() + b"changed")
with pytest.raises(HTTPException) as caught:
_endpoint(
router,
"/api/v1/laboratory/l34/results/{result_id}/frames/{sequence}",
)(result_id=result.name, sequence=1) # type: ignore[operator]
assert caught.value.status_code == 404
def test_l34_annotation_source_is_prediction_free(tmp_path: Path) -> None:
result, truth_root, pack_root = _write_visual_sources(tmp_path)
router = build_l34_annotation_router(
root_provider=lambda: result.parent,
truth_root_provider=lambda: truth_root,
evaluation_pack_root_provider=lambda: pack_root,
annotation_root_provider=lambda: tmp_path / "annotations",
)
catalog = _endpoint(
router,
"/api/v1/laboratory/l34/results/{result_id}/annotation-source",
)(result_id=result.name) # type: ignore[operator]
frame = _endpoint(
router,
(
"/api/v1/laboratory/l34/results/{result_id}"
"/annotation-source/frames/{sequence}"
),
)(result_id=result.name, sequence=1) # type: ignore[operator]
seed = _endpoint(
router,
(
"/api/v1/laboratory/l34/results/{result_id}"
"/annotation-seed/frames/{sequence}"
),
)(result_id=result.name, sequence=1) # type: ignore[operator]
serialized = json.dumps({"catalog": catalog, "frame": frame})
assert catalog["frame_count"] == 1
assert catalog["contract"]["classes"] == [
"person",
"bicycle",
"motorcycle",
"car",
"heavy_vehicle",
"static_obstacle",
"animal",
]
assert catalog["contract"]["unmapped_class"] == {
"value": "unmapped",
"proposed_label_required": True,
"normalization_state": "pending-adjudication",
}
assert frame["camera"]["width"] == 8
assert frame["camera_url"].endswith("/annotation-source/frames/1/camera")
assert frame["model_material_included"] is False
for forbidden in ("predictions", "prediction_rows", "candidate", "score"):
assert forbidden not in serialized
assert seed == {
"schema_version": "missioncore.l34-annotation-seed/v1",
"result_id": result.name,
"truth_island_sequence": 1,
"source_sha256": _sha256(next(pack_root.rglob("frame.png"))),
"objects": [
{
"object_id": "seed-1-1",
"category": "car",
"proposed_label": None,
"origin": "frozen_candidate_seed",
"box_xyxy": [1.0, 1.0, 6.0, 5.0],
"occluded": False,
"truncated": False,
}
],
"assistance": {
"mode": "frozen-candidate-seeded",
"independent_truth_eligible": False,
},
"model_material_included": True,
"access": "assisted-annotation-seed-read-only",
}
assert "score" not in json.dumps(seed)
def test_l34_annotation_sessions_are_revisioned_and_not_truth(
tmp_path: Path,
) -> None:
result, truth_root, pack_root = _write_visual_sources(tmp_path)
annotation_root = tmp_path / "annotations"
router = build_l34_annotation_router(
root_provider=lambda: result.parent,
truth_root_provider=lambda: truth_root,
evaluation_pack_root_provider=lambda: pack_root,
annotation_root_provider=lambda: annotation_root,
)
create = _endpoint(
router,
"/api/v1/laboratory/l34/results/{result_id}/annotation-sessions",
"POST",
)
created = create( # type: ignore[operator]
result_id=result.name,
request=L34AnnotationCreateRequest(idempotency_key="browser-create-1"),
)
repeated = create( # type: ignore[operator]
result_id=result.name,
request=L34AnnotationCreateRequest(idempotency_key="browser-create-1"),
)
assert repeated["session_id"] == created["session_id"]
assert created["title"] == "Разметка · LAB L3.4 · Рецензент 1"
assert created["revision"] == 0
assert created["authority"]["ground_truth"] is False
assert created["assistance"] == {
"mode": "frozen-candidate-seeded",
"independent_truth_eligible": False,
}
save = _endpoint(
router,
(
"/api/v1/laboratory/l34/results/{result_id}"
"/annotation-sessions/{session_id}"
),
"PUT",
)
request = L34AnnotationSaveRequest(
expected_revision=0,
idempotency_key="browser-save-1",
title="Разметка · LAB L3.4 · Рецензент 1",
assistance_mode="frozen-candidate-seeded",
frames=[
L34AnnotationFrameRequest(
truth_island_sequence=1,
reviewed=True,
hard_negative=False,
objects=[
L34AnnotationObjectRequest(
object_id="box-1",
category="car",
origin="frozen_candidate_seed",
box_xyxy=[1.0, 1.0, 6.0, 5.0],
occluded=False,
truncated=True,
),
L34AnnotationObjectRequest(
object_id="box-stroller",
category="unmapped",
proposed_label="Детская коляска",
box_xyxy=[0.0, 0.0, 2.0, 2.0],
occluded=False,
truncated=False,
),
],
)
],
)
saved = save( # type: ignore[operator]
result_id=result.name,
session_id=created["session_id"],
request=request,
)
replayed = save( # type: ignore[operator]
result_id=result.name,
session_id=created["session_id"],
request=request,
)
assert saved["revision"] == 1
assert replayed["revision"] == 1
assert saved["progress"] == {
"reviewed_frame_count": 1,
"frame_count": 32,
"object_count": 2,
"complete": False,
}
assert saved["frames"][0]["source_sha256"] == _sha256(
next(pack_root.rglob("frame.png"))
)
assert saved["frames"][0]["objects"][0]["proposed_label"] is None
assert saved["frames"][0]["objects"][0]["origin"] == "frozen_candidate_seed"
assert saved["frames"][0]["objects"][1]["proposed_label"] == "Детская коляска"
assert saved["contract_id"] == "l34-assisted-candidate-review/v1"
assert saved["blindness"]["model_prelabels_seen"] is True
assert "last_save_idempotency_key" not in json.dumps(saved)
labels = _endpoint(
router,
"/api/v1/laboratory/l34/results/{result_id}/annotation-labels",
)(result_id=result.name) # type: ignore[operator]
assert labels["items"] == [
{
"value": "Детская коляска",
"normalization_state": "pending-adjudication",
}
]
with pytest.raises(HTTPException) as missing_label:
save( # type: ignore[operator]
result_id=result.name,
session_id=created["session_id"],
request=L34AnnotationSaveRequest(
expected_revision=1,
idempotency_key="browser-save-unmapped-without-label",
title=request.title,
frames=[
L34AnnotationFrameRequest(
truth_island_sequence=1,
reviewed=True,
hard_negative=False,
objects=[
L34AnnotationObjectRequest(
object_id="box-unmapped",
category="unmapped",
box_xyxy=[0.0, 0.0, 2.0, 2.0],
occluded=False,
truncated=False,
)
],
)
],
),
)
assert missing_label.value.status_code == 422
with pytest.raises(HTTPException) as caught:
save( # type: ignore[operator]
result_id=result.name,
session_id=created["session_id"],
request=request.model_copy(
update={"idempotency_key": "browser-save-stale"}
),
)
assert caught.value.status_code == 409
def test_advanced_index_includes_l34_by_real_creation_time(tmp_path: Path) -> None:
result = _write_result(tmp_path)
router = build_advanced_laboratory_router(
l34_root_provider=lambda: tmp_path,
)
index = _endpoint(router, "/api/v1/laboratory/advanced-index")()
assert index["items"] == [
{
"work_id": "l34-right-yolox-truth-island-freeze",
"result_id": result.name,
"created_at_utc": "2026-08-01T00:30:00Z",
"access": "read-only",
}
]
+214
View File
@@ -0,0 +1,214 @@
from __future__ import annotations
import json
import struct
from pathlib import Path
from types import SimpleNamespace
import pytest
from fastapi import APIRouter, HTTPException
from fastapi.routing import APIRoute
from k1link.web import l34_annotation_api
from k1link.web.l34_annotation_api import (
L34AnnotationCreateRequest,
L34AnnotationFrameRequest,
L34AnnotationObjectRequest,
L34AnnotationSaveRequest,
build_l34d_blind_annotation_router,
)
def _endpoint(router: APIRouter, path: str, method: str = "GET") -> object:
for route in router.routes:
if (
isinstance(route, APIRoute)
and route.path == path
and route.methods is not None
and method in route.methods
):
return route.endpoint
raise AssertionError(f"{method} {path} route is missing")
def _png_header(width: int, height: int) -> bytes:
return (
b"\x89PNG\r\n\x1a\n" + struct.pack(">I", 13) + b"IHDR" + struct.pack(">II", width, height)
)
def _router(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> tuple[APIRouter, str]:
result_id = f"l34d-cumulative-postprocessing-candidate-{'d' * 64}"
image_path = tmp_path / "clean-source.png"
image_path.write_bytes(_png_header(800, 600))
reference = {
"truth_island_sequence": 1,
"image_id": 15,
"frame_index": 1248,
"group_id": "clip-stroller-person",
"role": "temporal",
"session_seconds": 160.142857292,
"sha256": "a" * 64,
}
case = {
"truth_island_sequence": 1,
"image_id": 15,
"frame_index": 1248,
"group_id": "clip-stroller-person",
"session_seconds": 160.142857292,
"source_image_sha256": "a" * 64,
}
result = {
"result_id": result_id,
"cases": [case],
"manifest": {
"identity": {
"l34_freeze": {
"result_id": f"l34-right-yolox-truth-island-freeze-{'b' * 64}",
}
}
},
}
l34_result = SimpleNamespace(
manifest={
"identity": {
"truth_island": {
"result_id": f"e46-detector-truth-island-{'c' * 64}",
}
}
}
)
def resolve(**kwargs: object):
assert kwargs["result_id"] == result_id
assert kwargs["sequence"] == 1
return result, case, l34_result, reference, image_path
monkeypatch.setattr(l34_annotation_api, "resolve_l34d_case_source", resolve)
router = build_l34d_blind_annotation_router(
annotation_root_provider=lambda: tmp_path / "blind-annotations",
)
return router, result_id
def test_l34d_blind_source_physically_excludes_candidate_material(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
router, result_id = _router(tmp_path, monkeypatch)
catalog = _endpoint(
router,
"/api/v1/laboratory/l34d/results/{result_id}/annotation-source",
)(result_id=result_id) # type: ignore[operator]
frame = _endpoint(
router,
("/api/v1/laboratory/l34d/results/{result_id}/annotation-source/frames/{sequence}"),
)(result_id=result_id, sequence=1) # type: ignore[operator]
assert catalog["contract"]["contract_id"] == ("l34d-prediction-hidden-review/v1")
assert catalog["candidate_predictions_included"] is False
assert catalog["prelabels_included"] is False
assert frame["candidate_predictions_included"] is False
assert frame["prelabels_included"] is False
serialized = json.dumps({"catalog": catalog, "frame": frame})
for forbidden in ("bbox_xyxy", "objects", "score", "origin"):
assert forbidden not in serialized
with pytest.raises(AssertionError):
_endpoint(
router,
("/api/v1/laboratory/l34d/results/{result_id}/annotation-seed/frames/{sequence}"),
)
def test_l34d_blind_session_rejects_seeded_objects(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
router, result_id = _router(tmp_path, monkeypatch)
created = _endpoint(
router,
"/api/v1/laboratory/l34d/results/{result_id}/annotation-sessions",
"POST",
)(
result_id=result_id,
request=L34AnnotationCreateRequest(idempotency_key="blind-create-1"),
) # type: ignore[operator]
assert created["title"] == "Разметка · LAB L3.4D · Рецензент 1"
assert created["contract_id"] == "l34d-prediction-hidden-review/v1"
assert created["assistance"] == {
"mode": "prediction-hidden-manual",
"independent_truth_eligible": False,
}
assert created["blindness"] == {
"candidate_identity_seen": True,
"model_prelabels_seen": False,
"model_predictions_seen": False,
"model_scores_seen": False,
}
save = _endpoint(
router,
("/api/v1/laboratory/l34d/results/{result_id}/annotation-sessions/{session_id}"),
"PUT",
)
saved = save( # type: ignore[operator]
result_id=result_id,
session_id=created["session_id"],
request=L34AnnotationSaveRequest(
expected_revision=0,
idempotency_key="blind-save-1",
title=created["title"],
assistance_mode="prediction-hidden-manual",
frames=[
L34AnnotationFrameRequest(
truth_island_sequence=1,
reviewed=True,
hard_negative=False,
objects=[
L34AnnotationObjectRequest(
object_id="box-stroller",
category="unmapped",
proposed_label="Детская коляска",
origin="manual",
box_xyxy=[40.0, 50.0, 240.0, 320.0],
occluded=False,
truncated=False,
)
],
)
],
),
)
assert saved["revision"] == 1
assert saved["frames"][0]["objects"][0]["origin"] == "manual"
with pytest.raises(HTTPException) as caught:
save( # type: ignore[operator]
result_id=result_id,
session_id=created["session_id"],
request=L34AnnotationSaveRequest(
expected_revision=1,
idempotency_key="blind-save-seed",
title=created["title"],
assistance_mode="prediction-hidden-manual",
frames=[
L34AnnotationFrameRequest(
truth_island_sequence=1,
reviewed=True,
hard_negative=False,
objects=[
L34AnnotationObjectRequest(
object_id="seed-1-1",
category="car",
origin="frozen_candidate_seed",
box_xyxy=[10.0, 10.0, 100.0, 100.0],
occluded=False,
truncated=False,
)
],
)
],
),
)
assert caught.value.status_code == 422
@@ -0,0 +1,123 @@
from __future__ import annotations
from pathlib import Path
from fastapi import APIRouter
from fastapi.routing import APIRoute
from pytest import MonkeyPatch
import k1link.web.l34e_self_review_diagnostic_api as l34e_api
from k1link.web.l34e_self_review_diagnostic_api import (
build_l34e_self_review_diagnostic_router,
)
def _endpoint(router: APIRouter, path: str) -> object:
for route in router.routes:
if (
isinstance(route, APIRoute)
and route.path == path
and route.methods is not None
and "GET" in route.methods
):
return route.endpoint
raise AssertionError(f"GET {path} route is missing")
def test_l34e_catalog_projects_read_only_diagnostic(
tmp_path: Path,
monkeypatch: MonkeyPatch,
) -> None:
digest = "a" * 64
result_id = f"l34e-self-review-diagnostic-{digest}"
candidate = tmp_path / result_id
candidate.mkdir()
(candidate / "manifest.json").write_text("{}", encoding="utf-8")
case = {
"truth_island_sequence": 1,
"image_id": 2,
"frame_index": 70,
"group_id": "anchor-002",
"session_seconds": 10.0,
"source_image_sha256": "b" * 64,
"strict_summary": {"true_positive": 1},
"diagnostic_summary": {
"associated_pair_count": 1,
"prediction_only": 0,
"reference_only": 0,
},
}
result = {
"result_id": result_id,
"report": {
"created_at_utc": "2026-08-03T17:21:06Z",
"status": "completed-self-review-diagnostic-not-truth",
"profile": {"profile_id": "l34e-self-review-diagnostic/v1"},
"method": {
"pipeline_id": "ravnoves00-right-yolox-self-review-diagnostic/v1"
},
"source_session_id": "RAVNOVES00",
"camera_source_id": "sensor.camera.right",
"metrics": {
"reference_quality": "not-metric-grade-self-review"
},
"case_order": list(range(1, 33)),
"decision": {
"candidate_accepted": False,
"detector_retuning_authorized": False,
},
"limitations": ["not independent truth"],
"authority": {
"ground_truth": False,
"candidate_accepted": False,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
},
"cases": tuple(
{
**case,
"truth_island_sequence": sequence,
}
for sequence in range(1, 33)
),
}
def fake_read(path: Path) -> dict[str, object]:
assert path == candidate
return result
monkeypatch.setattr(l34e_api, "read_l34e_self_review_diagnostic", fake_read)
router = build_l34e_self_review_diagnostic_router(
diagnostic_root_provider=lambda: tmp_path,
)
route = _endpoint(router, "/api/v1/laboratory/l34e/results")
catalog = route(limit=1) # type: ignore[operator]
assert catalog["schema_version"] == (
"missioncore.l34e-self-review-diagnostic-catalog/v1"
)
assert catalog["candidate_total"] == 1
assert catalog["invalid_total"] == 0
item = catalog["items"][0]
assert item["result_id"] == result_id
assert item["ground_truth"] is False
assert item["access"] == "read-only"
assert item["metrics"]["reference_quality"] == (
"not-metric-grade-self-review"
)
assert len(item["cases"]) == 32
def test_l34e_catalog_is_empty_when_not_configured() -> None:
router = build_l34e_self_review_diagnostic_router()
route = _endpoint(router, "/api/v1/laboratory/l34e/results")
assert route(limit=1) == { # type: ignore[operator]
"schema_version": "missioncore.l34e-self-review-diagnostic-catalog/v1",
"configured": False,
"items": [],
"candidate_total": 0,
"invalid_total": 0,
"access": "read-only",
}
+240
View File
@@ -0,0 +1,240 @@
from __future__ import annotations
import struct
from pathlib import Path
import pytest
from fastapi import APIRouter, HTTPException
from fastapi.routing import APIRoute
from k1link.web import l34f_adjudication_api
from k1link.web.l34f_adjudication_api import (
L34FCreateRequest,
L34FFrameRequest,
L34FFreezeRequest,
L34FObjectRequest,
L34FSaveRequest,
build_l34f_adjudication_router,
)
def _endpoint(router: APIRouter, path: str, method: str = "GET") -> object:
for route in router.routes:
if (
isinstance(route, APIRoute)
and route.path == path
and route.methods is not None
and method in route.methods
):
return route.endpoint
raise AssertionError(f"{method} {path} route is missing")
def _png_header(width: int, height: int) -> bytes:
return (
b"\x89PNG\r\n\x1a\n" + struct.pack(">I", 13) + b"IHDR" + struct.pack(">II", width, height)
)
def _fixture(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
diagnostic_id = f"l34e-self-review-diagnostic-{'e' * 64}"
diagnostic_root = tmp_path / "diagnostics"
result_root = diagnostic_root / diagnostic_id
result_root.mkdir(parents=True)
image = tmp_path / "frame.png"
image.write_bytes(_png_header(800, 600))
cases = []
for sequence in range(1, 33):
cases.append(
{
"truth_island_sequence": sequence,
"image_id": sequence,
"frame_index": sequence * 10,
"group_id": f"group-{sequence}",
"session_seconds": float(sequence),
"source_image_sha256": "a" * 64,
"predictions": [
{
"prediction_index": 1,
"category": "car",
"score": 0.91,
"box_xyxy": [10.0, 20.0, 100.0, 120.0],
"diagnostic_verdict": "localization_disagreement",
"associated_object_id": f"self-{sequence:02d}-01",
}
],
"references": [
{
"object_id": f"self-{sequence:02d}-01",
"category": "car",
"proposed_label": None,
"box_xyxy": [12.0, 22.0, 102.0, 122.0],
"occluded": False,
"truncated": False,
}
],
"diagnostic_summary": {"severity_score": 1},
}
)
diagnostic = {
"result_id": diagnostic_id,
"result_root": result_root,
"manifest": {
"identity": {"self_review": {"session_id": f"l34-annotation-session-{'b' * 64}"}}
},
"report": {"source_session_id": "RAVNOVES00"},
"cases": tuple(cases),
}
monkeypatch.setattr(
l34f_adjudication_api,
"read_l34e_self_review_diagnostic",
lambda path: diagnostic,
)
def resolve(**kwargs: object):
sequence = int(kwargs["sequence"])
return diagnostic, cases[sequence - 1], image
monkeypatch.setattr(l34f_adjudication_api, "resolve_l34e_case_source", resolve)
router = build_l34f_adjudication_router(
diagnostic_root_provider=lambda: diagnostic_root,
adjudication_root_provider=lambda: tmp_path / "adjudication",
result_root_provider=lambda: tmp_path / "frozen",
)
return router, diagnostic_id, diagnostic
def test_l34f_case_separates_candidate_and_hides_scores(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
router, diagnostic_id, _ = _fixture(tmp_path, monkeypatch)
case = _endpoint(
router,
"/api/v1/laboratory/l34f/diagnostics/{diagnostic_id}/cases/{sequence}",
)(diagnostic_id=diagnostic_id, sequence=1) # type: ignore[operator]
assert case["model_scores_included"] is False
assert case["ground_truth"] is False
assert case["candidate_objects"][0]["category"] == "car"
assert "score" not in case["candidate_objects"][0]
assert "references" not in case
def test_l34f_session_is_revisioned_and_freezes_only_at_32_of_32(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
router, diagnostic_id, diagnostic = _fixture(tmp_path, monkeypatch)
created = _endpoint(
router,
"/api/v1/laboratory/l34f/diagnostics/{diagnostic_id}/sessions",
"POST",
)(
diagnostic_id=diagnostic_id,
request=L34FCreateRequest(idempotency_key="create-l34f-1"),
) # type: ignore[operator]
assert created["revision"] == 0
assert created["progress"]["reviewed_frame_count"] == 0
assert len(created["frames"]) == 32
assert created["frames"][0]["objects"][0]["origin"] == "self_review_seed"
assert created["authority"]["ground_truth"] is False
frames = []
for source in diagnostic["cases"]:
reference = source["references"][0]
frames.append(
L34FFrameRequest(
truth_island_sequence=source["truth_island_sequence"],
reviewed=source["truth_island_sequence"] != 32,
objects=[
L34FObjectRequest(
object_id=reference["object_id"],
category="car",
proposed_label=None,
origin="self_review_seed",
box_xyxy=reference["box_xyxy"],
occluded=False,
truncated=False,
)
],
)
)
save = _endpoint(
router,
"/api/v1/laboratory/l34f/diagnostics/{diagnostic_id}/sessions/{session_id}",
"PUT",
)
saved = save( # type: ignore[operator]
diagnostic_id=diagnostic_id,
session_id=created["session_id"],
request=L34FSaveRequest(
expected_revision=0,
idempotency_key="save-l34f-1",
title=created["title"],
frames=frames,
),
)
assert saved["revision"] == 1
assert saved["progress"]["reviewed_frame_count"] == 31
freeze = _endpoint(
router,
("/api/v1/laboratory/l34f/diagnostics/{diagnostic_id}/sessions/{session_id}/freeze"),
"POST",
)
with pytest.raises(HTTPException) as caught:
freeze( # type: ignore[operator]
diagnostic_id=diagnostic_id,
session_id=created["session_id"],
request=L34FFreezeRequest(expected_revision=1),
)
assert caught.value.status_code == 422
frames[-1].reviewed = True
completed = save( # type: ignore[operator]
diagnostic_id=diagnostic_id,
session_id=created["session_id"],
request=L34FSaveRequest(
expected_revision=1,
idempotency_key="save-l34f-2",
title=created["title"],
frames=frames,
),
)
assert completed["progress"]["complete"] is True
def build(**kwargs: object):
assert Path(kwargs["adjudication_session_path"]).is_file()
return {
"result_id": f"l34f-adjudicated-reference-{'f' * 64}",
"manifest": {
"identity": {
"l34e_diagnostic": {"result_id": diagnostic_id},
"adjudication_session": {"session_id": created["session_id"]},
}
},
"report": {
"created_at_utc": "2026-08-03T00:00:00.000Z",
"status": "completed-candidate-visible-adjudication-not-truth",
"source_session_id": "RAVNOVES00",
"camera_source_id": "sensor.camera.right",
"metrics": {"frame_count": 32},
"decision": {"candidate_accepted": False},
"limitations": [],
"authority": completed["authority"],
},
}
monkeypatch.setattr(
l34f_adjudication_api,
"build_l34f_adjudicated_reference",
build,
)
frozen = freeze( # type: ignore[operator]
diagnostic_id=diagnostic_id,
session_id=created["session_id"],
request=L34FFreezeRequest(expected_revision=2),
)
assert frozen["ground_truth"] is False
assert frozen["decision"]["candidate_accepted"] is False