feat(lab): present chronological perception evidence

This commit is contained in:
DCCONSTRUCTIONS
2026-08-05 07:49:49 +03:00
parent 12c8a2d74c
commit 7a72a206f1
102 changed files with 20122 additions and 222 deletions
@@ -15,10 +15,32 @@ import { fetchE35DegradationRecoveryResult } from "./e35DegradationRecovery";
import { fetchE40ProductGateResult } from "./e40ProductGate";
import { fetchL3PointPillarsVisualAudit } from "./l3PointPillarsVisualAudit";
import { fetchL31PointPillarsRavnoves } from "./l31PointPillarsRavnoves";
import { fetchL32PointPillarsCameraReview } from "./l32PointPillarsCameraReview";
import { fetchL33CameraFirstDetectorReview } from "./l33CameraFirstDetectorReview";
import { fetchL34RightYoloxTruthIsland } from "./l34RightYoloxTruthIsland";
import { fetchL34AAssistedYoloxErrorAudit } from "./l34aAssistedYoloxErrorAudit";
import { fetchL34BNestedBoxConsolidation } from "./l34bNestedBoxConsolidation";
import { fetchL34CTileSeamStitch } from "./l34cTileSeamStitch";
import { fetchL34DCumulativePostprocessing } from "./l34dCumulativePostprocessing";
import { fetchL34ESelfReviewDiagnostic } from "./l34eSelfReviewDiagnostic";
import { fetchL34FFrozenResult } from "./l34fAdjudication";
import { fetchE46BlindReviewResult } from "./e46BlindReview";
import { fetchE46AAiEngineeringPreannotation } from "./e46aAiEngineeringPreannotation";
import { fetchE46BTemporalMotion } from "./e46bTemporalMotion";
import { fetchE46CFullReplayWorldTracks } from "./e46cFullReplayWorldTracks";
import { fetchE46DTemporalFailureAudit } from "./e46dTemporalFailureAudit";
import { fetchE46EReadyStack } from "./e46eReadyStack";
import { fetchE46FDashCamBakeoff } from "./e46fDashCamBakeoff";
import { fetchE46GRectifiedDetectorBakeoff } from "./e46gRectifiedDetectorBakeoff";
import { fetchE46HFullRectifiedFrontReplay } from "./e46hFullRectifiedFrontReplay";
import { fetchE46IGroundingDinoFullReplay } from "./e46iGroundingDinoFullReplay";
import { fetchE46JRawFisheyeRealtime } from "./e46jRawFisheyeRealtime";
export type AdvancedLaboratoryWorkId =
| "l3-pointpillars-visual-audit"
| "l31-pointpillars-ravnoves"
| "l32-pointpillars-camera-review"
| "l33-camera-first-detector-review"
| "e31-source-binding"
| "e32-track-geometry"
| "e33-worker-shadow"
@@ -27,7 +49,25 @@ export type AdvancedLaboratoryWorkId =
| "e37-ravnoves-acceptance"
| "e38-perception-baseline"
| "e39-perception-refinement"
| "e40-perception-product-gate";
| "e40-perception-product-gate"
| "e46-detector-truth-island"
| "e46a-ai-engineering-preannotation"
| "e46b-temporal-motion"
| "e46c-full-replay-world-tracks"
| "e46d-temporal-failure-audit"
| "e46e-ready-stack"
| "e46f-dashcam-bakeoff"
| "e46g-rectified-detector-bakeoff"
| "e46h-full-rectified-front-replay"
| "e46i-grounding-dino-full-replay"
| "e46j-raw-fisheye-realtime"
| "l34-right-yolox-truth-island-freeze"
| "l34a-assisted-yolox-error-audit"
| "l34b-nested-box-consolidation-shadow"
| "l34c-tile-seam-stitch-shadow"
| "l34d-cumulative-postprocessing-candidate"
| "l34e-self-review-diagnostic"
| "l34f-adjudicated-reference";
export interface AdvancedLaboratoryIndexItem {
workId: AdvancedLaboratoryWorkId;
@@ -38,6 +78,8 @@ export interface AdvancedLaboratoryIndexItem {
const WORK_IDS: readonly AdvancedLaboratoryWorkId[] = [
"l3-pointpillars-visual-audit",
"l31-pointpillars-ravnoves",
"l32-pointpillars-camera-review",
"l33-camera-first-detector-review",
"e31-source-binding",
"e32-track-geometry",
"e33-worker-shadow",
@@ -47,11 +89,31 @@ const WORK_IDS: readonly AdvancedLaboratoryWorkId[] = [
"e38-perception-baseline",
"e39-perception-refinement",
"e40-perception-product-gate",
"e46-detector-truth-island",
"e46a-ai-engineering-preannotation",
"e46b-temporal-motion",
"e46c-full-replay-world-tracks",
"e46d-temporal-failure-audit",
"e46e-ready-stack",
"e46f-dashcam-bakeoff",
"e46g-rectified-detector-bakeoff",
"e46h-full-rectified-front-replay",
"e46i-grounding-dino-full-replay",
"e46j-raw-fisheye-realtime",
"l34-right-yolox-truth-island-freeze",
"l34a-assisted-yolox-error-audit",
"l34b-nested-box-consolidation-shadow",
"l34c-tile-seam-stitch-shadow",
"l34d-cumulative-postprocessing-candidate",
"l34e-self-review-diagnostic",
"l34f-adjudicated-reference",
];
const RESULT_PREFIX: Readonly<Record<AdvancedLaboratoryWorkId, string>> = {
"l3-pointpillars-visual-audit": "l3-pointpillars-visual-audit",
"l31-pointpillars-ravnoves": "l31-pointpillars-ravnoves",
"l32-pointpillars-camera-review": "l32-pointpillars-camera-review",
"l33-camera-first-detector-review": "l33-camera-first-detector-review",
"e31-source-binding": "e31-source-qualification",
"e32-track-geometry": "e32-track-geometry",
"e33-worker-shadow": "e33-worker-shadow",
@@ -61,6 +123,24 @@ const RESULT_PREFIX: Readonly<Record<AdvancedLaboratoryWorkId, string>> = {
"e38-perception-baseline": "e38-perception-baseline",
"e39-perception-refinement": "e39-perception-refinement",
"e40-perception-product-gate": "e40-perception-product-gate",
"e46-detector-truth-island": "e46-detector-truth-island",
"e46a-ai-engineering-preannotation": "e46a-ai-engineering-preannotation",
"e46b-temporal-motion": "e46b-temporal-motion",
"e46c-full-replay-world-tracks": "e46c-full-replay-world-tracks",
"e46d-temporal-failure-audit": "e46d-temporal-failure-audit",
"e46e-ready-stack": "e46e-ready-stack",
"e46f-dashcam-bakeoff": "e46f-dashcam-bakeoff",
"e46g-rectified-detector-bakeoff": "e46g-rectified-detector-bakeoff",
"e46h-full-rectified-front-replay": "e46h-full-rectified-front-replay",
"e46i-grounding-dino-full-replay": "e46i-grounding-dino-full-replay",
"e46j-raw-fisheye-realtime": "e46j-raw-fisheye-realtime",
"l34-right-yolox-truth-island-freeze": "l34-right-yolox-truth-island-freeze",
"l34a-assisted-yolox-error-audit": "l34a-assisted-yolox-error-audit",
"l34b-nested-box-consolidation-shadow": "l34b-nested-box-consolidation-shadow",
"l34c-tile-seam-stitch-shadow": "l34c-tile-seam-stitch-shadow",
"l34d-cumulative-postprocessing-candidate": "l34d-cumulative-postprocessing-candidate",
"l34e-self-review-diagnostic": "l34e-self-review-diagnostic",
"l34f-adjudicated-reference": "l34f-adjudicated-reference",
};
export function isAdvancedLaboratoryWorkId(
@@ -73,6 +153,8 @@ export function emptyAdvancedLaboratoryResults(): AdvancedLaboratoryResults {
return {
l3: null,
l31: null,
l32: null,
l33: null,
e31: null,
e32: null,
e33: null,
@@ -82,6 +164,24 @@ export function emptyAdvancedLaboratoryResults(): AdvancedLaboratoryResults {
e38: null,
e39: null,
e40: null,
e46: null,
e46a: null,
e46b: null,
e46c: null,
e46d: null,
e46e: null,
e46f: null,
e46g: null,
e46h: null,
e46i: null,
e46j: null,
l34: null,
l34a: null,
l34b: null,
l34c: null,
l34d: null,
l34e: null,
l34f: null,
};
}
@@ -175,6 +275,8 @@ export function advancedLaboratoryResultAvailable(
): boolean {
return workId === "l3-pointpillars-visual-audit" ? results.l3 !== null
: workId === "l31-pointpillars-ravnoves" ? results.l31 !== null
: workId === "l32-pointpillars-camera-review" ? results.l32 !== null
: workId === "l33-camera-first-detector-review" ? results.l33 !== null
: workId === "e31-source-binding" ? results.e31 !== null
: workId === "e32-track-geometry" ? results.e32 !== null
: workId === "e33-worker-shadow" ? results.e33 !== null
@@ -183,7 +285,25 @@ export function advancedLaboratoryResultAvailable(
: workId === "e37-ravnoves-acceptance" ? results.e37 !== null
: workId === "e38-perception-baseline" ? results.e38 !== null
: workId === "e39-perception-refinement" ? results.e39 !== null
: results.e40 !== null;
: workId === "e40-perception-product-gate" ? results.e40 !== null
: workId === "e46-detector-truth-island" ? results.e46 !== null
: workId === "e46a-ai-engineering-preannotation" ? results.e46a !== null
: workId === "e46b-temporal-motion" ? results.e46b !== null
: workId === "e46c-full-replay-world-tracks" ? results.e46c !== null
: workId === "e46d-temporal-failure-audit" ? results.e46d !== null
: workId === "e46e-ready-stack" ? results.e46e !== null
: workId === "e46f-dashcam-bakeoff" ? results.e46f !== null
: workId === "e46g-rectified-detector-bakeoff" ? results.e46g !== null
: workId === "e46h-full-rectified-front-replay" ? results.e46h !== null
: workId === "e46i-grounding-dino-full-replay" ? results.e46i !== null
: workId === "e46j-raw-fisheye-realtime" ? results.e46j !== null
: workId === "l34-right-yolox-truth-island-freeze" ? results.l34 !== null
: workId === "l34a-assisted-yolox-error-audit" ? results.l34a !== null
: workId === "l34b-nested-box-consolidation-shadow" ? results.l34b !== null
: workId === "l34c-tile-seam-stitch-shadow" ? results.l34c !== null
: workId === "l34d-cumulative-postprocessing-candidate" ? results.l34d !== null
: workId === "l34e-self-review-diagnostic" ? results.l34e !== null
: results.l34f !== null;
}
export async function fetchAdvancedLaboratoryResult(
@@ -201,6 +321,10 @@ export async function fetchAdvancedLaboratoryResult(
results.l3 = await fetchL3PointPillarsVisualAudit({ fetcher, signal });
} else if (workId === "l31-pointpillars-ravnoves") {
results.l31 = await fetchL31PointPillarsRavnoves({ fetcher, signal });
} else if (workId === "l32-pointpillars-camera-review") {
results.l32 = await fetchL32PointPillarsCameraReview({ fetcher, signal });
} else if (workId === "l33-camera-first-detector-review") {
results.l33 = await fetchL33CameraFirstDetectorReview({ fetcher, signal });
} else if (workId === "e31-source-binding") {
results.e31 = await fetchOne(
"/api/v1/laboratory/e31/results?limit=1",
@@ -247,8 +371,44 @@ export async function fetchAdvancedLaboratoryResult(
fetcher,
signal,
);
} else {
} else if (workId === "e40-perception-product-gate") {
results.e40 = await fetchE40ProductGateResult({ fetcher, signal });
} else if (workId === "e46-detector-truth-island") {
results.e46 = await fetchE46BlindReviewResult({ fetcher, signal });
} else if (workId === "e46a-ai-engineering-preannotation") {
results.e46a = await fetchE46AAiEngineeringPreannotation({ fetcher, signal });
} else if (workId === "e46b-temporal-motion") {
results.e46b = await fetchE46BTemporalMotion({ fetcher, signal });
} else if (workId === "e46c-full-replay-world-tracks") {
results.e46c = await fetchE46CFullReplayWorldTracks({ fetcher, signal });
} else if (workId === "e46d-temporal-failure-audit") {
results.e46d = await fetchE46DTemporalFailureAudit({ fetcher, signal });
} else if (workId === "e46e-ready-stack") {
results.e46e = await fetchE46EReadyStack({ fetcher, signal });
} else if (workId === "e46f-dashcam-bakeoff") {
results.e46f = await fetchE46FDashCamBakeoff({ fetcher, signal });
} else if (workId === "e46g-rectified-detector-bakeoff") {
results.e46g = await fetchE46GRectifiedDetectorBakeoff({ fetcher, signal });
} else if (workId === "e46h-full-rectified-front-replay") {
results.e46h = await fetchE46HFullRectifiedFrontReplay({ fetcher, signal });
} else if (workId === "e46i-grounding-dino-full-replay") {
results.e46i = await fetchE46IGroundingDinoFullReplay({ fetcher, signal });
} else if (workId === "e46j-raw-fisheye-realtime") {
results.e46j = await fetchE46JRawFisheyeRealtime({ fetcher, signal });
} else if (workId === "l34-right-yolox-truth-island-freeze") {
results.l34 = await fetchL34RightYoloxTruthIsland({ fetcher, signal });
} else if (workId === "l34a-assisted-yolox-error-audit") {
results.l34a = await fetchL34AAssistedYoloxErrorAudit({ fetcher, signal });
} else if (workId === "l34b-nested-box-consolidation-shadow") {
results.l34b = await fetchL34BNestedBoxConsolidation({ fetcher, signal });
} else if (workId === "l34c-tile-seam-stitch-shadow") {
results.l34c = await fetchL34CTileSeamStitch({ fetcher, signal });
} else if (workId === "l34d-cumulative-postprocessing-candidate") {
results.l34d = await fetchL34DCumulativePostprocessing({ fetcher, signal });
} else if (workId === "l34e-self-review-diagnostic") {
results.l34e = await fetchL34ESelfReviewDiagnostic({ fetcher, signal });
} else {
results.l34f = await fetchL34FFrozenResult({ fetcher, signal });
}
if (!advancedLaboratoryResultAvailable(workId, results)) {
throw new AdvancedLaboratoryContractError(
@@ -11,10 +11,32 @@ import type { E35DegradationRecoveryResult } from "./e35DegradationRecovery";
import type { E40PerceptionProductGateResult } from "./e40ProductGate";
import type { L3PointPillarsVisualAuditResult } from "./l3PointPillarsVisualAudit";
import type { L31PointPillarsRavnovesResult } from "./l31PointPillarsRavnoves";
import type { L32PointPillarsCameraReviewResult } from "./l32PointPillarsCameraReview";
import type { L33CameraFirstDetectorReviewResult } from "./l33CameraFirstDetectorReview";
import type { L34RightYoloxTruthIslandResult } from "./l34RightYoloxTruthIsland";
import type { L34AAssistedYoloxErrorAuditResult } from "./l34aAssistedYoloxErrorAudit";
import type { L34BResult } from "./l34bNestedBoxConsolidation";
import type { L34CResult } from "./l34cTileSeamStitch";
import type { L34DResult } from "./l34dCumulativePostprocessing";
import type { L34EResult } from "./l34eSelfReviewDiagnostic";
import type { L34FFrozenResult } from "./l34fAdjudication";
import type { E46BlindReviewResult } from "./e46BlindReview";
import type { E46AAiEngineeringPreannotationResult } from "./e46aAiEngineeringPreannotation";
import type { E46BTemporalMotionResult } from "./e46bTemporalMotion";
import type { E46CFullReplayWorldTracksResult } from "./e46cFullReplayWorldTracks";
import type { E46DTemporalFailureAuditResult } from "./e46dTemporalFailureAudit";
import type { E46EReadyStackResult } from "./e46eReadyStack";
import type { E46FDashCamBakeoffResult } from "./e46fDashCamBakeoff";
import type { E46GRectifiedDetectorBakeoffResult } from "./e46gRectifiedDetectorBakeoff";
import type { E46HFullRectifiedFrontReplayResult } from "./e46hFullRectifiedFrontReplay";
import type { E46IGroundingDinoFullReplayResult } from "./e46iGroundingDinoFullReplay";
import type { E46JRawFisheyeRealtimeResult } from "./e46jRawFisheyeRealtime";
export interface AdvancedLaboratoryResults {
l3: L3PointPillarsVisualAuditResult | null;
l31: L31PointPillarsRavnovesResult | null;
l32: L32PointPillarsCameraReviewResult | null;
l33: L33CameraFirstDetectorReviewResult | null;
e31: E31LaboratoryResult | null;
e32: E32LaboratoryResult | null;
e33: E33LaboratoryResult | null;
@@ -24,4 +46,22 @@ export interface AdvancedLaboratoryResults {
e38: E38PerceptionBaselineResult | null;
e39: E39PerceptionRefinementResult | null;
e40: E40PerceptionProductGateResult | null;
e46: E46BlindReviewResult | null;
e46a: E46AAiEngineeringPreannotationResult | null;
e46b: E46BTemporalMotionResult | null;
e46c: E46CFullReplayWorldTracksResult | null;
e46d: E46DTemporalFailureAuditResult | null;
e46e: E46EReadyStackResult | null;
e46f: E46FDashCamBakeoffResult | null;
e46g: E46GRectifiedDetectorBakeoffResult | null;
e46h: E46HFullRectifiedFrontReplayResult | null;
e46i: E46IGroundingDinoFullReplayResult | null;
e46j: E46JRawFisheyeRealtimeResult | null;
l34: L34RightYoloxTruthIslandResult | null;
l34a: L34AAssistedYoloxErrorAuditResult | null;
l34b: L34BResult | null;
l34c: L34CResult | null;
l34d: L34DResult | null;
l34e: L34EResult | null;
l34f: L34FFrozenResult | null;
}
@@ -1,16 +1,9 @@
import {
fetchE34TemporalLayerResult,
} from "./e34TemporalLayer";
import {
fetchE35DegradationRecoveryResult,
} from "./e35DegradationRecovery";
import {
fetchE40ProductGateResult,
} from "./e40ProductGate";
import { fetchE34TemporalLayerResult } from "./e34TemporalLayer";
import { fetchE35DegradationRecoveryResult } from "./e35DegradationRecovery";
import { fetchE40ProductGateResult } from "./e40ProductGate";
import { settledCatalogValue } from "./catalogTransport";
import type { AdvancedLaboratoryResults } from "./advancedLaboratoryResults";
export type { AdvancedLaboratoryResults } from "./advancedLaboratoryResults";
export interface E31LaboratoryResult {
resultId: string;
createdAtUtc: string | null;
@@ -947,7 +940,6 @@ export async function fetchOne<T>(
}
return parseCatalog(await response.json(), parser);
}
export async function fetchAdvancedLaboratoryResults({
fetcher = fetch,
signal,
@@ -976,8 +968,9 @@ export async function fetchAdvancedLaboratoryResults({
const e39 = settledCatalogValue(settled[7]);
const e40 = settledCatalogValue(settled[8]);
return {
l3: null,
l31: null,
l3: null, l31: null,
l32: null,
l33: null,
e31,
e32,
e33,
@@ -987,5 +980,20 @@ export async function fetchAdvancedLaboratoryResults({
e38,
e39,
e40,
e46: null,
e46a: null,
e46b: null,
e46c: null,
e46d: null,
e46e: null,
e46f: null,
e46g: null, e46h: null, e46i: null, e46j: null,
l34: null,
l34a: null,
l34b: null,
l34c: null,
l34d: null,
l34e: null,
l34f: null,
};
}
@@ -0,0 +1,243 @@
export interface E46BlindReviewSubmissionSummary {
resultId: string;
reviewerId: string;
annotationSessionId: string;
state: "completed-e48-review-input-not-truth";
frameCount: number;
objectCount: number;
}
export interface E46BlindReviewResult {
resultId: string;
createdAtUtc: string;
status: "prepared-awaiting-independent-human-review";
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
metrics: {
frameCount: 32;
anchorCount: 16;
temporalFrameCount: 16;
temporalGroupCount: 4;
reviewSessionCount: number;
completedSubmissionCount: number;
requiredSubmissionCount: 2;
};
submissions: readonly E46BlindReviewSubmissionSummary[];
decision: {
collectionReady: true;
twoIndependentReviewsComplete: boolean;
adjudicationReady: boolean;
e48Sealed: false;
l35Open: false;
nextAction: string;
};
access: "review-collection-read-only-summary";
}
type LaboratoryFetch = (
input: RequestInfo | URL,
init?: RequestInit,
) => Promise<Response>;
class E46BlindReviewContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new E46BlindReviewContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) {
throw new E46BlindReviewContractError(`${label}: ожидался массив.`);
}
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new E46BlindReviewContractError(`${label}: ожидалась строка.`);
}
return value;
}
function integer(value: unknown, label: string): number {
if (!Number.isInteger(value) || Number(value) < 0) {
throw new E46BlindReviewContractError(`${label}: ожидалось целое число.`);
}
return Number(value);
}
function boolean(value: unknown, label: string): boolean {
if (typeof value !== "boolean") {
throw new E46BlindReviewContractError(`${label}: ожидался boolean.`);
}
return value;
}
function exact<T extends string | boolean | number>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) {
throw new E46BlindReviewContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function parseSubmission(value: unknown): E46BlindReviewSubmissionSummary {
const item = object(value, "E46 submission");
const resultId = string(item.result_id, "E46 submission id");
if (!/^e46-lab-review-submission-[a-f0-9]{64}$/.test(resultId)) {
throw new E46BlindReviewContractError("E46 submission: нарушена identity.");
}
return {
resultId,
reviewerId: string(item.reviewer_id, "E46 reviewer"),
annotationSessionId: string(item.annotation_session_id, "E46 session"),
state: exact(
item.state,
"completed-e48-review-input-not-truth",
"E46 submission state",
),
frameCount: integer(item.frame_count, "E46 submitted frames"),
objectCount: integer(item.object_count, "E46 submitted objects"),
};
}
export async function fetchE46BlindReviewResult({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46BlindReviewResult | null> {
const response = await fetcher("/api/v1/laboratory/e46/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) {
throw new E46BlindReviewContractError(`E46 LAB недоступен: HTTP ${response.status}.`);
}
const catalog = object(await response.json(), "E46 catalog");
exact(
catalog.schema_version,
"missioncore.e46-detector-truth-island-catalog/v1",
"E46 catalog schema",
);
const items = array(catalog.items, "E46 results");
if (!items.length) return null;
if (items.length !== 1) {
throw new E46BlindReviewContractError("E46 catalog: нарушен размер.");
}
const item = object(items[0], "E46 result");
const resultId = string(item.result_id, "E46 result id");
if (!/^e46-detector-truth-island-[a-f0-9]{64}$/.test(resultId)) {
throw new E46BlindReviewContractError("E46 result: нарушена identity.");
}
const metrics = object(item.metrics, "E46 metrics");
const decision = object(item.decision, "E46 decision");
const blindness = object(item.blindness, "E46 blindness");
const authority = object(item.authority, "E46 authority");
const submissions = array(item.submissions, "E46 submissions").map(parseSubmission);
const reviewSessions = array(item.review_sessions, "E46 review sessions");
const completedSubmissionCount = integer(
metrics.completed_submission_count,
"E46 completed submissions",
);
if (
completedSubmissionCount !== submissions.length
|| completedSubmissionCount > 2
|| integer(metrics.review_session_count, "E46 session count") !== reviewSessions.length
|| reviewSessions.length > 2
|| submissions.some((submission) => submission.frameCount !== 32)
) {
throw new E46BlindReviewContractError("E46 review collection: нарушен размер.");
}
for (const key of (
[
"candidate_identity_included",
"model_prelabels_included",
"model_predictions_included",
"model_scores_included",
] as const
)) exact(blindness[key], false, `E46 blindness ${key}`);
for (const key of (
[
"ground_truth",
"independent_truth",
"metric_grade_reference",
"candidate_accepted",
"commands_enabled",
"navigation_or_safety_accepted",
] as const
)) exact(authority[key], false, `E46 authority ${key}`);
const twoComplete = boolean(
decision.two_independent_reviews_complete,
"E46 two review state",
);
const adjudicationReady = boolean(
decision.adjudication_ready,
"E46 adjudication state",
);
if (twoComplete !== (completedSubmissionCount === 2) || adjudicationReady !== twoComplete) {
throw new E46BlindReviewContractError("E46 decision: нарушен review gate.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "E46 created time"),
status: exact(
item.status,
"prepared-awaiting-independent-human-review",
"E46 status",
),
sourceSessionId: string(item.source_session_id, "E46 source session"),
cameraSourceId: exact(
item.camera_source_id,
"sensor.camera.right",
"E46 camera source",
),
metrics: {
frameCount: exact(metrics.frame_count, 32, "E46 frame count"),
anchorCount: exact(metrics.anchor_count, 16, "E46 anchors"),
temporalFrameCount: exact(
metrics.temporal_frame_count,
16,
"E46 temporal frames",
),
temporalGroupCount: exact(
metrics.temporal_group_count,
4,
"E46 temporal groups",
),
reviewSessionCount: integer(metrics.review_session_count, "E46 sessions"),
completedSubmissionCount,
requiredSubmissionCount: exact(
metrics.required_submission_count,
2,
"E46 required submissions",
),
},
submissions,
decision: {
collectionReady: exact(
decision.collection_ready,
true,
"E46 collection ready",
),
twoIndependentReviewsComplete: twoComplete,
adjudicationReady,
e48Sealed: exact(decision.e48_sealed, false, "E48 seal state"),
l35Open: exact(decision.l35_open, false, "L3.5 state"),
nextAction: string(decision.next_action, "E46 next action"),
},
access: exact(
item.access,
"review-collection-read-only-summary",
"E46 access",
),
};
}
@@ -0,0 +1,269 @@
export interface E46AObject {
objectId: string;
category: string;
displayCategory: string;
boxXyxy: readonly [number, number, number, number];
occluded: boolean;
truncated: boolean;
}
export interface E46ACase {
resultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
objects: readonly E46AObject[];
objectCount: number;
cameraUrl: string;
groundTruth: false;
independentReview: false;
}
export interface E46AAiEngineeringPreannotationResult {
resultId: string;
createdAtUtc: string;
sourceSessionId: "RAVNOVES00";
cameraSourceId: "sensor.camera.right";
sourceE46ResultId: string;
metrics: {
frameCount: 32;
reviewedFrameCount: 32;
sourceObjectCount: number;
objectCount: number;
customClassRelabelCount: number;
deletedFalseBoxCount: number;
geometrySnappedObjectCount: number;
sourceGeometryRetainedObjectCount: number;
categoryCorrectedObjectCount: number;
hardNegativeFrameCount: number;
independentReviewSubmissionCount: 0;
classCounts: Readonly<Record<string, number>>;
};
taxonomy: {
classes: readonly string[];
customClasses: readonly ["laptop", "stroller"];
unresolvedClassCount: 0;
};
decision: {
preannotationAvailable: true;
visualReviewComplete: true;
independentReviewCountAffected: false;
e48TruthSealOpen: false;
l35AcceptanceOpen: false;
nextAction: string;
};
limitations: readonly string[];
groundTruth: false;
access: "read-only-ai-engineering-preannotation-not-truth";
}
type LaboratoryFetch = (
input: RequestInfo | URL,
init?: RequestInit,
) => Promise<Response>;
class E46AContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new E46AContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new E46AContractError(`${label}: ожидался массив.`);
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new E46AContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new E46AContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isInteger(parsed) || parsed < 0) {
throw new E46AContractError(`${label}: ожидалось целое число.`);
}
return parsed;
}
function optionalInteger(value: unknown, fallback: number, label: string): number {
return value === undefined ? fallback : integer(value, label);
}
function exact<T extends string | boolean | number>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new E46AContractError(`${label}: нарушен контракт.`);
return expected;
}
function boolean(value: unknown, label: string): boolean {
if (typeof value !== "boolean") {
throw new E46AContractError(`${label}: ожидался boolean.`);
}
return value;
}
function sha256(value: unknown, label: string): string {
const parsed = string(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) throw new E46AContractError(`${label}: invalid hash.`);
return parsed;
}
function parseClassCounts(value: unknown): Readonly<Record<string, number>> {
const raw = object(value, "E46A class counts");
const parsed: Record<string, number> = {};
for (const [key, count] of Object.entries(raw)) {
if (!key.trim()) throw new E46AContractError("E46A class name: пустое значение.");
parsed[key] = integer(count, `E46A ${key} count`);
}
return parsed;
}
function parseObject(value: unknown): E46AObject {
const item = object(value, "E46A object");
const box = array(item.box_xyxy, "E46A box").map((coordinate) => number(coordinate, "E46A coordinate"));
if (box.length !== 4 || box[2] <= box[0] || box[3] <= box[1]) {
throw new E46AContractError("E46A box: invalid geometry.");
}
const category = string(item.category, "E46A category");
if (category === "unmapped") throw new E46AContractError("E46A category unresolved.");
return {
objectId: string(item.object_id, "E46A object id"),
category,
displayCategory: category === "stroller" ? "Коляска"
: category === "laptop" ? "Ноутбук"
: category,
boxXyxy: box as [number, number, number, number],
occluded: boolean(item.occluded, "E46A occluded"),
truncated: boolean(item.truncated, "E46A truncated"),
};
}
export async function fetchE46AAiEngineeringPreannotation({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46AAiEngineeringPreannotationResult | null> {
const response = await fetcher("/api/v1/laboratory/e46a/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new E46AContractError(`E46A LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46A catalog");
exact(catalog.schema_version, "missioncore.e46a-ai-engineering-preannotation-catalog/v1", "E46A catalog schema");
const items = array(catalog.items, "E46A results");
if (!items.length) return null;
if (items.length !== 1) throw new E46AContractError("E46A catalog: нарушен размер.");
const item = object(items[0], "E46A result");
exact(item.schema_version, "missioncore.e46a-ai-engineering-preannotation-view/v1", "E46A result schema");
const resultId = string(item.result_id, "E46A result id");
const sourceE46ResultId = string(item.source_e46_result_id, "E46A source id");
if (!/^e46a-ai-engineering-preannotation-[a-f0-9]{64}$/.test(resultId)
|| !/^e46-detector-truth-island-[a-f0-9]{64}$/.test(sourceE46ResultId)) {
throw new E46AContractError("E46A result: нарушена identity.");
}
const metrics = object(item.metrics, "E46A metrics");
const taxonomy = object(item.taxonomy, "E46A taxonomy");
const decision = object(item.decision, "E46A decision");
const classes = array(taxonomy.classes, "E46A classes").map((value) => string(value, "E46A class"));
const custom = array(taxonomy.custom_classes, "E46A custom classes").map((value) => string(value, "E46A custom class"));
const objectCount = integer(metrics.object_count, "E46A object count");
if (custom.length !== 2 || custom[0] !== "laptop" || custom[1] !== "stroller") {
throw new E46AContractError("E46A custom taxonomy changed.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "E46A created time"),
sourceSessionId: exact(item.source_session_id, "RAVNOVES00", "E46A source session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "E46A camera source"),
sourceE46ResultId,
metrics: {
frameCount: exact(metrics.frame_count, 32, "E46A frame count"),
reviewedFrameCount: exact(metrics.reviewed_frame_count, 32, "E46A reviewed frames"),
sourceObjectCount: optionalInteger(metrics.source_object_count, objectCount, "E46A source object count"),
objectCount,
customClassRelabelCount: integer(metrics.custom_class_relabel_count, "E46A relabel count"),
deletedFalseBoxCount: optionalInteger(metrics.deleted_false_box_count, 0, "E46A deleted false boxes"),
geometrySnappedObjectCount: optionalInteger(metrics.geometry_snapped_object_count, 0, "E46A snapped geometry"),
sourceGeometryRetainedObjectCount: optionalInteger(metrics.source_geometry_retained_object_count, objectCount, "E46A retained geometry"),
categoryCorrectedObjectCount: optionalInteger(metrics.category_corrected_object_count, 0, "E46A category corrections"),
hardNegativeFrameCount: integer(metrics.hard_negative_frame_count, "E46A hard negatives"),
independentReviewSubmissionCount: exact(metrics.independent_review_submission_count, 0, "E46A independent reviews"),
classCounts: parseClassCounts(metrics.class_counts),
},
taxonomy: {
classes,
customClasses: ["laptop", "stroller"],
unresolvedClassCount: exact(taxonomy.unresolved_class_count, 0, "E46A unresolved classes"),
},
decision: {
preannotationAvailable: exact(decision.preannotation_available, true, "E46A available"),
visualReviewComplete: exact(decision.visual_review_complete, true, "E46A visual review"),
independentReviewCountAffected: exact(decision.independent_review_count_affected, false, "E46A reviewer isolation"),
e48TruthSealOpen: exact(decision.e48_truth_seal_open, false, "E46A E48 state"),
l35AcceptanceOpen: exact(decision.l35_acceptance_open, false, "E46A L3.5 state"),
nextAction: string(decision.next_action, "E46A next action"),
},
limitations: array(item.limitations, "E46A limitations").map((value) => string(value, "E46A limitation")),
groundTruth: exact(item.ground_truth, false, "E46A truth state"),
access: exact(item.access, "read-only-ai-engineering-preannotation-not-truth", "E46A access"),
};
}
export async function fetchE46ACase(
resultId: string,
sequence: number,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
): Promise<E46ACase> {
if (!/^e46a-ai-engineering-preannotation-[a-f0-9]{64}$/.test(resultId)
|| !Number.isInteger(sequence) || sequence < 1 || sequence > 32) {
throw new E46AContractError("E46A case request invalid.");
}
const response = await fetcher(`/api/v1/laboratory/e46a/results/${resultId}/cases/${sequence}`, {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new E46AContractError(`E46A frame недоступен: HTTP ${response.status}.`);
const item = object(await response.json(), "E46A case");
exact(item.schema_version, "missioncore.e46a-ai-engineering-preannotation-case/v1", "E46A case schema");
const objects = array(item.objects, "E46A objects").map(parseObject);
if (integer(item.object_count, "E46A object count") !== objects.length) {
throw new E46AContractError("E46A case object count mismatch.");
}
return {
resultId: exact(item.result_id, resultId, "E46A case result"),
truthIslandSequence: exact(item.truth_island_sequence, sequence, "E46A case sequence"),
imageId: integer(item.image_id, "E46A image id"),
frameIndex: integer(item.frame_index, "E46A frame index"),
groupId: string(item.group_id, "E46A group"),
sessionSeconds: number(item.session_seconds, "E46A session seconds"),
sourceImageSha256: sha256(item.source_image_sha256, "E46A source hash"),
objects,
objectCount: objects.length,
cameraUrl: string(item.camera_url, "E46A camera URL"),
groundTruth: exact(item.ground_truth, false, "E46A case truth"),
independentReview: exact(item.independent_review, false, "E46A independent review"),
};
}
@@ -0,0 +1,170 @@
export type E46BMotionState = "dynamic" | "static" | "unknown";
export interface E46BObject {
objectId: string;
trackId: string;
trackIndex: number;
category: string;
displayCategory: string;
boxXyxy: readonly [number, number, number, number];
motionState: E46BMotionState;
motionConfidence: number;
motionEvidenceObservationCount: number;
trailCentersXy: readonly (readonly [number, number])[];
}
export interface E46BCase {
resultId: string;
truthIslandSequence: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
objects: readonly E46BObject[];
objectCount: number;
motionCounts: Readonly<Record<E46BMotionState, number>>;
cameraUrl: string;
}
export interface E46BTemporalMotionResult {
resultId: string;
createdAtUtc: string;
sourceE46AResultId: string;
sourceE26ResultId: string;
metrics: {
frameCount: 16;
temporalGroupCount: 4;
objectObservationCount: 136;
trackCount: 34;
matchedMotionObservationCount: number;
unmatchedMotionObservationCount: number;
dynamicTrackCount: number;
staticTrackCount: number;
unknownTrackCount: number;
visuallyReviewedFrameCount: 16;
};
decision: { stableIdsAvailable: true; motionStateAvailable: true; metricVelocityAvailable: false; nextAction: string };
limitations: readonly string[];
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
const object = (value: unknown, label: string): Record<string, unknown> => {
if (!value || typeof value !== "object" || Array.isArray(value)) throw new ContractError(`${label}: объект.`);
return value as Record<string, unknown>;
};
const array = (value: unknown, label: string): readonly unknown[] => {
if (!Array.isArray(value)) throw new ContractError(`${label}: массив.`);
return value;
};
const string = (value: unknown, label: string): string => {
if (typeof value !== "string" || !value.trim()) throw new ContractError(`${label}: строка.`);
return value;
};
const number = (value: unknown, label: string): number => {
if (typeof value !== "number" || !Number.isFinite(value)) throw new ContractError(`${label}: число.`);
return value;
};
const integer = (value: unknown, label: string): number => {
const parsed = number(value, label);
if (!Number.isInteger(parsed) || parsed < 0) throw new ContractError(`${label}: целое.`);
return parsed;
};
const exact = <T extends string | boolean | number>(value: unknown, expected: T, label: string): T => {
if (value !== expected) throw new ContractError(`${label}: контракт.`);
return expected;
};
const motionState = (value: unknown): E46BMotionState => {
if (value !== "dynamic" && value !== "static" && value !== "unknown") throw new ContractError("E46B motion state.");
return value;
};
const displayCategory = (category: string): string => category === "stroller" ? "Коляска"
: category === "laptop" ? "Ноутбук"
: category === "heavy_vehicle" ? "Тяжёлый транспорт"
: category === "person" ? "Человек"
: category === "car" ? "Авто" : category;
export async function fetchE46BTemporalMotion({ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {}): Promise<E46BTemporalMotionResult | null> {
const response = await fetcher("/api/v1/laboratory/e46b/results?limit=1", { headers: { Accept: "application/json" }, signal });
if (!response.ok) throw new ContractError(`E46B LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46B catalog");
exact(catalog.schema_version, "missioncore.e46b-temporal-motion-catalog/v1", "E46B catalog schema");
const items = array(catalog.items, "E46B results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46B catalog size.");
const item = object(items[0], "E46B result");
exact(item.schema_version, "missioncore.e46b-temporal-motion-view/v1", "E46B view schema");
const resultId = string(item.result_id, "E46B result id");
if (!/^e46b-temporal-motion-[a-f0-9]{64}$/.test(resultId)) throw new ContractError("E46B identity.");
const metrics = object(item.metrics, "E46B metrics");
const decision = object(item.decision, "E46B decision");
return {
resultId,
createdAtUtc: string(item.created_at_utc, "E46B created"),
sourceE46AResultId: string(item.source_e46a_result_id, "E46B E46A source"),
sourceE26ResultId: string(item.source_e26_result_id, "E46B E26 source"),
metrics: {
frameCount: exact(metrics.frame_count, 16, "E46B frames"),
temporalGroupCount: exact(metrics.temporal_group_count, 4, "E46B groups"),
objectObservationCount: exact(metrics.object_observation_count, 136, "E46B observations"),
trackCount: exact(metrics.track_count, 34, "E46B tracks"),
matchedMotionObservationCount: integer(metrics.matched_motion_observation_count, "E46B matched"),
unmatchedMotionObservationCount: integer(metrics.unmatched_motion_observation_count, "E46B unmatched"),
dynamicTrackCount: integer(metrics.dynamic_track_count, "E46B dynamic"),
staticTrackCount: integer(metrics.static_track_count, "E46B static"),
unknownTrackCount: integer(metrics.unknown_track_count, "E46B unknown"),
visuallyReviewedFrameCount: exact(metrics.visually_reviewed_frame_count, 16, "E46B reviewed"),
},
decision: {
stableIdsAvailable: exact(decision.stable_ids_available, true, "E46B stable IDs"),
motionStateAvailable: exact(decision.motion_state_available, true, "E46B motion"),
metricVelocityAvailable: exact(decision.metric_velocity_available, false, "E46B velocity"),
nextAction: string(decision.next_action, "E46B next action"),
},
limitations: array(item.limitations, "E46B limitations").map((value) => string(value, "E46B limitation")),
};
}
export async function fetchE46BCase(resultId: string, sequence: number, { fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {}): Promise<E46BCase> {
if (!/^e46b-temporal-motion-[a-f0-9]{64}$/.test(resultId)) throw new ContractError("E46B result id.");
const response = await fetcher(`/api/v1/laboratory/e46b/results/${resultId}/cases/${sequence}`, { headers: { Accept: "application/json" }, signal });
if (!response.ok) throw new ContractError(`E46B frame недоступен: HTTP ${response.status}.`);
const item = object(await response.json(), "E46B case");
exact(item.schema_version, "missioncore.e46b-temporal-motion-case/v1", "E46B case schema");
const objects = array(item.objects, "E46B objects").map((raw): E46BObject => {
const value = object(raw, "E46B object");
const box = array(value.box_xyxy, "E46B box").map((coordinate) => number(coordinate, "E46B coordinate"));
const trail = array(value.trail_centers_xy, "E46B trail").map((rawPoint) => {
const point = array(rawPoint, "E46B point").map((coordinate) => number(coordinate, "E46B point coordinate"));
if (point.length !== 2) throw new ContractError("E46B point geometry.");
return point as [number, number];
});
if (box.length !== 4 || box[2] <= box[0] || box[3] <= box[1]) throw new ContractError("E46B box geometry.");
const category = string(value.category, "E46B category");
return {
objectId: string(value.object_id, "E46B object id"),
trackId: string(value.track_id, "E46B track id"),
trackIndex: integer(value.track_index, "E46B track index"),
category,
displayCategory: displayCategory(category),
boxXyxy: box as [number, number, number, number],
motionState: motionState(value.motion_state),
motionConfidence: number(value.motion_confidence, "E46B motion confidence"),
motionEvidenceObservationCount: integer(value.motion_evidence_observation_count, "E46B evidence count"),
trailCentersXy: trail,
};
});
const rawCounts = object(item.motion_counts, "E46B motion counts");
return {
resultId: exact(item.result_id, resultId, "E46B case result"),
truthIslandSequence: integer(item.truth_island_sequence, "E46B sequence"),
frameIndex: integer(item.frame_index, "E46B frame"),
groupId: string(item.group_id, "E46B group"),
sessionSeconds: number(item.session_seconds, "E46B time"),
sourceImageSha256: string(item.source_image_sha256, "E46B image hash"),
objects,
objectCount: integer(item.object_count, "E46B object count"),
motionCounts: { dynamic: integer(rawCounts.dynamic, "E46B dynamic count"), static: integer(rawCounts.static, "E46B static count"), unknown: integer(rawCounts.unknown, "E46B unknown count") },
cameraUrl: string(item.camera_url, "E46B camera URL"),
};
}
@@ -0,0 +1,281 @@
export type E46CMotionState = "dynamic" | "static" | "unknown";
export interface E46CCameraObject {
objectId: string;
category: string;
displayCategory: string;
boxXyxy: readonly [number, number, number, number];
routeTrackId: number | null;
worldTrackId: number | null;
motionState: E46CMotionState;
}
export interface E46CWorldObject {
worldTrackId: number;
routeTrackId: number;
category: string;
motionState: E46CMotionState;
positionMapM: readonly [number, number, number];
occupancyFootprintMapXy: readonly (readonly [number, number])[];
occupancyEvidenceCurrent: boolean;
occupancyCellCount: number;
}
export interface E46CCase {
resultId: string;
truthIslandSequence: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
fusionState: string;
objects: readonly E46CCameraObject[];
objectCount: number;
matchedRouteObjectCount: number;
worldObjects: readonly E46CWorldObject[];
worldObjectCount: number;
cameraUrl: string;
}
export interface E46CFullReplayWorldTracksResult {
resultId: string;
createdAtUtc: string;
sourceE46AResultId: string;
sourceE26ResultId: string;
metrics: {
routeFrameCount: 4489;
routeSpanSeconds: number;
fusionObservationCount: number;
sourceTrackCount: number;
worldTrackCandidateCount: number;
worldTrackCount: number;
sourceTrackWorldBoundCount: number;
worldFrameCount: number;
worldObservationCount: number;
worldCurrentObservationCount: number;
worldHeldObservationCount: number;
visualSampleFrameCount: 32;
sampleObjectCount: number;
sampleMatchedRouteObjectCount: number;
sampleUnmatchedObjectCount: number;
sampleWorldFrameCount: number;
motionObservationCounts: Readonly<Record<E46CMotionState, number>>;
};
acceptance: { benchmarkPassedEvents: 11; benchmarkTotalEvents: 11 };
decision: { routeTrackLayerAvailable: true; worldOccupiedLayerAvailable: true; unknownRemainsOccupied: true; freeSpaceAvailable: false; nextAction: string };
limitations: readonly string[];
}
export interface E46CVideoObject {
boxXyxy: readonly [number, number, number, number];
category: string;
displayCategory: string;
score: number;
routeTrackId: number;
worldTrackId: number | null;
motionState: E46CMotionState;
motionConfidence: number;
trackHits: number;
trackAgeSeconds: number;
cameraEvidenceCurrent: boolean;
worldEvidenceCurrent: boolean;
}
export interface E46CVideoFrame {
frameIndex: number;
sessionSeconds: number;
fusionState: string;
objects: readonly E46CVideoObject[];
}
export interface E46CVideoReviewWindow {
id: string;
kind: string;
classGroup: string;
startSeconds: number;
endSeconds: number;
targetSourceTrackIds: readonly number[];
}
export interface E46CVideoOverlay {
resultId: string;
recordedSourceSessionId: string;
recordedSourceId: "sensor.camera.right";
inputSha256: string;
imageWidth: 800;
imageHeight: 600;
timelineStartSeconds: number;
timelineEndSeconds: number;
frameCount: 4489;
frames: readonly E46CVideoFrame[];
reviewWindows: readonly E46CVideoReviewWindow[];
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
const object = (value: unknown, label: string): Record<string, unknown> => { if (!value || typeof value !== "object" || Array.isArray(value)) throw new ContractError(`${label}: объект.`); return value as Record<string, unknown>; };
const array = (value: unknown, label: string): readonly unknown[] => { if (!Array.isArray(value)) throw new ContractError(`${label}: массив.`); return value; };
const string = (value: unknown, label: string): string => { if (typeof value !== "string" || !value.trim()) throw new ContractError(`${label}: строка.`); return value; };
const number = (value: unknown, label: string): number => { if (typeof value !== "number" || !Number.isFinite(value)) throw new ContractError(`${label}: число.`); return value; };
const integer = (value: unknown, label: string): number => { const parsed = number(value, label); if (!Number.isInteger(parsed) || parsed < 0) throw new ContractError(`${label}: целое.`); return parsed; };
const optionalInteger = (value: unknown, label: string): number | null => value === null ? null : integer(value, label);
const exact = <T extends string | boolean | number>(value: unknown, expected: T, label: string): T => { if (value !== expected) throw new ContractError(`${label}: контракт.`); return expected; };
const motionState = (value: unknown): E46CMotionState => { if (value !== "dynamic" && value !== "static" && value !== "unknown") throw new ContractError("E46C motion state."); return value; };
const displayCategory = (category: string): string => category === "stroller" ? "Коляска" : category === "laptop" ? "Ноутбук" : category === "heavy_vehicle" || category === "truck" || category === "bus" ? "Тяжёлый транспорт" : category === "person" ? "Человек" : category === "car" ? "Авто" : category;
const vector = (value: unknown, length: number, label: string): number[] => { const parsed = array(value, label).map((item) => number(item, label)); if (parsed.length !== length) throw new ContractError(`${label}: geometry.`); return parsed; };
export async function fetchE46CFullReplayWorldTracks({ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {}): Promise<E46CFullReplayWorldTracksResult | null> {
const response = await fetcher("/api/v1/laboratory/e46c/results?limit=1", { headers: { Accept: "application/json" }, signal });
if (!response.ok) throw new ContractError(`E46C LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46C catalog"); exact(catalog.schema_version, "missioncore.e46c-full-replay-world-tracks-catalog/v1", "E46C catalog schema");
const items = array(catalog.items, "E46C results"); if (!items.length) return null; if (items.length !== 1) throw new ContractError("E46C catalog size.");
const item = object(items[0], "E46C result"); exact(item.schema_version, "missioncore.e46c-full-replay-world-tracks-view/v1", "E46C view schema");
const resultId = string(item.result_id, "E46C result id"); if (!/^e46c-full-replay-world-tracks-[a-f0-9]{64}$/.test(resultId)) throw new ContractError("E46C identity.");
const metrics = object(item.metrics, "E46C metrics"); const counts = object(metrics.motion_observation_counts, "E46C motion counts"); const acceptance = object(item.acceptance, "E46C acceptance"); const decision = object(item.decision, "E46C decision");
return { resultId, createdAtUtc: string(item.created_at_utc, "E46C created"), sourceE46AResultId: string(item.source_e46a_result_id, "E46C E46A"), sourceE26ResultId: string(item.source_e26_result_id, "E46C E26"), metrics: { routeFrameCount: exact(metrics.route_frame_count, 4489, "E46C route frames"), routeSpanSeconds: number(metrics.route_span_seconds, "E46C span"), fusionObservationCount: integer(metrics.fusion_observation_count, "E46C observations"), sourceTrackCount: integer(metrics.source_track_count, "E46C source tracks"), worldTrackCandidateCount: integer(metrics.world_track_candidate_count, "E46C world candidates"), worldTrackCount: integer(metrics.world_track_count, "E46C world tracks"), sourceTrackWorldBoundCount: integer(metrics.source_track_world_bound_count, "E46C bound tracks"), worldFrameCount: integer(metrics.world_frame_count, "E46C world frames"), worldObservationCount: integer(metrics.world_observation_count, "E46C world observations"), worldCurrentObservationCount: integer(metrics.world_current_observation_count, "E46C current world"), worldHeldObservationCount: integer(metrics.world_held_observation_count, "E46C held world"), visualSampleFrameCount: exact(metrics.visual_sample_frame_count, 32, "E46C samples"), sampleObjectCount: integer(metrics.sample_object_count, "E46C sample objects"), sampleMatchedRouteObjectCount: integer(metrics.sample_matched_route_object_count, "E46C matched"), sampleUnmatchedObjectCount: integer(metrics.sample_unmatched_object_count, "E46C unmatched"), sampleWorldFrameCount: integer(metrics.sample_world_frame_count, "E46C sample world frames"), motionObservationCounts: { dynamic: integer(counts.dynamic, "E46C dynamic"), static: integer(counts.static, "E46C static"), unknown: integer(counts.unknown, "E46C unknown") } }, acceptance: { benchmarkPassedEvents: exact(acceptance.benchmark_passed_events, 11, "E46C passed events"), benchmarkTotalEvents: exact(acceptance.benchmark_total_events, 11, "E46C total events") }, decision: { routeTrackLayerAvailable: exact(decision.route_track_layer_available, true, "E46C route layer"), worldOccupiedLayerAvailable: exact(decision.world_occupied_layer_available, true, "E46C world layer"), unknownRemainsOccupied: exact(decision.unknown_remains_occupied, true, "E46C unknown"), freeSpaceAvailable: exact(decision.free_space_available, false, "E46C free space"), nextAction: string(decision.next_action, "E46C next") }, limitations: array(item.limitations, "E46C limitations").map((value) => string(value, "E46C limitation")) };
}
export async function fetchE46CCase(resultId: string, sequence: number, { fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {}): Promise<E46CCase> {
const response = await fetcher(`/api/v1/laboratory/e46c/results/${resultId}/cases/${sequence}`, { headers: { Accept: "application/json" }, signal }); if (!response.ok) throw new ContractError(`E46C frame недоступен: HTTP ${response.status}.`);
const item = object(await response.json(), "E46C case"); exact(item.schema_version, "missioncore.e46c-full-replay-world-track-case/v1", "E46C case schema");
const objects = array(item.objects, "E46C objects").map((raw): E46CCameraObject => { const value = object(raw, "E46C object"); const category = string(value.category, "E46C category"); const box = vector(value.box_xyxy, 4, "E46C box") as [number, number, number, number]; return { objectId: string(value.object_id, "E46C object id"), category, displayCategory: displayCategory(category), boxXyxy: box, routeTrackId: optionalInteger(value.route_track_id, "E46C route track"), worldTrackId: optionalInteger(value.world_track_id, "E46C world track"), motionState: motionState(value.motion_state) }; });
const worldObjects = array(item.world_objects, "E46C world objects").map((raw): E46CWorldObject => { const value = object(raw, "E46C world object"); return { worldTrackId: integer(value.world_track_id, "E46C world id"), routeTrackId: integer(value.route_track_id, "E46C route id"), category: string(value.category, "E46C world category"), motionState: motionState(value.motion_state), positionMapM: vector(value.position_map_m, 3, "E46C position") as [number, number, number], occupancyFootprintMapXy: array(value.occupancy_footprint_map_xy, "E46C footprint").map((point) => vector(point, 2, "E46C footprint point") as [number, number]), occupancyEvidenceCurrent: exact(value.occupancy_evidence_current, Boolean(value.occupancy_evidence_current), "E46C current") as boolean, occupancyCellCount: integer(value.occupancy_cell_count, "E46C cells") }; });
return { resultId: exact(item.result_id, resultId, "E46C case result"), truthIslandSequence: integer(item.truth_island_sequence, "E46C sequence"), frameIndex: integer(item.frame_index, "E46C frame"), groupId: string(item.group_id, "E46C group"), sessionSeconds: number(item.session_seconds, "E46C time"), sourceImageSha256: string(item.source_image_sha256, "E46C image hash"), fusionState: string(item.fusion_state, "E46C fusion"), objects, objectCount: integer(item.object_count, "E46C object count"), matchedRouteObjectCount: integer(item.matched_route_object_count, "E46C matched count"), worldObjects, worldObjectCount: integer(item.world_object_count, "E46C world count"), cameraUrl: string(item.camera_url, "E46C camera URL") };
}
export async function fetchE46CVideoOverlay(
resultId: string,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
): Promise<E46CVideoOverlay> {
const response = await fetcher(
`/api/v1/laboratory/e46c/results/${resultId}/video-overlay`,
{ headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new ContractError(`E46C video overlay недоступен: HTTP ${response.status}.`);
}
const payload = object(await response.json(), "E46C video overlay");
exact(
payload.schema_version,
"missioncore.e46c-recorded-video-overlay/v1",
"E46C video overlay schema",
);
exact(payload.result_id, resultId, "E46C video result");
exact(payload.ground_truth, false, "E46C video truth");
const recordedSource = object(payload.recorded_source, "E46C recorded source");
exact(recordedSource.source_id, "sensor.camera.right", "E46C video source");
exact(
recordedSource.synchronization,
"host-arrival-best-effort",
"E46C video synchronization",
);
const inputSha256 = string(recordedSource.input_sha256, "E46C video input hash");
if (!/^[a-f0-9]{64}$/.test(inputSha256)) throw new ContractError("E46C video input hash.");
const frames = array(payload.frames, "E46C video frames").map(
(raw, frameSequence): E46CVideoFrame => {
const frame = object(raw, "E46C video frame");
const frameIndex = integer(frame.frame_index, "E46C video frame index");
if (frameIndex !== frameSequence) throw new ContractError("E46C video frame order.");
return {
frameIndex,
sessionSeconds: number(frame.session_seconds, "E46C video frame time"),
fusionState: string(frame.fusion_state, "E46C video fusion state"),
objects: array(frame.objects, "E46C video objects").map((rawObject) => {
const item = object(rawObject, "E46C video object");
const category = string(item.category, "E46C video category");
return {
boxXyxy: vector(item.bbox_xyxy, 4, "E46C video box") as [number, number, number, number],
category,
displayCategory: displayCategory(category),
score: number(item.score, "E46C video score"),
routeTrackId: integer(item.route_track_id, "E46C video route track"),
worldTrackId: optionalInteger(item.world_track_id, "E46C video world track"),
motionState: motionState(item.motion_state),
motionConfidence: number(item.motion_confidence, "E46C video motion confidence"),
trackHits: integer(item.track_hits, "E46C video track hits"),
trackAgeSeconds: number(item.track_age_seconds, "E46C video track age"),
cameraEvidenceCurrent: exact(
item.camera_evidence_current,
Boolean(item.camera_evidence_current),
"E46C camera evidence",
) as boolean,
worldEvidenceCurrent: exact(
item.world_evidence_current,
Boolean(item.world_evidence_current),
"E46C world evidence",
) as boolean,
};
}),
};
},
);
const reviewWindows = array(payload.review_windows, "E46C video review windows").map(
(raw): E46CVideoReviewWindow => {
const window = object(raw, "E46C video review window");
return {
id: string(window.id, "E46C video review id"),
kind: string(window.kind, "E46C video review kind"),
classGroup: string(window.class_group, "E46C video review class"),
startSeconds: number(window.start_seconds, "E46C video review start"),
endSeconds: number(window.end_seconds, "E46C video review end"),
targetSourceTrackIds: array(
window.target_source_track_ids,
"E46C video review targets",
).map((value) => integer(value, "E46C video review target")),
};
},
);
const timelineStartSeconds = number(
payload.timeline_start_seconds,
"E46C video timeline start",
);
const timelineEndSeconds = number(
payload.timeline_end_seconds,
"E46C video timeline end",
);
if (
frames.length !== 4489 ||
exact(payload.frame_count, 4489, "E46C video frame count") !== frames.length ||
frames[0]?.sessionSeconds !== timelineStartSeconds ||
frames.at(-1)?.sessionSeconds !== timelineEndSeconds
) {
throw new ContractError("E46C video timeline coverage.");
}
return {
resultId,
recordedSourceSessionId: string(
recordedSource.session_id,
"E46C recorded source session",
),
recordedSourceId: "sensor.camera.right",
inputSha256,
imageWidth: exact(payload.image_width, 800, "E46C video width"),
imageHeight: exact(payload.image_height, 600, "E46C video height"),
timelineStartSeconds,
timelineEndSeconds,
frameCount: 4489,
frames,
reviewWindows,
};
}
export function selectE46CVideoFrame(
frames: readonly E46CVideoFrame[],
sessionSeconds: number,
): E46CVideoFrame | null {
if (!frames.length || !Number.isFinite(sessionSeconds)) return null;
let low = 0;
let high = frames.length - 1;
while (low <= high) {
const middle = Math.floor((low + high) / 2);
const frame = frames[middle];
if (!frame) break;
if (frame.sessionSeconds <= sessionSeconds) low = middle + 1;
else high = middle - 1;
}
const before = frames[Math.max(0, high)] ?? null;
const after = frames[Math.min(frames.length - 1, low)] ?? null;
if (!before) return after;
if (!after) return before;
return Math.abs(before.sessionSeconds - sessionSeconds) <=
Math.abs(after.sessionSeconds - sessionSeconds)
? before
: after;
}
@@ -0,0 +1,291 @@
export type E46DTemporalSignalKind =
| "layer-blackout"
| "camera-evidence-hold"
| "route-layer-gap"
| "route-id-rebirth-candidate"
| "bbox-jump"
| "motion-state-flap"
| "world-binding-flap"
| "short-track-burst";
export type E46DTemporalPriority = "critical" | "high" | "medium";
export interface E46DReviewClip {
clipId: string;
rank: number;
priority: E46DTemporalPriority;
kind: E46DTemporalSignalKind;
signalId: string;
startSeconds: number;
eventStartSeconds: number;
eventEndSeconds: number;
endSeconds: number;
startFrame: number;
endFrame: number;
routeTrackIds: readonly number[];
worldTrackIds: readonly number[];
evidence: Readonly<Record<string, string | number | boolean>>;
}
export interface E46DTemporalFailureAuditResult {
resultId: string;
createdAtUtc: string;
sourceE46CResultId: string;
sourceE26ResultId: string;
metrics: {
routeFrameCount: 4489;
routeSpanSeconds: number;
objectObservationCount: number;
routeTrackCount: number;
zeroObjectFrameCount: number;
zeroObjectFrameFraction: number;
cameraHeldObservationCount: number;
cameraHeldObservationFraction: number;
detectorHoldEpisodeCount: number;
layerBlackoutEpisodeCount: number;
routeLayerGapEpisodeCount: number;
routeIdRebirthCandidateCount: number;
bboxJumpEpisodeCount: number;
motionStateFlapEpisodeCount: number;
worldBindingFlapEpisodeCount: number;
shortRouteTrackCount: number;
shortRouteTrackFraction: number;
shortTrackBurstEpisodeCount: number;
failureSignalCount: number;
reviewClipCount: number;
temporalContinuityPassed: boolean;
};
acceptance: {
fullRouteAccounted: true;
temporalContinuityPassed: boolean;
independentTruthAvailable: false;
navigationOrSafetyAccepted: false;
};
decision: {
temporalRegressionConfirmed: boolean;
detectorGapVisible: boolean;
routeFragmentationVisible: boolean;
worldBindingInstabilityVisible: boolean;
nextAction: string;
};
limitations: readonly string[];
reviewClips: readonly E46DReviewClip[];
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new ContractError(`${label}: ожидался массив.`);
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new ContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isInteger(parsed) || parsed < 0) {
throw new ContractError(`${label}: ожидалось неотрицательное целое.`);
}
return parsed;
}
function exact<T extends string | number | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new ContractError(`${label}: нарушен контракт.`);
return expected;
}
function boolean(value: unknown, label: string): boolean {
if (typeof value !== "boolean") throw new ContractError(`${label}: ожидался boolean.`);
return value;
}
function priority(value: unknown): E46DTemporalPriority {
if (value !== "critical" && value !== "high" && value !== "medium") {
throw new ContractError("E46D priority: неизвестное значение.");
}
return value;
}
function kind(value: unknown): E46DTemporalSignalKind {
if (
value !== "layer-blackout"
&& value !== "camera-evidence-hold"
&& value !== "route-layer-gap"
&& value !== "route-id-rebirth-candidate"
&& value !== "bbox-jump"
&& value !== "motion-state-flap"
&& value !== "world-binding-flap"
&& value !== "short-track-burst"
) {
throw new ContractError("E46D signal kind: неизвестное значение.");
}
return value;
}
function shaResult(value: unknown, prefix: string, label: string): string {
const parsed = string(value, label);
if (!new RegExp(`^${prefix}-[a-f0-9]{64}$`).test(parsed)) {
throw new ContractError(`${label}: нарушена идентичность.`);
}
return parsed;
}
function evidence(value: unknown): Readonly<Record<string, string | number | boolean>> {
const raw = object(value, "E46D clip evidence");
const parsed: Record<string, string | number | boolean> = {};
for (const [key, item] of Object.entries(raw)) {
if (
typeof item !== "string"
&& typeof item !== "number"
&& typeof item !== "boolean"
) {
throw new ContractError("E46D clip evidence: неизвестное значение.");
}
parsed[key] = item;
}
return parsed;
}
function parseClip(value: unknown, expectedRank: number): E46DReviewClip {
const item = object(value, "E46D review clip");
exact(item.schema_version, "missioncore.e46d-temporal-review-clip/v1", "E46D clip schema");
const rank = integer(item.rank, "E46D clip rank");
if (rank !== expectedRank) throw new ContractError("E46D clip order: нарушен контракт.");
const clipId = string(item.clip_id, "E46D clip id");
const signalId = string(item.signal_id, "E46D signal id");
if (!/^e46d-clip-\d{2}-[a-f0-9]{20}$/.test(clipId) || !/^e46d-signal-[a-f0-9]{20}$/.test(signalId)) {
throw new ContractError("E46D clip identity: нарушен контракт.");
}
const startSeconds = number(item.start_seconds, "E46D clip start");
const eventStartSeconds = number(item.event_start_seconds, "E46D event start");
const eventEndSeconds = number(item.event_end_seconds, "E46D event end");
const endSeconds = number(item.end_seconds, "E46D clip end");
if (!(startSeconds <= eventStartSeconds && eventStartSeconds <= eventEndSeconds && eventEndSeconds <= endSeconds)) {
throw new ContractError("E46D clip timeline: нарушен контракт.");
}
return {
clipId,
rank,
priority: priority(item.priority),
kind: kind(item.kind),
signalId,
startSeconds,
eventStartSeconds,
eventEndSeconds,
endSeconds,
startFrame: integer(item.start_frame, "E46D clip start frame"),
endFrame: integer(item.end_frame, "E46D clip end frame"),
routeTrackIds: array(item.route_track_ids, "E46D clip route tracks").map((entry) => integer(entry, "E46D route track")),
worldTrackIds: array(item.world_track_ids, "E46D clip world tracks").map((entry) => integer(entry, "E46D world track")),
evidence: evidence(item.evidence),
};
}
export async function fetchE46DTemporalFailureAudit({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46DTemporalFailureAuditResult | null> {
const response = await fetcher("/api/v1/laboratory/e46d/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new ContractError(`E46D LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46D catalog");
exact(
catalog.schema_version,
"missioncore.e46d-temporal-failure-audit-catalog/v1",
"E46D catalog schema",
);
const items = array(catalog.items, "E46D results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46D catalog size: нарушен контракт.");
const item = object(items[0], "E46D result");
exact(
item.schema_version,
"missioncore.e46d-temporal-failure-audit-view/v1",
"E46D view schema",
);
exact(item.ground_truth, false, "E46D truth authority");
const metrics = object(item.metrics, "E46D metrics");
const acceptance = object(item.acceptance, "E46D acceptance");
const decision = object(item.decision, "E46D decision");
const clips = array(item.review_clips, "E46D review clips").map((clip, index) => (
parseClip(clip, index + 1)
));
const result: E46DTemporalFailureAuditResult = {
resultId: shaResult(item.result_id, "e46d-temporal-failure-audit", "E46D result id"),
createdAtUtc: string(item.created_at_utc, "E46D created"),
sourceE46CResultId: shaResult(item.source_e46c_result_id, "e46c-full-replay-world-tracks", "E46D E46C source"),
sourceE26ResultId: shaResult(item.source_e26_result_id, "e10-integrated-perception", "E46D E26 source"),
metrics: {
routeFrameCount: exact(metrics.route_frame_count, 4489, "E46D route frames"),
routeSpanSeconds: number(metrics.route_span_seconds, "E46D route span"),
objectObservationCount: integer(metrics.object_observation_count, "E46D observations"),
routeTrackCount: integer(metrics.route_track_count, "E46D route tracks"),
zeroObjectFrameCount: integer(metrics.zero_object_frame_count, "E46D zero frames"),
zeroObjectFrameFraction: number(metrics.zero_object_frame_fraction, "E46D zero fraction"),
cameraHeldObservationCount: integer(metrics.camera_held_observation_count, "E46D held observations"),
cameraHeldObservationFraction: number(metrics.camera_held_observation_fraction, "E46D held fraction"),
detectorHoldEpisodeCount: integer(metrics.detector_hold_episode_count, "E46D detector holds"),
layerBlackoutEpisodeCount: integer(metrics.layer_blackout_episode_count, "E46D blackouts"),
routeLayerGapEpisodeCount: integer(metrics.route_layer_gap_episode_count, "E46D route gaps"),
routeIdRebirthCandidateCount: integer(metrics.route_id_rebirth_candidate_count, "E46D ID candidates"),
bboxJumpEpisodeCount: integer(metrics.bbox_jump_episode_count, "E46D bbox jumps"),
motionStateFlapEpisodeCount: integer(metrics.motion_state_flap_episode_count, "E46D motion flaps"),
worldBindingFlapEpisodeCount: integer(metrics.world_binding_flap_episode_count, "E46D world flaps"),
shortRouteTrackCount: integer(metrics.short_route_track_count, "E46D short tracks"),
shortRouteTrackFraction: number(metrics.short_route_track_fraction, "E46D short fraction"),
shortTrackBurstEpisodeCount: integer(metrics.short_track_burst_episode_count, "E46D short bursts"),
failureSignalCount: integer(metrics.failure_signal_count, "E46D failure signals"),
reviewClipCount: integer(metrics.review_clip_count, "E46D review clips"),
temporalContinuityPassed: boolean(metrics.temporal_continuity_passed, "E46D continuity"),
},
acceptance: {
fullRouteAccounted: exact(acceptance.full_route_accounted, true, "E46D full route"),
temporalContinuityPassed: boolean(acceptance.temporal_continuity_passed, "E46D acceptance continuity"),
independentTruthAvailable: exact(acceptance.independent_truth_available, false, "E46D truth"),
navigationOrSafetyAccepted: exact(acceptance.navigation_or_safety_accepted, false, "E46D safety"),
},
decision: {
temporalRegressionConfirmed: boolean(decision.temporal_regression_confirmed, "E46D regression"),
detectorGapVisible: boolean(decision.detector_gap_visible, "E46D detector gap"),
routeFragmentationVisible: boolean(decision.route_fragmentation_visible, "E46D fragmentation"),
worldBindingInstabilityVisible: boolean(decision.world_binding_instability_visible, "E46D world binding"),
nextAction: string(decision.next_action, "E46D next action"),
},
limitations: array(item.limitations, "E46D limitations").map((value) => string(value, "E46D limitation")),
reviewClips: clips,
};
if (result.metrics.reviewClipCount !== clips.length) {
throw new ContractError("E46D review clip accounting: нарушен контракт.");
}
return result;
}
@@ -0,0 +1,219 @@
export interface E46ELaboratoryMethod {
completeness: "complete";
executionClass: "hybrid";
pipelineId: string;
components: readonly {
kind: "source" | "tool" | "model" | "algorithm" | "runtime";
name: string;
version: string;
role: string;
identitySha256: string;
}[];
}
export interface E46EReadyStackResult {
resultId: string;
createdAtUtc: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
metrics: {
frameCount: 4489;
routeDurationSeconds: number;
detectionObservationCount: number;
trackObservationCount: number;
detectionBoxClippedCount: number;
trackBoxClippedCount: number;
uniqueTrackCount: number;
meanTrackedObjectsPerFrame: number;
zeroDetectionFrameCount: number;
zeroTrackFrameCount: number;
trackerRecoveredFrameCount: number;
fullLayerBlackoutEventCount: number;
routeIdGapEventCount: number;
shortTrackCount: number;
shortTrackFraction: number;
trackClassSwitchCount: number;
};
acceptance: {
fullRouteAccounted: true;
stockDetectorTrackerExecuted: true;
visualOverlayAvailable: true;
independentTruthAvailable: false;
navigationOrSafetyAccepted: false;
};
decision: {
readyStackBaselineAvailable: true;
customTemporalLogicUsed: false;
nextAction: string;
};
method: E46ELaboratoryMethod;
limitations: readonly string[];
video: {
url: string;
mediaType: "video/mp4";
byteLength: number;
sha256: string;
width: 800;
height: 600;
};
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new ContractError(`${label}: ожидался массив.`);
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new ContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isSafeInteger(parsed) || parsed < 0) {
throw new ContractError(`${label}: ожидалось неотрицательное целое.`);
}
return parsed;
}
function exact<T extends string | number | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new ContractError(`${label}: нарушен контракт.`);
return expected;
}
function sha(value: unknown, label: string): string {
const parsed = string(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) {
throw new ContractError(`${label}: нарушена SHA-256 идентичность.`);
}
return parsed;
}
function method(value: unknown): E46ELaboratoryMethod {
const raw = object(value, "E46E method");
exact(raw.schema_version, "missioncore.laboratory-method/v1", "E46E method schema");
exact(raw.completeness, "complete", "E46E method completeness");
exact(raw.execution_class, "hybrid", "E46E execution class");
const components = array(raw.components, "E46E method components").map((entry) => {
const component = object(entry, "E46E method component");
const kind = string(component.kind, "E46E component kind");
if (!(["source", "tool", "model", "algorithm", "runtime"] as const).includes(
kind as "source",
)) {
throw new ContractError("E46E component kind: неизвестное значение.");
}
return {
kind: kind as "source" | "tool" | "model" | "algorithm" | "runtime",
name: string(component.name, "E46E component name"),
version: string(component.version, "E46E component version"),
role: string(component.role, "E46E component role"),
identitySha256: sha(component.identity_sha256, "E46E component identity"),
};
});
return {
completeness: "complete",
executionClass: "hybrid",
pipelineId: string(raw.pipeline_id, "E46E pipeline"),
components,
};
}
export async function fetchE46EReadyStack({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46EReadyStackResult | null> {
const response = await fetcher("/api/v1/laboratory/e46e/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new ContractError(`E46E LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46E catalog");
exact(catalog.schema_version, "missioncore.e46e-ready-stack-catalog/v1", "E46E catalog schema");
const items = array(catalog.items, "E46E results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46E catalog size: нарушен контракт.");
const item = object(items[0], "E46E result");
exact(item.schema_version, "missioncore.e46e-ready-stack-view/v1", "E46E view schema");
exact(item.ground_truth, false, "E46E truth authority");
const metrics = object(item.metrics, "E46E metrics");
const acceptance = object(item.acceptance, "E46E acceptance");
const decision = object(item.decision, "E46E decision");
const video = object(item.video, "E46E video");
const resultId = string(item.result_id, "E46E result id");
if (!/^e46e-ready-stack-[a-f0-9]{64}$/.test(resultId)) {
throw new ContractError("E46E result identity: нарушен контракт.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "E46E created"),
sourceSessionId: string(item.source_session_id, "E46E source session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "E46E camera"),
metrics: {
frameCount: exact(metrics.frame_count, 4489, "E46E frames"),
routeDurationSeconds: number(metrics.route_duration_seconds, "E46E duration"),
detectionObservationCount: integer(metrics.detection_observation_count, "E46E detections"),
trackObservationCount: integer(metrics.track_observation_count, "E46E track observations"),
detectionBoxClippedCount: integer(metrics.detection_box_clipped_count, "E46E clipped detections"),
trackBoxClippedCount: integer(metrics.track_box_clipped_count, "E46E clipped tracks"),
uniqueTrackCount: integer(metrics.unique_track_count, "E46E tracks"),
meanTrackedObjectsPerFrame: number(metrics.mean_tracked_objects_per_frame, "E46E mean objects"),
zeroDetectionFrameCount: integer(metrics.zero_detection_frame_count, "E46E zero detections"),
zeroTrackFrameCount: integer(metrics.zero_track_frame_count, "E46E zero tracks"),
trackerRecoveredFrameCount: integer(metrics.tracker_recovered_frame_count, "E46E recovered frames"),
fullLayerBlackoutEventCount: integer(metrics.full_layer_blackout_event_count, "E46E blackouts"),
routeIdGapEventCount: integer(metrics.route_id_gap_event_count, "E46E ID gaps"),
shortTrackCount: integer(metrics.short_track_count, "E46E short tracks"),
shortTrackFraction: number(metrics.short_track_fraction, "E46E short fraction"),
trackClassSwitchCount: integer(metrics.track_class_switch_count, "E46E class switches"),
},
acceptance: {
fullRouteAccounted: exact(acceptance.full_route_accounted, true, "E46E full route"),
stockDetectorTrackerExecuted: exact(acceptance.stock_detector_tracker_executed, true, "E46E ready stack"),
visualOverlayAvailable: exact(acceptance.visual_overlay_available, true, "E46E visual"),
independentTruthAvailable: exact(acceptance.independent_truth_available, false, "E46E truth"),
navigationOrSafetyAccepted: exact(acceptance.navigation_or_safety_accepted, false, "E46E safety"),
},
decision: {
readyStackBaselineAvailable: exact(decision.ready_stack_baseline_available, true, "E46E baseline"),
customTemporalLogicUsed: exact(decision.custom_temporal_logic_used, false, "E46E custom logic"),
nextAction: string(decision.next_action, "E46E next action"),
},
method: method(item.method),
limitations: array(item.limitations, "E46E limitations").map((entry) => string(entry, "E46E limitation")),
video: {
url: string(video.url, "E46E video URL"),
mediaType: exact(video.media_type, "video/mp4", "E46E media type"),
byteLength: integer(video.byte_length, "E46E video bytes"),
sha256: sha(video.sha256, "E46E video SHA"),
width: exact(video.width, 800, "E46E video width"),
height: exact(video.height, 600, "E46E video height"),
},
};
}
@@ -0,0 +1,289 @@
import type { E46ELaboratoryMethod } from "./e46eReadyStack";
export interface E46FMetrics {
frameCount: 4489;
routeDurationSeconds: number;
detectionObservationCount: number;
trackObservationCount: number;
detectionBoxClippedCount: number;
trackBoxClippedCount: number;
uniqueTrackCount: number;
meanTrackedObjectsPerFrame: number;
zeroDetectionFrameCount: number;
zeroTrackFrameCount: number;
trackerRecoveredFrameCount: number;
fullLayerBlackoutEventCount: number;
routeIdGapEventCount: number;
shortTrackCount: number;
shortTrackFraction: number;
trackClassSwitchCount: number;
}
export interface E46FLargeBoxTriage {
observationCount: number;
frameCount: number;
trackIdCount: number;
classObservations: Readonly<Record<string, number>>;
}
export interface E46FDashCamBakeoffResult {
resultId: string;
createdAtUtc: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
metrics: E46FMetrics;
acceptance: {
fullRouteAccounted: true;
stockDetectorTrackerExecuted: true;
controlledDetectorOnlyChange: true;
visualOverlayAvailable: true;
independentTruthAvailable: false;
navigationOrSafetyAccepted: false;
};
method: E46ELaboratoryMethod;
limitations: readonly string[];
comparison: {
baselineResultId: string;
baselineMetrics: E46FMetrics;
delta: {
zeroTrackFrameCount: number;
fullLayerBlackoutEventCount: number;
uniqueTrackCount: number;
shortTrackFraction: number;
};
largeBoxVisualTriage: {
areaRatioThreshold: 0.2;
candidate: E46FLargeBoxTriage;
baseline: E46FLargeBoxTriage;
interpretation: string;
};
visualReview: {
status: "rejected-semantic-regression";
sampleVideoSeconds: readonly number[];
finding: string;
nextAction: string;
};
verdict: "reject-dashcamnet-on-unrectified-fisheye";
};
video: {
url: string;
mediaType: "video/mp4";
byteLength: number;
sha256: string;
width: 800;
height: 600;
};
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new ContractError(`${label}: ожидался массив.`);
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new ContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isSafeInteger(parsed) || parsed < 0) {
throw new ContractError(`${label}: ожидалось неотрицательное целое.`);
}
return parsed;
}
function exact<T extends string | number | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new ContractError(`${label}: нарушен контракт.`);
return expected;
}
function sha(value: unknown, label: string): string {
const parsed = string(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) {
throw new ContractError(`${label}: нарушена SHA-256 идентичность.`);
}
return parsed;
}
function signedNumber(value: unknown, label: string): number {
return number(value, label);
}
function metrics(value: unknown, label: string): E46FMetrics {
const raw = object(value, label);
return {
frameCount: exact(raw.frame_count, 4489, `${label} frames`),
routeDurationSeconds: number(raw.route_duration_seconds, `${label} duration`),
detectionObservationCount: integer(raw.detection_observation_count, `${label} detections`),
trackObservationCount: integer(raw.track_observation_count, `${label} track observations`),
detectionBoxClippedCount: integer(raw.detection_box_clipped_count, `${label} clipped detections`),
trackBoxClippedCount: integer(raw.track_box_clipped_count, `${label} clipped tracks`),
uniqueTrackCount: integer(raw.unique_track_count, `${label} tracks`),
meanTrackedObjectsPerFrame: number(raw.mean_tracked_objects_per_frame, `${label} mean objects`),
zeroDetectionFrameCount: integer(raw.zero_detection_frame_count, `${label} zero detections`),
zeroTrackFrameCount: integer(raw.zero_track_frame_count, `${label} zero tracks`),
trackerRecoveredFrameCount: integer(raw.tracker_recovered_frame_count, `${label} recovered`),
fullLayerBlackoutEventCount: integer(raw.full_layer_blackout_event_count, `${label} blackouts`),
routeIdGapEventCount: integer(raw.route_id_gap_event_count, `${label} ID gaps`),
shortTrackCount: integer(raw.short_track_count, `${label} short tracks`),
shortTrackFraction: number(raw.short_track_fraction, `${label} short fraction`),
trackClassSwitchCount: integer(raw.track_class_switch_count, `${label} class switches`),
};
}
function method(value: unknown): E46ELaboratoryMethod {
const raw = object(value, "E46F method");
exact(raw.schema_version, "missioncore.laboratory-method/v1", "E46F method schema");
exact(raw.completeness, "complete", "E46F method completeness");
exact(raw.execution_class, "hybrid", "E46F execution class");
const components = array(raw.components, "E46F method components").map((entry) => {
const component = object(entry, "E46F method component");
const kind = string(component.kind, "E46F component kind");
if (!(["source", "tool", "model", "algorithm", "runtime"] as const).includes(
kind as "source",
)) {
throw new ContractError("E46F component kind: неизвестное значение.");
}
return {
kind: kind as "source" | "tool" | "model" | "algorithm" | "runtime",
name: string(component.name, "E46F component name"),
version: string(component.version, "E46F component version"),
role: string(component.role, "E46F component role"),
identitySha256: sha(component.identity_sha256, "E46F component identity"),
};
});
return {
completeness: "complete",
executionClass: "hybrid",
pipelineId: string(raw.pipeline_id, "E46F pipeline"),
components,
};
}
function classObservations(value: unknown, label: string): Readonly<Record<string, number>> {
const raw = object(value, label);
return Object.fromEntries(
Object.entries(raw).map(([key, entry]) => [key, integer(entry, `${label}.${key}`)]),
);
}
function triage(value: unknown, label: string): E46FLargeBoxTriage {
const raw = object(value, label);
return {
observationCount: integer(raw.observation_count, `${label} observations`),
frameCount: integer(raw.frame_count, `${label} frames`),
trackIdCount: integer(raw.track_id_count, `${label} tracks`),
classObservations: classObservations(raw.class_observations, `${label} classes`),
};
}
export async function fetchE46FDashCamBakeoff({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46FDashCamBakeoffResult | null> {
const response = await fetcher("/api/v1/laboratory/e46f/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new ContractError(`E46F LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46F catalog");
exact(catalog.schema_version, "missioncore.e46f-dashcam-bakeoff-catalog/v1", "E46F catalog schema");
const items = array(catalog.items, "E46F results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46F catalog size: нарушен контракт.");
const item = object(items[0], "E46F result");
exact(item.schema_version, "missioncore.e46f-dashcam-bakeoff-view/v1", "E46F view schema");
exact(item.ground_truth, false, "E46F truth authority");
const resultId = string(item.result_id, "E46F result id");
if (!/^e46f-dashcam-bakeoff-[a-f0-9]{64}$/.test(resultId)) {
throw new ContractError("E46F result identity: нарушен контракт.");
}
const acceptance = object(item.acceptance, "E46F acceptance");
const comparison = object(item.comparison, "E46F comparison");
exact(comparison.controlled_change, "detector-only", "E46F controlled change");
const delta = object(comparison.delta, "E46F delta");
const largeBox = object(comparison.large_box_visual_triage, "E46F large-box triage");
const visualReview = object(comparison.visual_review, "E46F visual review");
const video = object(item.video, "E46F video");
const baselineResultId = string(comparison.baseline_result_id, "E46F baseline id");
if (!/^e46e-ready-stack-[a-f0-9]{64}$/.test(baselineResultId)) {
throw new ContractError("E46F baseline identity: нарушен контракт.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "E46F created"),
sourceSessionId: string(item.source_session_id, "E46F source session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "E46F camera"),
metrics: metrics(item.metrics, "E46F metrics"),
acceptance: {
fullRouteAccounted: exact(acceptance.full_route_accounted, true, "E46F full route"),
stockDetectorTrackerExecuted: exact(acceptance.stock_detector_tracker_executed, true, "E46F stack"),
controlledDetectorOnlyChange: exact(acceptance.controlled_detector_only_change, true, "E46F controlled change"),
visualOverlayAvailable: exact(acceptance.visual_overlay_available, true, "E46F visual"),
independentTruthAvailable: exact(acceptance.independent_truth_available, false, "E46F truth"),
navigationOrSafetyAccepted: exact(acceptance.navigation_or_safety_accepted, false, "E46F safety"),
},
method: method(item.method),
limitations: array(item.limitations, "E46F limitations").map((entry) => string(entry, "E46F limitation")),
comparison: {
baselineResultId,
baselineMetrics: metrics(comparison.baseline_metrics, "E46E baseline metrics"),
delta: {
zeroTrackFrameCount: signedNumber(delta.zero_track_frame_count, "E46F zero-track delta"),
fullLayerBlackoutEventCount: signedNumber(delta.full_layer_blackout_event_count, "E46F blackout delta"),
uniqueTrackCount: signedNumber(delta.unique_track_count, "E46F track delta"),
shortTrackFraction: signedNumber(delta.short_track_fraction, "E46F short-track delta"),
},
largeBoxVisualTriage: {
areaRatioThreshold: exact(largeBox.area_ratio_threshold, 0.2, "E46F triage threshold"),
candidate: triage(largeBox.candidate, "E46F candidate triage"),
baseline: triage(largeBox.baseline, "E46E baseline triage"),
interpretation: string(largeBox.interpretation, "E46F triage interpretation"),
},
visualReview: {
status: exact(visualReview.status, "rejected-semantic-regression", "E46F visual status"),
sampleVideoSeconds: array(visualReview.sample_video_seconds, "E46F review timestamps")
.map((entry) => number(entry, "E46F review timestamp")),
finding: string(visualReview.finding, "E46F visual finding"),
nextAction: string(visualReview.next_action, "E46F next action"),
},
verdict: exact(comparison.verdict, "reject-dashcamnet-on-unrectified-fisheye", "E46F verdict"),
},
video: {
url: string(video.url, "E46F video URL"),
mediaType: exact(video.media_type, "video/mp4", "E46F media type"),
byteLength: integer(video.byte_length, "E46F video bytes"),
sha256: sha(video.sha256, "E46F video SHA"),
width: exact(video.width, 800, "E46F video width"),
height: exact(video.height, 600, "E46F video height"),
},
};
}
@@ -0,0 +1,327 @@
import type { E46ELaboratoryMethod } from "./e46eReadyStack";
export type E46GCandidate = "trafficcamnet" | "dashcamnet";
export type E46GView = "left" | "front" | "right";
export interface E46GViewMetrics {
frameCount: 600;
detectionObservationCount: number;
trackObservationCount: number;
uniqueTrackCount: number;
meanTrackedObjectsPerFrame: number;
zeroDetectionFrameCount: number;
zeroTrackFrameCount: number;
fullLayerBlackoutEventCount: number;
shortTrackFraction: number;
largeTrackObservationCount: number;
largeTrackFraction: number;
}
export interface E46GCandidateMetrics {
sourceFrameCount: 600;
viewFrameCount: 1800;
detectionObservationCount: number;
trackObservationCount: number;
uniqueTrackCount: number;
largeTrackObservationCount: number;
largeTrackFraction: number;
views: Readonly<Record<E46GView, E46GViewMetrics>>;
}
export interface E46GVideo {
url: string;
mediaType: "video/mp4";
byteLength: number;
sha256: string;
width: 2880;
height: 544;
durationSeconds: 60;
viewOrder: readonly ["left", "front", "right"];
}
export interface E46GRectifiedDetectorBakeoffResult {
resultId: string;
createdAtUtc: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
selection: {
firstSourceFrameIndex: 1000;
lastSourceFrameIndex: 1599;
frameCount: 600;
};
rectification: {
provider: "NVIDIA Gst-nvdewarper";
providerVersion: string;
outputResolution: readonly [960, 544];
horizontalFovDegrees: 100;
retainedSourceFrameIndexRange: readonly [0, 4487];
excludedSourceTailFrameCount: 1;
viewOrder: readonly ["left", "front", "right"];
};
metrics: Readonly<Record<E46GCandidate, E46GCandidateMetrics>>;
acceptance: {
exactRecordedRightSourceBound: true;
factoryCalibrationBound: true;
officialNvidiaDewarperExecuted: true;
stockDetectorTrackerExecuted: true;
sameViewsAndFramesForBothCandidates: true;
visualComparisonVideosAvailable: true;
independentTruthAvailable: false;
candidateAccepted: false;
navigationOrSafetyAccepted: false;
};
method: E46ELaboratoryMethod;
limitations: readonly string[];
comparison: {
visualReview: {
status: "selected-for-next-diagnostic";
reviewedVideoSeconds: readonly number[];
selectedCandidate: "trafficcamnet";
selectedView: "front";
excludedViews: readonly ["left", "right"];
finding: string;
risk: string;
nextAction: string;
};
verdict: "select-trafficcamnet-front-only-for-e46h";
};
videos: Readonly<Record<E46GCandidate, E46GVideo>>;
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new ContractError(`${label}: ожидался массив.`);
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new ContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isSafeInteger(parsed) || parsed < 0) {
throw new ContractError(`${label}: ожидалось неотрицательное целое.`);
}
return parsed;
}
function exact<T extends string | number | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new ContractError(`${label}: нарушен контракт.`);
return expected;
}
function sha(value: unknown, label: string): string {
const parsed = string(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) {
throw new ContractError(`${label}: нарушена SHA-256 идентичность.`);
}
return parsed;
}
function tuple<T extends readonly unknown[]>(
value: unknown,
expected: T,
label: string,
): T {
const parsed = array(value, label);
if (parsed.length !== expected.length || parsed.some((entry, index) => entry !== expected[index])) {
throw new ContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function viewMetrics(value: unknown, label: string): E46GViewMetrics {
const raw = object(value, label);
return {
frameCount: exact(raw.frame_count, 600, `${label} frames`),
detectionObservationCount: integer(raw.detection_observation_count, `${label} detections`),
trackObservationCount: integer(raw.track_observation_count, `${label} tracks`),
uniqueTrackCount: integer(raw.unique_track_count, `${label} identities`),
meanTrackedObjectsPerFrame: number(raw.mean_tracked_objects_per_frame, `${label} mean`),
zeroDetectionFrameCount: integer(raw.zero_detection_frame_count, `${label} zero detections`),
zeroTrackFrameCount: integer(raw.zero_track_frame_count, `${label} zero tracks`),
fullLayerBlackoutEventCount: integer(raw.full_layer_blackout_event_count, `${label} blackouts`),
shortTrackFraction: number(raw.short_track_fraction, `${label} short fraction`),
largeTrackObservationCount: integer(raw.large_track_observation_count, `${label} large tracks`),
largeTrackFraction: number(raw.large_track_fraction, `${label} large fraction`),
};
}
function candidateMetrics(value: unknown, label: string): E46GCandidateMetrics {
const raw = object(value, label);
const views = object(raw.views, `${label} views`);
return {
sourceFrameCount: exact(raw.source_frame_count, 600, `${label} source frames`),
viewFrameCount: exact(raw.view_frame_count, 1800, `${label} view frames`),
detectionObservationCount: integer(raw.detection_observation_count, `${label} detections`),
trackObservationCount: integer(raw.track_observation_count, `${label} tracks`),
uniqueTrackCount: integer(raw.unique_track_count, `${label} identities`),
largeTrackObservationCount: integer(raw.large_track_observation_count, `${label} large tracks`),
largeTrackFraction: number(raw.large_track_fraction, `${label} large fraction`),
views: {
left: viewMetrics(views.left, `${label} left`),
front: viewMetrics(views.front, `${label} front`),
right: viewMetrics(views.right, `${label} right`),
},
};
}
function method(value: unknown): E46ELaboratoryMethod {
const raw = object(value, "E46G method");
exact(raw.schema_version, "missioncore.laboratory-method/v1", "E46G method schema");
exact(raw.completeness, "complete", "E46G method completeness");
exact(raw.execution_class, "hybrid", "E46G execution class");
const components = array(raw.components, "E46G method components").map((entry) => {
const component = object(entry, "E46G method component");
const kind = string(component.kind, "E46G component kind");
if (!("source tool model algorithm runtime".split(" ")).includes(kind)) {
throw new ContractError("E46G component kind: неизвестное значение.");
}
return {
kind: kind as "source" | "tool" | "model" | "algorithm" | "runtime",
name: string(component.name, "E46G component name"),
version: string(component.version, "E46G component version"),
role: string(component.role, "E46G component role"),
identitySha256: sha(component.identity_sha256, "E46G component identity"),
};
});
return {
completeness: "complete",
executionClass: "hybrid",
pipelineId: string(raw.pipeline_id, "E46G pipeline"),
components,
};
}
function video(value: unknown, label: string): E46GVideo {
const raw = object(value, label);
return {
url: string(raw.url, `${label} URL`),
mediaType: exact(raw.media_type, "video/mp4", `${label} media`),
byteLength: integer(raw.byte_length, `${label} bytes`),
sha256: sha(raw.sha256, `${label} SHA`),
width: exact(raw.width, 2880, `${label} width`),
height: exact(raw.height, 544, `${label} height`),
durationSeconds: exact(raw.duration_seconds, 60, `${label} duration`),
viewOrder: tuple(raw.view_order, ["left", "front", "right"] as const, `${label} views`),
};
}
export async function fetchE46GRectifiedDetectorBakeoff({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46GRectifiedDetectorBakeoffResult | null> {
const response = await fetcher("/api/v1/laboratory/e46g/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new ContractError(`E46G LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46G catalog");
exact(catalog.schema_version, "missioncore.e46g-rectified-detector-bakeoff-catalog/v1", "E46G catalog schema");
const items = array(catalog.items, "E46G results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46G catalog size: нарушен контракт.");
const item = object(items[0], "E46G result");
exact(item.schema_version, "missioncore.e46g-rectified-detector-bakeoff-view/v1", "E46G view schema");
exact(item.status, "selected-for-next-diagnostic-full-route", "E46G status");
exact(item.ground_truth, false, "E46G truth authority");
const resultId = string(item.result_id, "E46G result id");
if (!/^e46g-rectified-detector-bakeoff-[a-f0-9]{64}$/.test(resultId)) {
throw new ContractError("E46G result identity: нарушен контракт.");
}
const selection = object(item.selection, "E46G selection");
const rectification = object(item.rectification, "E46G rectification");
const metrics = object(item.metrics, "E46G metrics");
const acceptance = object(item.acceptance, "E46G acceptance");
const comparison = object(item.comparison, "E46G comparison");
const review = object(comparison.visual_review, "E46G visual review");
const videos = object(item.videos, "E46G videos");
const authority = object(item.authority, "E46G authority");
exact(authority.ground_truth, false, "E46G authority ground truth");
exact(authority.independent_truth, false, "E46G authority independent truth");
exact(authority.candidate_accepted, false, "E46G authority candidate");
exact(authority.commands_enabled, false, "E46G authority commands");
exact(authority.navigation_or_safety_accepted, false, "E46G authority safety");
return {
resultId,
createdAtUtc: string(item.created_at_utc, "E46G created"),
sourceSessionId: string(item.source_session_id, "E46G source session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "E46G camera"),
selection: {
firstSourceFrameIndex: exact(selection.first_source_frame_index, 1000, "E46G first frame"),
lastSourceFrameIndex: exact(selection.last_source_frame_index, 1599, "E46G last frame"),
frameCount: exact(selection.frame_count, 600, "E46G frame count"),
},
rectification: {
provider: exact(rectification.provider, "NVIDIA Gst-nvdewarper", "E46G dewarper"),
providerVersion: string(rectification.provider_version, "E46G dewarper version"),
outputResolution: tuple(rectification.output_resolution, [960, 544] as const, "E46G output"),
horizontalFovDegrees: exact(rectification.horizontal_fov_degrees, 100, "E46G FOV"),
retainedSourceFrameIndexRange: tuple(rectification.retained_source_frame_index_range, [0, 4487] as const, "E46G retained source"),
excludedSourceTailFrameCount: exact(rectification.excluded_source_tail_frame_count, 1, "E46G excluded tail"),
viewOrder: tuple(rectification.view_order, ["left", "front", "right"] as const, "E46G views"),
},
metrics: {
trafficcamnet: candidateMetrics(metrics.trafficcamnet, "TrafficCamNet"),
dashcamnet: candidateMetrics(metrics.dashcamnet, "DashCamNet"),
},
acceptance: {
exactRecordedRightSourceBound: exact(acceptance.exact_recorded_right_source_bound, true, "E46G source"),
factoryCalibrationBound: exact(acceptance.factory_calibration_bound, true, "E46G calibration"),
officialNvidiaDewarperExecuted: exact(acceptance.official_nvidia_dewarper_executed, true, "E46G dewarper execution"),
stockDetectorTrackerExecuted: exact(acceptance.stock_detector_tracker_executed, true, "E46G stock stack"),
sameViewsAndFramesForBothCandidates: exact(acceptance.same_views_and_frames_for_both_candidates, true, "E46G controlled A/B"),
visualComparisonVideosAvailable: exact(acceptance.visual_comparison_videos_available, true, "E46G videos"),
independentTruthAvailable: exact(acceptance.independent_truth_available, false, "E46G truth"),
candidateAccepted: exact(acceptance.candidate_accepted, false, "E46G acceptance authority"),
navigationOrSafetyAccepted: exact(acceptance.navigation_or_safety_accepted, false, "E46G safety"),
},
method: method(item.method),
limitations: array(item.limitations, "E46G limitations").map((entry) => string(entry, "E46G limitation")),
comparison: {
visualReview: {
status: exact(review.status, "selected-for-next-diagnostic", "E46G review status"),
reviewedVideoSeconds: array(review.reviewed_video_seconds, "E46G review seconds").map((entry) => number(entry, "E46G review second")),
selectedCandidate: exact(review.selected_candidate, "trafficcamnet", "E46G candidate"),
selectedView: exact(review.selected_view, "front", "E46G selected view"),
excludedViews: tuple(review.excluded_views, ["left", "right"] as const, "E46G excluded views"),
finding: string(review.finding, "E46G finding"),
risk: string(review.risk, "E46G risk"),
nextAction: string(review.next_action, "E46G next action"),
},
verdict: exact(comparison.verdict, "select-trafficcamnet-front-only-for-e46h", "E46G verdict"),
},
videos: {
trafficcamnet: video(videos.trafficcamnet, "TrafficCamNet video"),
dashcamnet: video(videos.dashcamnet, "DashCamNet video"),
},
};
}
@@ -0,0 +1,325 @@
import type { E46ELaboratoryMethod } from "./e46eReadyStack";
export interface E46HReviewWindow {
id: string;
label: string;
startSeconds: number;
endSeconds: number;
sourceTrackId: number | null;
verdict: "semantic-false-positive" | "empty-scene-expected";
}
export interface E46HFullRectifiedFrontReplayResult {
resultId: string;
createdAtUtc: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
baselineResultId: string;
selection: {
firstSourceFrameIndex: 0;
lastSourceFrameIndex: 4487;
frameCount: 4488;
excludedSourceTailFrameCount: 1;
};
rectification: {
provider: "NVIDIA Gst-nvdewarper";
providerVersion: string;
projection: "fisheye-to-perspective";
view: "front";
outputResolution: readonly [960, 544];
horizontalFovDegrees: 100;
};
metrics: {
frameCount: 4488;
routeDurationSeconds: number;
detectionObservationCount: number;
trackObservationCount: number;
uniqueTrackCount: number;
meanTrackedObjectsPerFrame: number;
zeroDetectionFrameCount: number;
zeroTrackFrameCount: number;
trackerRecoveredFrameCount: number;
fullLayerBlackoutEventCount: number;
routeIdGapEventCount: number;
shortTrackCount: number;
shortTrackFraction: number;
trackClassSwitchCount: number;
largeTrackObservationCount: number;
largeTrackFraction: number;
};
acceptance: {
exactRecordedRightSourceBound: true;
factoryCalibrationBound: true;
officialNvidiaDewarperExecuted: true;
selectedStockDetectorTrackerExecuted: true;
retainedRouteAccounted: true;
terminalSourceFrameExcluded: true;
fullVisualReviewCompleted: false;
independentTruthAvailable: false;
candidateAccepted: false;
navigationOrSafetyAccepted: false;
};
decision: {
selectedProvider: "front-trafficcamnet-stock-nvdcf";
customDetectorOrTrackerLogicUsed: false;
providerPromoted: false;
nextAction: string;
};
method: E46ELaboratoryMethod;
limitations: readonly string[];
visualReview: {
status: "full-continuous-and-targeted-review-completed";
completeVideoReviewed: true;
reviewedVideoRangeSeconds: readonly [0, 448.8];
verdict: "useful-front-continuity-but-semantic-regression-blocks-promotion";
reviewWindows: readonly E46HReviewWindow[];
finding: string;
blackoutInterpretation: string;
nextAction: string;
};
video: {
url: string;
mediaType: "video/mp4";
byteLength: number;
sha256: string;
width: 960;
height: 544;
durationSeconds: 448.8;
};
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new ContractError(`${label}: ожидался массив.`);
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new ContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isSafeInteger(parsed) || parsed < 0) {
throw new ContractError(`${label}: ожидалось неотрицательное целое.`);
}
return parsed;
}
function exact<T extends string | number | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new ContractError(`${label}: нарушен контракт.`);
return expected;
}
function sha(value: unknown, label: string): string {
const parsed = string(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) {
throw new ContractError(`${label}: нарушена SHA-256 идентичность.`);
}
return parsed;
}
function method(value: unknown): E46ELaboratoryMethod {
const raw = object(value, "E46H method");
exact(raw.schema_version, "missioncore.laboratory-method/v1", "E46H method schema");
exact(raw.completeness, "complete", "E46H method completeness");
exact(raw.execution_class, "hybrid", "E46H execution class");
const components = array(raw.components, "E46H method components").map((entry) => {
const component = object(entry, "E46H method component");
const kind = string(component.kind, "E46H component kind");
if (!("source tool model algorithm runtime".split(" ")).includes(kind)) {
throw new ContractError("E46H component kind: неизвестное значение.");
}
return {
kind: kind as "source" | "tool" | "model" | "algorithm" | "runtime",
name: string(component.name, "E46H component name"),
version: string(component.version, "E46H component version"),
role: string(component.role, "E46H component role"),
identitySha256: sha(component.identity_sha256, "E46H component identity"),
};
});
return {
completeness: "complete",
executionClass: "hybrid",
pipelineId: string(raw.pipeline_id, "E46H pipeline"),
components,
};
}
function reviewWindow(value: unknown): E46HReviewWindow {
const raw = object(value, "E46H review window");
const sourceTrackId = raw.source_track_id === null
? null
: integer(raw.source_track_id, "E46H review track");
const verdict = raw.verdict;
if (verdict !== "semantic-false-positive" && verdict !== "empty-scene-expected") {
throw new ContractError("E46H review verdict: неизвестное значение.");
}
const startSeconds = number(raw.start_seconds, "E46H review start");
const endSeconds = number(raw.end_seconds, "E46H review end");
if (startSeconds < 0 || endSeconds <= startSeconds || endSeconds > 448.8) {
throw new ContractError("E46H review window: нарушен диапазон.");
}
return {
id: string(raw.id, "E46H review id"),
label: string(raw.label, "E46H review label"),
startSeconds,
endSeconds,
sourceTrackId,
verdict,
};
}
export async function fetchE46HFullRectifiedFrontReplay({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46HFullRectifiedFrontReplayResult | null> {
const response = await fetcher("/api/v1/laboratory/e46h/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new ContractError(`E46H LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46H catalog");
exact(catalog.schema_version, "missioncore.e46h-full-rectified-front-replay-catalog/v1", "E46H catalog schema");
const items = array(catalog.items, "E46H results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46H catalog size: нарушен контракт.");
const item = object(items[0], "E46H result");
exact(item.schema_version, "missioncore.e46h-full-rectified-front-replay-view/v1", "E46H view schema");
exact(item.status, "diagnostic-regression-large-semantic-false-tracks", "E46H status");
exact(item.ground_truth, false, "E46H truth authority");
const resultId = string(item.result_id, "E46H result id");
if (!/^e46h-full-rectified-front-replay-[a-f0-9]{64}$/.test(resultId)) {
throw new ContractError("E46H result identity: нарушен контракт.");
}
const selection = object(item.selection, "E46H selection");
const rectification = object(item.rectification, "E46H rectification");
const metrics = object(item.metrics, "E46H metrics");
const acceptance = object(item.acceptance, "E46H acceptance");
const decision = object(item.decision, "E46H decision");
const visualReview = object(item.visual_review, "E46H visual review");
const video = object(item.video, "E46H video");
const authority = object(item.authority, "E46H authority");
exact(authority.ground_truth, false, "E46H authority ground truth");
exact(authority.independent_truth, false, "E46H authority independent truth");
exact(authority.candidate_accepted, false, "E46H authority candidate");
exact(authority.commands_enabled, false, "E46H authority commands");
exact(authority.navigation_or_safety_accepted, false, "E46H authority safety");
return {
resultId,
createdAtUtc: string(item.created_at_utc, "E46H created"),
sourceSessionId: string(item.source_session_id, "E46H source session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "E46H camera"),
baselineResultId: string(item.baseline_result_id, "E46H baseline"),
selection: {
firstSourceFrameIndex: exact(selection.first_source_frame_index, 0, "E46H first frame"),
lastSourceFrameIndex: exact(selection.last_source_frame_index, 4487, "E46H last frame"),
frameCount: exact(selection.frame_count, 4488, "E46H frame count"),
excludedSourceTailFrameCount: exact(selection.excluded_source_tail_frame_count, 1, "E46H excluded tail"),
},
rectification: {
provider: exact(rectification.provider, "NVIDIA Gst-nvdewarper", "E46H dewarper"),
providerVersion: string(rectification.provider_version, "E46H dewarper version"),
projection: exact(rectification.projection, "fisheye-to-perspective", "E46H projection"),
view: exact(rectification.view, "front", "E46H view"),
outputResolution: (() => {
const parsed = array(rectification.output_resolution, "E46H output");
if (parsed.length !== 2 || parsed[0] !== 960 || parsed[1] !== 544) {
throw new ContractError("E46H output: нарушен контракт.");
}
return [960, 544] as const;
})(),
horizontalFovDegrees: exact(rectification.horizontal_fov_degrees, 100, "E46H FOV"),
},
metrics: {
frameCount: exact(metrics.frame_count, 4488, "E46H metric frames"),
routeDurationSeconds: number(metrics.route_duration_seconds, "E46H source duration"),
detectionObservationCount: integer(metrics.detection_observation_count, "E46H detections"),
trackObservationCount: integer(metrics.track_observation_count, "E46H tracks"),
uniqueTrackCount: integer(metrics.unique_track_count, "E46H identities"),
meanTrackedObjectsPerFrame: number(metrics.mean_tracked_objects_per_frame, "E46H mean"),
zeroDetectionFrameCount: integer(metrics.zero_detection_frame_count, "E46H zero detections"),
zeroTrackFrameCount: integer(metrics.zero_track_frame_count, "E46H zero tracks"),
trackerRecoveredFrameCount: integer(metrics.tracker_recovered_frame_count, "E46H recovered"),
fullLayerBlackoutEventCount: integer(metrics.full_layer_blackout_event_count, "E46H blackouts"),
routeIdGapEventCount: integer(metrics.route_id_gap_event_count, "E46H id gaps"),
shortTrackCount: integer(metrics.short_track_count, "E46H short tracks"),
shortTrackFraction: number(metrics.short_track_fraction, "E46H short fraction"),
trackClassSwitchCount: integer(metrics.track_class_switch_count, "E46H class switches"),
largeTrackObservationCount: integer(metrics.large_track_observation_count, "E46H large tracks"),
largeTrackFraction: number(metrics.large_track_fraction, "E46H large fraction"),
},
acceptance: {
exactRecordedRightSourceBound: exact(acceptance.exact_recorded_right_source_bound, true, "E46H source"),
factoryCalibrationBound: exact(acceptance.factory_calibration_bound, true, "E46H calibration"),
officialNvidiaDewarperExecuted: exact(acceptance.official_nvidia_dewarper_executed, true, "E46H dewarper execution"),
selectedStockDetectorTrackerExecuted: exact(acceptance.selected_stock_detector_tracker_executed, true, "E46H stock stack"),
retainedRouteAccounted: exact(acceptance.retained_route_accounted, true, "E46H retained route"),
terminalSourceFrameExcluded: exact(acceptance.terminal_source_frame_excluded, true, "E46H tail"),
fullVisualReviewCompleted: exact(acceptance.full_visual_review_completed, false, "E46H visual review authority"),
independentTruthAvailable: exact(acceptance.independent_truth_available, false, "E46H truth"),
candidateAccepted: exact(acceptance.candidate_accepted, false, "E46H candidate"),
navigationOrSafetyAccepted: exact(acceptance.navigation_or_safety_accepted, false, "E46H safety"),
},
decision: {
selectedProvider: exact(decision.selected_provider, "front-trafficcamnet-stock-nvdcf", "E46H provider"),
customDetectorOrTrackerLogicUsed: exact(decision.custom_detector_or_tracker_logic_used, false, "E46H custom logic"),
providerPromoted: exact(decision.provider_promoted, false, "E46H promotion"),
nextAction: string(decision.next_action, "E46H decision"),
},
method: method(item.method),
limitations: array(item.limitations, "E46H limitations").map((entry) => string(entry, "E46H limitation")),
visualReview: {
status: exact(visualReview.status, "full-continuous-and-targeted-review-completed", "E46H review status"),
completeVideoReviewed: exact(visualReview.complete_video_reviewed, true, "E46H complete video review"),
reviewedVideoRangeSeconds: (() => {
const parsed = array(visualReview.reviewed_video_range_seconds, "E46H reviewed video range");
if (parsed.length !== 2 || parsed[0] !== 0 || parsed[1] !== 448.8) {
throw new ContractError("E46H reviewed video range: нарушен контракт.");
}
return [0, 448.8] as const;
})(),
verdict: exact(visualReview.verdict, "useful-front-continuity-but-semantic-regression-blocks-promotion", "E46H review verdict"),
reviewWindows: array(visualReview.review_windows, "E46H review windows").map(reviewWindow),
finding: string(visualReview.finding, "E46H finding"),
blackoutInterpretation: string(visualReview.blackout_interpretation, "E46H blackout interpretation"),
nextAction: string(visualReview.next_action, "E46H next action"),
},
video: {
url: string(video.url, "E46H video URL"),
mediaType: exact(video.media_type, "video/mp4", "E46H video media"),
byteLength: integer(video.byte_length, "E46H video bytes"),
sha256: sha(video.sha256, "E46H video SHA"),
width: exact(video.width, 960, "E46H video width"),
height: exact(video.height, 544, "E46H video height"),
durationSeconds: exact(video.duration_seconds, 448.8, "E46H video duration"),
},
};
}
@@ -0,0 +1,350 @@
import type { E46ELaboratoryMethod } from "./e46eReadyStack";
export interface E46IReviewWindow {
id: string;
label: string;
startSeconds: number;
endSeconds: number;
verdict:
| "legacy-background-false-positive-suppressed"
| "empty-scene-mostly-preserved";
}
export interface E46IGroundingDinoFullReplayResult {
resultId: string;
createdAtUtc: string;
baselineResultId: string;
source: {
cameraSourceId: "sensor.camera.right";
sessionId: string;
view: "front";
resolution: readonly [960, 544];
frameCount: 4488;
frameRate: 10;
durationSeconds: 448.8;
};
provider: {
name: "NVIDIA TAO Grounding DINO Swin-Tiny Commercial";
version: "1.0";
toolkit: "NVIDIA TAO Toolkit Deploy 7.0.1";
precision: "FP16";
};
inference: {
captions: readonly ["car", "person", "bicycle", "road sign"];
confidenceThreshold: 0.5;
meanFramesPerSecond: number;
};
metrics: {
frameCount: 4488;
detectionObservationCount: number;
classObservationCounts: Readonly<Record<string, number>>;
meanDetectionsPerFrame: number;
maxDetectionsPerFrame: number;
zeroDetectionFrameCount: number;
longestZeroDetectionRunFrames: number;
confidenceMean: number;
largeBoxObservationCount: number;
largeBoxObservationFraction: number;
workerElapsedSeconds: number;
workerMeanFramesPerSecond: number;
};
shadowGate: {
legacyCases: 5;
suppressedCases: 5;
positiveCases: 5;
positiveCasesWithRelevantDetection: 5;
limitations: readonly string[];
};
visualReview: {
completeVideoPlaybackCompleted: true;
reviewedRangeSeconds: readonly [0, 448.8];
verdict: "material-semantic-progress-not-yet-complete-perception";
reviewWindows: readonly E46IReviewWindow[];
finding: string;
knownError: string;
};
decision: {
selectedProvider: "nvidia-grounding-dino-swin-tiny-commercial-v1.0";
providerSemanticProgress: true;
providerPromoted: false;
nextAction: string;
};
method: E46ELaboratoryMethod;
limitations: readonly string[];
video: {
url: string;
mediaType: "video/mp4";
byteLength: number;
sha256: string;
width: 960;
height: 544;
frameRate: 10;
frameCount: 4488;
durationSeconds: 448.8;
};
visuals: {
shadowGate: VisualArtifact;
fullRoute: VisualArtifact;
targetedWindows: VisualArtifact;
};
}
interface VisualArtifact {
url: string;
mediaType: "image/png";
byteLength: number;
sha256: string;
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new ContractError(`${label}: ожидался массив.`);
return value;
}
function text(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new ContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isSafeInteger(parsed) || parsed < 0) {
throw new ContractError(`${label}: ожидалось неотрицательное целое.`);
}
return parsed;
}
function exact<T extends string | number | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new ContractError(`${label}: нарушен контракт.`);
return expected;
}
function sha(value: unknown, label: string): string {
const parsed = text(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) {
throw new ContractError(`${label}: нарушена SHA-256 идентичность.`);
}
return parsed;
}
function pair<const T extends readonly [number, number]>(
value: unknown,
expected: T,
label: string,
): T {
const parsed = array(value, label);
if (parsed.length !== 2 || parsed[0] !== expected[0] || parsed[1] !== expected[1]) {
throw new ContractError(`${label}: нарушен диапазон.`);
}
return expected;
}
function method(value: unknown): E46ELaboratoryMethod {
const raw = object(value, "E46I method");
exact(raw.schema_version, "missioncore.laboratory-method/v1", "E46I method schema");
exact(raw.completeness, "complete", "E46I method completeness");
exact(raw.execution_class, "hybrid", "E46I method execution");
return {
completeness: "complete",
executionClass: "hybrid",
pipelineId: text(raw.pipeline_id, "E46I pipeline"),
components: array(raw.components, "E46I components").map((entry) => {
const component = object(entry, "E46I component");
const kind = text(component.kind, "E46I component kind");
if (!("source tool model algorithm runtime".split(" ")).includes(kind)) {
throw new ContractError("E46I component kind: неизвестное значение.");
}
return {
kind: kind as "source" | "tool" | "model" | "algorithm" | "runtime",
name: text(component.name, "E46I component name"),
version: text(component.version, "E46I component version"),
role: text(component.role, "E46I component role"),
identitySha256: sha(component.identity_sha256, "E46I component identity"),
};
}),
};
}
function visual(value: unknown, label: string): VisualArtifact {
const raw = object(value, label);
return {
url: text(raw.url, `${label} URL`),
mediaType: exact(raw.media_type, "image/png", `${label} media`),
byteLength: integer(raw.byte_length, `${label} bytes`),
sha256: sha(raw.sha256, `${label} SHA`),
};
}
function reviewWindow(value: unknown): E46IReviewWindow {
const raw = object(value, "E46I review window");
const verdict = raw.verdict;
if (
verdict !== "legacy-background-false-positive-suppressed"
&& verdict !== "empty-scene-mostly-preserved"
) {
throw new ContractError("E46I review verdict: неизвестное значение.");
}
const startSeconds = number(raw.start_seconds, "E46I review start");
const endSeconds = number(raw.end_seconds, "E46I review end");
if (startSeconds < 0 || endSeconds <= startSeconds || endSeconds > 448.8) {
throw new ContractError("E46I review window: нарушен диапазон.");
}
return {
id: text(raw.id, "E46I review id"),
label: text(raw.label, "E46I review label"),
startSeconds,
endSeconds,
verdict,
};
}
export async function fetchE46IGroundingDinoFullReplay({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46IGroundingDinoFullReplayResult | null> {
const response = await fetcher("/api/v1/laboratory/e46i/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new ContractError(`E46I LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46I catalog");
exact(catalog.schema_version, "missioncore.e46i-grounding-dino-full-replay-catalog/v1", "E46I catalog schema");
const items = array(catalog.items, "E46I results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46I catalog size: нарушен контракт.");
const item = object(items[0], "E46I result");
exact(item.schema_version, "missioncore.e46i-grounding-dino-full-replay-view/v1", "E46I view schema");
exact(item.status, "semantic-regression-suppressed-awaiting-temporal-layer", "E46I status");
exact(item.ground_truth, false, "E46I truth authority");
const authority = object(item.authority, "E46I authority");
exact(authority.ground_truth, false, "E46I authority truth");
exact(authority.independent_truth, false, "E46I independent truth");
exact(authority.candidate_accepted, false, "E46I acceptance");
exact(authority.commands_enabled, false, "E46I commands");
exact(authority.navigation_or_safety_accepted, false, "E46I safety");
const resultId = text(item.result_id, "E46I result id");
if (!/^e46i-grounding-dino-full-replay-[a-f0-9]{64}$/.test(resultId)) {
throw new ContractError("E46I result identity: нарушен контракт.");
}
const source = object(item.source, "E46I source");
const provider = object(item.provider, "E46I provider");
const inference = object(item.inference, "E46I inference");
const metrics = object(item.metrics, "E46I metrics");
const shadow = object(item.shadow_gate, "E46I shadow gate");
const review = object(item.visual_review, "E46I visual review");
const decision = object(item.decision, "E46I decision");
const video = object(item.video, "E46I video");
const visuals = object(item.visuals, "E46I visuals");
const captions = array(inference.captions, "E46I captions");
if (captions.join("|") !== "car|person|bicycle|road sign") {
throw new ContractError("E46I captions: нарушен контракт.");
}
const classCounts = object(metrics.class_observation_counts, "E46I class counts");
return {
resultId,
createdAtUtc: text(item.created_at_utc, "E46I created"),
baselineResultId: text(item.baseline_result_id, "E46I baseline"),
source: {
cameraSourceId: exact(source.camera_source_id, "sensor.camera.right", "E46I camera"),
sessionId: text(source.session_id, "E46I session"),
view: exact(source.view, "front", "E46I view"),
resolution: pair(source.projection_resolution, [960, 544], "E46I resolution"),
frameCount: exact(source.video_frame_count, 4488, "E46I frames"),
frameRate: exact(source.video_frame_rate, 10, "E46I fps"),
durationSeconds: exact(source.video_duration_seconds, 448.8, "E46I duration"),
},
provider: {
name: exact(provider.name, "NVIDIA TAO Grounding DINO Swin-Tiny Commercial", "E46I provider"),
version: exact(provider.version, "1.0", "E46I provider version"),
toolkit: exact(provider.deployment_toolkit, "NVIDIA TAO Toolkit Deploy 7.0.1", "E46I toolkit"),
precision: exact(provider.engine_precision, "FP16", "E46I precision"),
},
inference: {
captions: ["car", "person", "bicycle", "road sign"],
confidenceThreshold: exact(inference.confidence_threshold, 0.5, "E46I threshold"),
meanFramesPerSecond: number(inference.mean_frames_per_second, "E46I inference fps"),
},
metrics: {
frameCount: exact(metrics.frame_count, 4488, "E46I metric frames"),
detectionObservationCount: integer(metrics.detection_observation_count, "E46I detections"),
classObservationCounts: Object.fromEntries(
Object.entries(classCounts).map(([key, value]) => [key, integer(value, `E46I ${key}`)]),
),
meanDetectionsPerFrame: number(metrics.mean_detections_per_frame, "E46I mean"),
maxDetectionsPerFrame: integer(metrics.max_detections_per_frame, "E46I max"),
zeroDetectionFrameCount: integer(metrics.zero_detection_frame_count, "E46I zero"),
longestZeroDetectionRunFrames: integer(metrics.longest_zero_detection_run_frames, "E46I zero run"),
confidenceMean: number(metrics.confidence_mean, "E46I confidence"),
largeBoxObservationCount: integer(metrics.large_box_observation_count, "E46I large boxes"),
largeBoxObservationFraction: number(metrics.large_box_observation_fraction, "E46I large fraction"),
workerElapsedSeconds: number(metrics.worker_elapsed_seconds, "E46I elapsed"),
workerMeanFramesPerSecond: number(metrics.worker_mean_frames_per_second, "E46I worker fps"),
},
shadowGate: {
legacyCases: exact(shadow.legacy_large_false_background_cases, 5, "E46I legacy cases"),
suppressedCases: exact(shadow.legacy_large_false_background_cases_suppressed, 5, "E46I suppressed"),
positiveCases: exact(shadow.positive_anchor_cases, 5, "E46I positives"),
positiveCasesWithRelevantDetection: exact(shadow.positive_anchor_cases_with_relevant_detection, 5, "E46I retained positives"),
limitations: array(shadow.known_semantic_limitations, "E46I gate limitations").map((entry) => text(entry, "E46I gate limitation")),
},
visualReview: {
completeVideoPlaybackCompleted: exact(review.complete_video_playback_completed, true, "E46I playback"),
reviewedRangeSeconds: pair(review.reviewed_video_range_seconds, [0, 448.8], "E46I reviewed range"),
verdict: exact(review.verdict, "material-semantic-progress-not-yet-complete-perception", "E46I verdict"),
reviewWindows: array(review.review_windows, "E46I review windows").map(reviewWindow),
finding: text(review.finding, "E46I finding"),
knownError: text(review.known_error, "E46I known error"),
},
decision: {
selectedProvider: exact(decision.selected_provider, "nvidia-grounding-dino-swin-tiny-commercial-v1.0", "E46I selected provider"),
providerSemanticProgress: exact(decision.provider_semantic_progress, true, "E46I progress"),
providerPromoted: exact(decision.provider_promoted, false, "E46I promotion"),
nextAction: text(decision.next_action, "E46I next action"),
},
method: method(item.method),
limitations: array(item.limitations, "E46I limitations").map((entry) => text(entry, "E46I limitation")),
video: {
url: text(video.url, "E46I video URL"),
mediaType: exact(video.media_type, "video/mp4", "E46I video media"),
byteLength: integer(video.byte_length, "E46I video bytes"),
sha256: sha(video.sha256, "E46I video SHA"),
width: exact(video.width, 960, "E46I video width"),
height: exact(video.height, 544, "E46I video height"),
frameRate: exact(video.frame_rate, 10, "E46I video fps"),
frameCount: exact(video.frame_count, 4488, "E46I video frames"),
durationSeconds: exact(video.duration_seconds, 448.8, "E46I video duration"),
},
visuals: {
shadowGate: visual(visuals.shadow_gate, "E46I shadow visual"),
fullRoute: visual(visuals.full_route, "E46I route visual"),
targetedWindows: visual(visuals.targeted_windows, "E46I targeted visual"),
},
};
}
@@ -0,0 +1,338 @@
import type { E46ELaboratoryMethod } from "./e46eReadyStack";
export interface E46JReviewWindow {
id: string;
label: string;
startSeconds: number;
endSeconds: number;
verdict:
| "legacy-background-false-positive-suppressed"
| "operator-shadow-person-false-positive-observed";
}
interface VisualArtifact {
url: string;
mediaType: "image/png";
byteLength: number;
sha256: string;
}
export interface E46JRawFisheyeRealtimeResult {
resultId: string;
createdAtUtc: string;
source: {
cameraSourceId: "sensor.camera.right";
sessionId: string;
resolution: readonly [800, 600];
frameCount: 4489;
frameRate: number;
durationSeconds: 448.723;
calibrationModel: "KB4";
};
detector: {
architecture: "YOLOX-S";
source: string;
license: "Apache-2.0";
runtime: string;
};
detection: {
minimumScore: 0.5;
nmsIouThreshold: 0.45;
};
metrics: {
frameCount: 4489;
failedFrameCount: 0;
detectionObservationCount: number;
classObservationCounts: Readonly<Record<string, number>>;
meanDetectionsPerFrame: number;
maxDetectionsPerFrame: number;
zeroDetectionFrameCount: number;
longestZeroDetectionRunFrames: number;
coreCapacityFps: number;
corePathMeanMs: number;
corePathP95Ms: number;
inferenceRequestMeanMs: number;
inferenceRequestP95Ms: number;
gpuUtilizationMeanPercent: number;
operatorShadowWindowFrameCount: number;
operatorShadowPersonFrameCount: number;
};
visualReview: {
reviewedRangeSeconds: readonly [0, 448.723];
verdict: "realtime-detector-progress-with-known-shadow-exception";
reviewWindows: readonly E46JReviewWindow[];
finding: string;
knownError: string;
};
decision: {
selectedProvider: "megvii-yolox-s-0.1.1rc0";
realtimeCapacityPassed: true;
readyForTemporalBakeoff: true;
providerPromoted: false;
nextAction: string;
};
method: E46ELaboratoryMethod;
limitations: readonly string[];
video: {
url: string;
mediaType: "video/mp4";
byteLength: number;
sha256: string;
width: 800;
height: 600;
frameRate: number;
frameCount: 4489;
durationSeconds: 448.723;
};
visuals: {
fullRoute: VisualArtifact;
targetedWindows: VisualArtifact;
operatorShadow: VisualArtifact;
};
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
class ContractError extends Error {}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new ContractError(`${label}: ожидался массив.`);
return value;
}
function text(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function number(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new ContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isSafeInteger(parsed) || parsed < 0) {
throw new ContractError(`${label}: ожидалось неотрицательное целое.`);
}
return parsed;
}
function exact<T extends string | number | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new ContractError(`${label}: нарушен контракт.`);
return expected;
}
function sha(value: unknown, label: string): string {
const parsed = text(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) {
throw new ContractError(`${label}: нарушена SHA-256 идентичность.`);
}
return parsed;
}
function pair<const T extends readonly [number, number]>(
value: unknown,
expected: T,
label: string,
): T {
const parsed = array(value, label);
if (parsed.length !== 2 || parsed[0] !== expected[0] || parsed[1] !== expected[1]) {
throw new ContractError(`${label}: нарушен диапазон.`);
}
return expected;
}
function visual(value: unknown, label: string): VisualArtifact {
const raw = object(value, label);
return {
url: text(raw.url, `${label} URL`),
mediaType: exact(raw.media_type, "image/png", `${label} media`),
byteLength: integer(raw.byte_length, `${label} bytes`),
sha256: sha(raw.sha256, `${label} SHA`),
};
}
function method(value: unknown): E46ELaboratoryMethod {
const raw = object(value, "E46J method");
exact(raw.schema_version, "missioncore.laboratory-method/v1", "E46J method schema");
exact(raw.completeness, "complete", "E46J method completeness");
exact(raw.execution_class, "hybrid", "E46J method execution");
return {
completeness: "complete",
executionClass: "hybrid",
pipelineId: text(raw.pipeline_id, "E46J pipeline"),
components: array(raw.components, "E46J components").map((value) => {
const component = object(value, "E46J component");
const kind = text(component.kind, "E46J component kind");
if (!("source tool model algorithm runtime".split(" ")).includes(kind)) {
throw new ContractError("E46J component kind: неизвестное значение.");
}
return {
kind: kind as "source" | "tool" | "model" | "algorithm" | "runtime",
name: text(component.name, "E46J component name"),
version: text(component.version, "E46J component version"),
role: text(component.role, "E46J component role"),
identitySha256: sha(component.identity_sha256, "E46J component identity"),
};
}),
};
}
function reviewWindow(value: unknown): E46JReviewWindow {
const raw = object(value, "E46J review window");
const verdict = raw.verdict;
if (
verdict !== "legacy-background-false-positive-suppressed"
&& verdict !== "operator-shadow-person-false-positive-observed"
) {
throw new ContractError("E46J review verdict: неизвестное значение.");
}
const startSeconds = number(raw.start_seconds, "E46J review start");
const endSeconds = number(raw.end_seconds, "E46J review end");
if (startSeconds < 0 || endSeconds <= startSeconds || endSeconds > 448.723) {
throw new ContractError("E46J review window: нарушен диапазон.");
}
return {
id: text(raw.id, "E46J review id"),
label: text(raw.label, "E46J review label"),
startSeconds,
endSeconds,
verdict,
};
}
export async function fetchE46JRawFisheyeRealtime({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E46JRawFisheyeRealtimeResult | null> {
const response = await fetcher("/api/v1/laboratory/e46j/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new ContractError(`E46J LAB недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "E46J catalog");
exact(catalog.schema_version, "missioncore.e46j-raw-fisheye-realtime-catalog/v1", "E46J catalog schema");
const items = array(catalog.items, "E46J results");
if (!items.length) return null;
if (items.length !== 1) throw new ContractError("E46J catalog size: нарушен контракт.");
const item = object(items[0], "E46J result");
exact(item.schema_version, "missioncore.e46j-raw-fisheye-realtime-view/v1", "E46J view schema");
exact(item.status, "realtime-capacity-passed-awaiting-temporal-layer", "E46J status");
exact(item.ground_truth, false, "E46J truth authority");
const authority = object(item.authority, "E46J authority");
exact(authority.ground_truth, false, "E46J authority truth");
exact(authority.provider_promoted, false, "E46J promotion");
exact(authority.commands_enabled, false, "E46J commands");
exact(authority.navigation_or_safety_accepted, false, "E46J safety");
const resultId = text(item.result_id, "E46J result id");
if (!/^e46j-raw-fisheye-realtime-[a-f0-9]{64}$/.test(resultId)) {
throw new ContractError("E46J result identity: нарушен контракт.");
}
const source = object(item.source, "E46J source");
const detector = object(item.detector, "E46J detector");
const detection = object(item.detection, "E46J detection");
const metrics = object(item.metrics, "E46J metrics");
const review = object(item.visual_review, "E46J visual review");
const decision = object(item.decision, "E46J decision");
const video = object(item.video, "E46J video");
const visuals = object(item.visuals, "E46J visuals");
const classCounts = object(metrics.class_observation_counts, "E46J class counts");
const acceptance = object(item.acceptance, "E46J acceptance");
exact(acceptance.ten_hz_capacity_gate_passed, true, "E46J capacity gate");
exact(acceptance.latency_gate_passed, true, "E46J latency gate");
exact(acceptance.full_raw_fisheye_retained, true, "E46J FOV gate");
return {
resultId,
createdAtUtc: text(item.created_at_utc, "E46J created"),
source: {
cameraSourceId: exact(source.camera_source_id, "sensor.camera.right", "E46J camera"),
sessionId: text(source.session_id, "E46J session"),
resolution: pair(source.resolution, [800, 600], "E46J resolution"),
frameCount: exact(source.frame_count, 4489, "E46J frames"),
frameRate: number(source.frame_rate, "E46J fps"),
durationSeconds: 448.723,
calibrationModel: exact(source.calibration_model, "KB4", "E46J calibration"),
},
detector: {
architecture: exact(detector.architecture, "YOLOX-S", "E46J architecture"),
source: text(detector.source, "E46J detector source"),
license: exact(detector.license, "Apache-2.0", "E46J license"),
runtime: text(detector.runtime, "E46J runtime"),
},
detection: {
minimumScore: exact(detection.minimum_score, 0.5, "E46J score"),
nmsIouThreshold: exact(detection.nms_iou_threshold, 0.45, "E46J NMS"),
},
metrics: {
frameCount: exact(metrics.frame_count, 4489, "E46J metric frames"),
failedFrameCount: exact(metrics.failed_frame_count, 0, "E46J failures"),
detectionObservationCount: integer(metrics.detection_observation_count, "E46J detections"),
classObservationCounts: Object.fromEntries(
Object.entries(classCounts).map(([key, value]) => [key, integer(value, `E46J ${key}`)]),
),
meanDetectionsPerFrame: number(metrics.mean_detections_per_frame, "E46J mean"),
maxDetectionsPerFrame: integer(metrics.max_detections_per_frame, "E46J max"),
zeroDetectionFrameCount: integer(metrics.zero_detection_frame_count, "E46J zero"),
longestZeroDetectionRunFrames: integer(metrics.longest_zero_detection_run_frames, "E46J zero run"),
coreCapacityFps: number(metrics.core_capacity_fps, "E46J capacity"),
corePathMeanMs: number(metrics.core_path_mean_ms, "E46J core mean"),
corePathP95Ms: number(metrics.core_path_p95_ms, "E46J core p95"),
inferenceRequestMeanMs: number(metrics.inference_request_mean_ms, "E46J infer mean"),
inferenceRequestP95Ms: number(metrics.inference_request_p95_ms, "E46J infer p95"),
gpuUtilizationMeanPercent: number(metrics.gpu_utilization_mean_percent, "E46J GPU"),
operatorShadowWindowFrameCount: integer(metrics.operator_shadow_window_frame_count, "E46J shadow window"),
operatorShadowPersonFrameCount: integer(metrics.operator_shadow_person_frame_count, "E46J shadow false frames"),
},
visualReview: {
reviewedRangeSeconds: pair(review.reviewed_video_range_seconds, [0, 448.723], "E46J reviewed range"),
verdict: exact(review.verdict, "realtime-detector-progress-with-known-shadow-exception", "E46J verdict"),
reviewWindows: array(review.review_windows, "E46J review windows").map(reviewWindow),
finding: text(review.finding, "E46J finding"),
knownError: text(review.known_error, "E46J known error"),
},
decision: {
selectedProvider: exact(decision.selected_provider, "megvii-yolox-s-0.1.1rc0", "E46J provider"),
realtimeCapacityPassed: exact(decision.realtime_capacity_passed, true, "E46J realtime"),
readyForTemporalBakeoff: exact(decision.ready_for_temporal_bakeoff, true, "E46J temporal readiness"),
providerPromoted: exact(decision.provider_promoted, false, "E46J provider promotion"),
nextAction: text(decision.next_action, "E46J next action"),
},
method: method(item.method),
limitations: array(item.limitations, "E46J limitations").map((value) => text(value, "E46J limitation")),
video: {
url: text(video.url, "E46J video URL"),
mediaType: exact(video.media_type, "video/mp4", "E46J video media"),
byteLength: integer(video.byte_length, "E46J video bytes"),
sha256: sha(video.sha256, "E46J video SHA"),
width: exact(video.width, 800, "E46J video width"),
height: exact(video.height, 600, "E46J video height"),
frameRate: number(video.frame_rate, "E46J video fps"),
frameCount: exact(video.frame_count, 4489, "E46J video frames"),
durationSeconds: exact(video.duration_seconds, 448.723, "E46J video duration"),
},
visuals: {
fullRoute: visual(visuals.full_route, "E46J route visual"),
targetedWindows: visual(visuals.targeted_windows, "E46J targeted visual"),
operatorShadow: visual(visuals.operator_shadow, "E46J shadow visual"),
},
};
}
@@ -0,0 +1,358 @@
import {
AdvancedLaboratoryContractError,
type LaboratoryFetch,
} from "./advancedResults";
import type { L3VisualBox } from "./l3PointPillarsVisualAudit";
import type { L31ClassCounts } from "./l31PointPillarsRavnoves";
export interface L32FrameSummary {
frameId: string;
frameIndex: number;
sessionSeconds: number;
sourcePointCount: number;
predictionCount: number;
classCounts: L31ClassCounts;
inferenceMs: number;
cameraSourceFrameIndex: number;
cameraSessionSeconds: number;
cameraDeltaMs: number;
}
export interface L32PointPillarsCameraReviewResult {
resultId: string;
createdAtUtc: string;
status: "camera-bound-review-rejects-current-candidate";
sourceSessionId: string;
sourceL31ResultId: string;
sourceE10PackId: string;
metrics: {
frameCount: number;
predictionCount: number;
classCounts: L31ClassCounts;
inferenceLatencyMs: { p50: number; p95: number; maximum: number };
reviewFrameCount: number;
reviewPredictionCount: number;
reviewVisibleProjectedBoxCount: number;
reviewProjectedPointCount: number;
scoreBelow025Fraction: number;
scoreBelow050Fraction: number;
cameraBindingAbsoluteDeltaMs: { p95: number; maximum: number };
};
frames: readonly L32FrameSummary[];
limitations: readonly string[];
}
export interface L32ProjectedBox {
modelClass: string;
score: number;
segmentsXyxy: readonly number[];
}
export interface L32VisualFrame {
frameId: string;
summary: L32FrameSummary;
cameraUrl: string;
cameraWidth: number;
cameraHeight: number;
modelRangePointCount: number;
pointsXyzi: readonly number[];
predictionBoxes: readonly L3VisualBox[];
projectedPointsXyd: readonly number[];
projectedBoxes: readonly L32ProjectedBox[];
}
export const L32_REVIEW_SCORE_THRESHOLD = 0.25;
const RESULT_ID = /^l32-pointpillars-camera-review-[a-f0-9]{64}$/;
const L31_RESULT_ID = /^l31-pointpillars-ravnoves-[a-f0-9]{64}$/;
const PACK_ID = /^e10-lidar-pack-[a-f0-9]{64}$/;
const FRAME_ID = /^[0-9]{6}$/;
function record(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new AdvancedLaboratoryContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) {
throw new AdvancedLaboratoryContractError(`${label}: ожидался массив.`);
}
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new AdvancedLaboratoryContractError(`${label}: ожидалась строка.`);
}
return value;
}
function exact<T extends string>(value: unknown, expected: T, label: string): T {
if (value !== expected) {
throw new AdvancedLaboratoryContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function number(value: unknown, label: string, minimum = 0): number {
if (typeof value !== "number" || !Number.isFinite(value) || value < minimum) {
throw new AdvancedLaboratoryContractError(`${label}: неверное число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isInteger(parsed)) {
throw new AdvancedLaboratoryContractError(`${label}: ожидалось целое.`);
}
return parsed;
}
function counts(value: unknown, label: string): L31ClassCounts {
const item = record(value, label);
if (Object.keys(item).sort().join(",") !== "Cyclist,Pedestrian,Vehicle") {
throw new AdvancedLaboratoryContractError(`${label}: классы изменились.`);
}
return {
Vehicle: integer(item.Vehicle, `${label}.Vehicle`),
Pedestrian: integer(item.Pedestrian, `${label}.Pedestrian`),
Cyclist: integer(item.Cyclist, `${label}.Cyclist`),
};
}
function distribution(value: unknown, label: string) {
const item = record(value, label);
return {
p50: number(item.p50, `${label}.p50`),
p95: number(item.p95, `${label}.p95`),
maximum: number(item.maximum, `${label}.maximum`),
};
}
function parseSummary(value: unknown): L32FrameSummary {
const item = record(value, "L3.2 frame");
const frameId = string(item.frame_id, "L3.2 frame_id");
if (!FRAME_ID.test(frameId)) {
throw new AdvancedLaboratoryContractError("L3.2 frame_id: неверный формат.");
}
return {
frameId,
frameIndex: integer(item.frame_index, "L3.2 frame index"),
sessionSeconds: number(item.session_seconds, "L3.2 session seconds"),
sourcePointCount: integer(item.source_point_count, "L3.2 source points"),
predictionCount: integer(item.prediction_count, "L3.2 predictions"),
classCounts: counts(item.class_counts, "L3.2 classes"),
inferenceMs: number(item.inference_ms, "L3.2 inference", Number.MIN_VALUE),
cameraSourceFrameIndex: integer(
item.camera_source_frame_index,
"L3.2 camera frame",
),
cameraSessionSeconds: number(
item.camera_session_seconds,
"L3.2 camera seconds",
),
cameraDeltaMs: number(item.camera_delta_ms, "L3.2 camera delta", -100),
};
}
function parseBox(value: unknown): L3VisualBox {
const box = record(value, "L3.2 box");
const modelClass = string(box.model_class, "L3.2 box class");
return {
benchmarkClass: modelClass,
centerXyzM: [
number(box.x_m, "L3.2 box x", -Infinity),
number(box.y_m, "L3.2 box y", -Infinity),
number(box.z_m, "L3.2 box z", -Infinity),
],
sizeLwhM: [
number(box.length_m, "L3.2 box length", Number.MIN_VALUE),
number(box.width_m, "L3.2 box width", Number.MIN_VALUE),
number(box.height_m, "L3.2 box height", Number.MIN_VALUE),
],
yawRad: number(box.yaw_rad, "L3.2 box yaw", -Infinity),
status: "model-prediction",
score: number(box.score, "L3.2 box score"),
};
}
function parseResult(value: unknown): L32PointPillarsCameraReviewResult {
const item = record(value, "L3.2 result");
exact(
item.schema_version,
"missioncore.l32-pointpillars-camera-review-result/v1",
"L3.2 schema",
);
exact(item.access, "read-only", "L3.2 access");
const resultId = string(item.result_id, "L3.2 result id");
const sourceL31ResultId = string(item.source_l31_result_id, "L3.2 L3.1 id");
const sourceE10PackId = string(item.source_e10_pack_id, "L3.2 E10 id");
if (
!RESULT_ID.test(resultId)
|| !L31_RESULT_ID.test(sourceL31ResultId)
|| !PACK_ID.test(sourceE10PackId)
) {
throw new AdvancedLaboratoryContractError("L3.2: неверная identity.");
}
const metrics = record(item.metrics, "L3.2 metrics");
const cameraDelta = distribution(
metrics.camera_binding_absolute_delta_ms,
"L3.2 camera delta",
);
const frames = array(item.frames, "L3.2 frames").map(parseSummary);
if (!frames.length || frames.length > 18) {
throw new AdvancedLaboratoryContractError("L3.2 frames: нарушен bound.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "L3.2 created at"),
status: exact(
item.status,
"camera-bound-review-rejects-current-candidate",
"L3.2 status",
),
sourceSessionId: exact(
item.source_session_id,
"20260720T065719Z_viewer_live",
"L3.2 session",
),
sourceL31ResultId,
sourceE10PackId,
metrics: {
frameCount: integer(metrics.frame_count, "L3.2 frame count"),
predictionCount: integer(metrics.prediction_count, "L3.2 predictions"),
classCounts: counts(metrics.class_counts, "L3.2 metric classes"),
inferenceLatencyMs: distribution(
metrics.inference_latency_ms,
"L3.2 inference latency",
),
reviewFrameCount: integer(metrics.review_frame_count, "L3.2 review frames"),
reviewPredictionCount: integer(
metrics.review_prediction_count,
"L3.2 review predictions",
),
reviewVisibleProjectedBoxCount: integer(
metrics.review_visible_projected_box_count,
"L3.2 visible boxes",
),
reviewProjectedPointCount: integer(
metrics.review_projected_point_count,
"L3.2 projected points",
),
scoreBelow025Fraction: number(
metrics.score_below_0_25_fraction,
"L3.2 low score 025",
),
scoreBelow050Fraction: number(
metrics.score_below_0_50_fraction,
"L3.2 low score 050",
),
cameraBindingAbsoluteDeltaMs: cameraDelta,
},
frames,
limitations: array(item.limitations, "L3.2 limitations").map(
(entry) => string(entry, "L3.2 limitation"),
),
};
}
export async function fetchL32PointPillarsCameraReview({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<L32PointPillarsCameraReviewResult | null> {
const response = await fetcher(
"/api/v1/laboratory/l32/pointpillars-camera-review/results?limit=1",
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new AdvancedLaboratoryContractError(
`L3.2 RAVNOVES недоступен: HTTP ${response.status}.`,
);
}
const catalog = record(await response.json(), "L3.2 catalog");
exact(
catalog.schema_version,
"missioncore.l32-pointpillars-camera-review-catalog-results/v1",
"L3.2 catalog schema",
);
const items = array(catalog.items, "L3.2 catalog items");
return items.length ? parseResult(items[0]) : null;
}
export async function fetchL32PointPillarsCameraReviewFrame(
resultId: string,
frameId: string,
{
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {},
): Promise<L32VisualFrame> {
if (!RESULT_ID.test(resultId) || !FRAME_ID.test(frameId)) {
throw new AdvancedLaboratoryContractError("L3.2 frame: неверная identity.");
}
const response = await fetcher(
`/api/v1/laboratory/l32/pointpillars-camera-review/${resultId}/frames/${frameId}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new AdvancedLaboratoryContractError(
`L3.2 frame недоступен: HTTP ${response.status}.`,
);
}
const item = record(await response.json(), "L3.2 visual frame");
exact(
item.schema_version,
"missioncore.l32-pointpillars-camera-review-frame/v1",
"L3.2 frame schema",
);
const summary = parseSummary(item.summary);
const camera = record(item.camera, "L3.2 camera");
const points = record(item.points, "L3.2 points");
exact(points.layout, "flat-xyzi", "L3.2 point layout");
const values = array(points.values, "L3.2 point values").map(
(entry, index) => number(entry, `L3.2 points[${index}]`, -Infinity),
);
const projection = record(item.camera_projection, "L3.2 projection");
exact(projection.point_layout, "flat-xy-depth-m", "L3.2 projection layout");
const projected = array(projection.point_values, "L3.2 projected points").map(
(entry, index) => number(entry, `L3.2 projected[${index}]`, -Infinity),
);
if (projected.length !== integer(projection.point_count, "L3.2 point count") * 3) {
throw new AdvancedLaboratoryContractError("L3.2 projection: нарушен размер.");
}
return {
frameId,
summary,
cameraUrl: `/api/v1/laboratory/l32/pointpillars-camera-review/${resultId}/frames/${frameId}/camera`,
cameraWidth: integer(camera.width, "L3.2 camera width"),
cameraHeight: integer(camera.height, "L3.2 camera height"),
modelRangePointCount: integer(
points.model_range_point_count,
"L3.2 model range points",
),
pointsXyzi: values,
predictionBoxes: array(item.prediction_boxes, "L3.2 boxes").map(parseBox),
projectedPointsXyd: projected,
projectedBoxes: array(projection.boxes, "L3.2 projected boxes").map(
(entry) => {
const box = record(entry, "L3.2 projected box");
return {
modelClass: string(box.model_class, "L3.2 projected class"),
score: number(box.score, "L3.2 projected score"),
segmentsXyxy: array(box.segments_xyxy, "L3.2 projected segments").map(
(value, index) => number(value, `L3.2 segment[${index}]`, -Infinity),
),
};
},
),
};
}
@@ -0,0 +1,396 @@
import {
AdvancedLaboratoryContractError,
type LaboratoryFetch,
} from "./advancedResults";
import type { L3VisualBox } from "./l3PointPillarsVisualAudit";
export type L33SemanticProvenance =
| "recorded-current"
| "bounded-track-interpolation"
| "rectified-detector-current"
| "e23-temporal-hold";
export interface L33FrameSummary {
frameId: string;
frameIndex: number;
sessionSeconds: number;
cameraSourceFrameIndex: number;
cameraSessionSeconds: number;
cameraDeltaMs: number;
sourcePointCount: number;
detectionCount: number;
rangedDetectionCount: number;
cameraOnlyDetectionCount: number;
cuboidCount: number;
semanticProvenance: L33SemanticProvenance;
}
export interface L33CameraFirstDetectorReviewResult {
resultId: string;
createdAtUtc: string;
status: "camera-first-boundary-restored-shadow-only";
sourceSessionId: string;
sourceL32ResultId: string;
sourceE26ResultId: string;
sourceE29ResultId: string;
sourceE10PackId: string;
sourceWorldStateResultId: string;
detector: {
id: string;
architecture: string;
classes: string;
modelSha256: string;
inputShape: readonly number[];
};
metrics: {
reviewFrameCount: number;
recordedCurrentFrameCount: number;
recoveredCameraFrameCount: number;
semanticFrameCoverageFraction: number;
detectionCount: number;
rangedDetectionCount: number;
cameraOnlyDetectionCount: number;
rangeCoverageFraction: number;
minimumDetectorScore: number;
cuboidCount: number;
routeDetectionCount: number;
routeDetectionFrameCount: number;
framesProcessed: number;
effectiveComposedFps: number;
composedP95Ms: number;
semanticEffectiveFps: number;
lidarFusedFrames: number;
rawAcceptedCuboids: number;
duplicateSupportRejections: number;
temporalAcceptedCuboids: number;
worldObjectObservations: number;
classCounts: Readonly<Record<string, number>>;
};
frames: readonly L33FrameSummary[];
limitations: readonly string[];
}
export interface L33Detection {
sourceTrackId: number;
label: string;
associationGroup: string;
score: number;
bboxXyxy: readonly [number, number, number, number];
semanticProvenance: L33SemanticProvenance;
geometryStatus: string;
geometryReason: string;
rangeM: number | null;
sourceE29OpticalDepthM: number | null;
support: {
projectedPoints: number;
occupiedPoints: number;
connectedOccupiedPoints: number;
};
geometryAnchorXyzM: readonly [number, number, number] | null;
cameraRayLidar: {
originXyzM: readonly [number, number, number];
directionXyz: readonly [number, number, number];
};
}
export interface L33VisualFrame {
frameId: string;
summary: L33FrameSummary;
cameraUrl: string;
cameraWidth: number;
cameraHeight: number;
pointsXyzi: readonly number[];
projectedPointsXyd: readonly number[];
detections: readonly L33Detection[];
predictionBoxes: readonly L3VisualBox[];
}
const RESULT_ID = /^l33-camera-first-detector-review-[a-f0-9]{64}$/;
const SOURCE_ID = /^(?:l32-pointpillars-camera-review|e10-integrated-perception|e29-camera-geometry|e10-lidar-pack|rectified-camera-world-state)-[a-f0-9]{64}$/;
const FRAME_ID = /^[0-9]{6}$/;
function record(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new AdvancedLaboratoryContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) {
throw new AdvancedLaboratoryContractError(`${label}: ожидался массив.`);
}
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new AdvancedLaboratoryContractError(`${label}: ожидалась строка.`);
}
return value;
}
function exact<T extends string>(value: unknown, expected: T, label: string): T {
if (value !== expected) {
throw new AdvancedLaboratoryContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function number(value: unknown, label: string, minimum = 0): number {
if (typeof value !== "number" || !Number.isFinite(value) || value < minimum) {
throw new AdvancedLaboratoryContractError(`${label}: неверное число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = number(value, label);
if (!Number.isInteger(parsed)) {
throw new AdvancedLaboratoryContractError(`${label}: ожидалось целое.`);
}
return parsed;
}
function provenance(value: unknown, label: string): L33SemanticProvenance {
if (
value !== "recorded-current"
&& value !== "bounded-track-interpolation"
&& value !== "rectified-detector-current"
&& value !== "e23-temporal-hold"
) {
throw new AdvancedLaboratoryContractError(`${label}: неизвестный источник.`);
}
return value;
}
function tuple(
value: unknown,
length: number,
label: string,
minimum = -Infinity,
): readonly number[] {
const values = array(value, label).map((item, index) => (
number(item, `${label}[${index}]`, minimum)
));
if (values.length !== length) {
throw new AdvancedLaboratoryContractError(`${label}: неверная размерность.`);
}
return values;
}
function sourceId(value: unknown, label: string): string {
const parsed = string(value, label);
if (!SOURCE_ID.test(parsed)) {
throw new AdvancedLaboratoryContractError(`${label}: неверная identity.`);
}
return parsed;
}
function parseSummary(value: unknown): L33FrameSummary {
const item = record(value, "L3.3 frame");
const frameId = string(item.frame_id, "L3.3 frame id");
if (!FRAME_ID.test(frameId)) {
throw new AdvancedLaboratoryContractError("L3.3 frame id: неверный формат.");
}
return {
frameId,
frameIndex: integer(item.frame_index, "L3.3 frame index"),
sessionSeconds: number(item.session_seconds, "L3.3 session seconds"),
cameraSourceFrameIndex: integer(item.camera_source_frame_index, "L3.3 camera frame"),
cameraSessionSeconds: number(item.camera_session_seconds, "L3.3 camera seconds"),
cameraDeltaMs: number(item.camera_delta_ms, "L3.3 camera delta", -100),
sourcePointCount: integer(item.source_point_count, "L3.3 source points"),
detectionCount: integer(item.detection_count, "L3.3 detections"),
rangedDetectionCount: integer(item.ranged_detection_count, "L3.3 ranged detections"),
cameraOnlyDetectionCount: integer(item.camera_only_detection_count, "L3.3 camera-only detections"),
cuboidCount: item.cuboid_count === undefined
? 0
: integer(item.cuboid_count, "L3.3 cuboids"),
semanticProvenance: provenance(item.semantic_provenance, "L3.3 provenance"),
};
}
function parsePredictionBox(value: unknown): L3VisualBox {
const item = record(value, "L3.3 cuboid");
exact(item.status, "model-prediction", "L3.3 cuboid status");
return {
benchmarkClass: string(item.benchmark_class, "L3.3 cuboid class"),
centerXyzM: tuple(item.center_xyz_m, 3, "L3.3 cuboid center", -Infinity) as [number, number, number],
sizeLwhM: tuple(item.size_lwh_m, 3, "L3.3 cuboid size", Number.MIN_VALUE) as [number, number, number],
yawRad: number(item.yaw_rad, "L3.3 cuboid yaw", -Infinity),
status: "model-prediction",
score: number(item.score, "L3.3 cuboid score"),
temporalStatus: string(item.temporal_status, "L3.3 cuboid temporal status"),
};
}
function parseDetection(value: unknown): L33Detection {
const item = record(value, "L3.3 detection");
const support = record(item.support, "L3.3 support");
const cameraRay = record(item.camera_ray_lidar, "L3.3 camera ray");
return {
sourceTrackId: integer(item.source_track_id, "L3.3 track"),
label: string(item.label, "L3.3 label"),
associationGroup: string(item.association_group, "L3.3 group"),
score: number(item.score, "L3.3 score", 0.25),
bboxXyxy: tuple(item.bbox_xyxy, 4, "L3.3 bbox", -Infinity) as [number, number, number, number],
semanticProvenance: provenance(item.semantic_provenance, "L3.3 detection provenance"),
geometryStatus: string(item.geometry_status, "L3.3 geometry status"),
geometryReason: string(item.geometry_reason, "L3.3 geometry reason"),
rangeM: item.range_m === null ? null : number(item.range_m, "L3.3 range"),
sourceE29OpticalDepthM: item.source_e29_optical_depth_m === null
? null
: number(item.source_e29_optical_depth_m, "L3.3 E29 optical depth"),
support: {
projectedPoints: integer(support.projected_points, "L3.3 projected support"),
occupiedPoints: integer(support.occupied_points, "L3.3 occupied support"),
connectedOccupiedPoints: integer(support.connected_occupied_points, "L3.3 connected support"),
},
geometryAnchorXyzM: item.geometry_anchor_xyz_m === null
? null
: tuple(item.geometry_anchor_xyz_m, 3, "L3.3 geometry anchor", -Infinity) as [number, number, number],
cameraRayLidar: {
originXyzM: tuple(cameraRay.origin_xyz_m, 3, "L3.3 ray origin", -Infinity) as [number, number, number],
directionXyz: tuple(cameraRay.direction_xyz, 3, "L3.3 ray direction", -Infinity) as [number, number, number],
},
};
}
function parseResult(value: unknown): L33CameraFirstDetectorReviewResult {
const item = record(value, "L3.3 result");
exact(item.schema_version, "missioncore.l33-camera-first-detector-review-result/v1", "L3.3 schema");
exact(item.access, "read-only", "L3.3 access");
const resultId = string(item.result_id, "L3.3 result id");
if (!RESULT_ID.test(resultId)) {
throw new AdvancedLaboratoryContractError("L3.3 result: неверная identity.");
}
const detector = record(item.detector, "L3.3 detector");
const metrics = record(item.metrics, "L3.3 metrics");
const classCounts = record(metrics.class_counts, "L3.3 class counts");
const frames = array(item.frames, "L3.3 frames").map(parseSummary);
if (!frames.length || frames.length > 18) {
throw new AdvancedLaboratoryContractError("L3.3 frames: нарушен bound.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "L3.3 created at"),
status: exact(item.status, "camera-first-boundary-restored-shadow-only", "L3.3 status"),
sourceSessionId: exact(item.source_session_id, "20260720T065719Z_viewer_live", "L3.3 session"),
sourceL32ResultId: sourceId(item.source_l32_result_id, "L3.3 L3.2 id"),
sourceE26ResultId: sourceId(item.source_e26_result_id, "L3.3 E26 id"),
sourceE29ResultId: sourceId(item.source_e29_result_id, "L3.3 E29 id"),
sourceE10PackId: sourceId(item.source_e10_pack_id, "L3.3 E10 id"),
sourceWorldStateResultId: sourceId(item.source_world_state_result_id, "L3.3 world-state id"),
detector: {
id: string(detector.id, "L3.3 detector id"),
architecture: string(detector.architecture, "L3.3 detector architecture"),
classes: string(detector.classes, "L3.3 detector classes"),
modelSha256: string(detector.model_sha256, "L3.3 detector sha"),
inputShape: tuple(detector.input_shape, 4, "L3.3 detector shape"),
},
metrics: {
reviewFrameCount: integer(metrics.review_frame_count, "L3.3 review frames"),
recordedCurrentFrameCount: integer(metrics.recorded_current_frame_count, "L3.3 current frames"),
recoveredCameraFrameCount: integer(metrics.recovered_camera_frame_count, "L3.3 recovered frames"),
semanticFrameCoverageFraction: number(metrics.semantic_frame_coverage_fraction, "L3.3 semantic coverage"),
detectionCount: integer(metrics.detection_count, "L3.3 detections"),
rangedDetectionCount: integer(metrics.ranged_detection_count, "L3.3 ranged"),
cameraOnlyDetectionCount: integer(metrics.camera_only_detection_count, "L3.3 camera only"),
rangeCoverageFraction: number(metrics.range_coverage_fraction, "L3.3 range coverage"),
minimumDetectorScore: number(metrics.minimum_detector_score, "L3.3 threshold"),
cuboidCount: integer(metrics.cuboid_count, "L3.3 selected cuboids"),
routeDetectionCount: integer(metrics.route_detection_count, "L3.3 route detections"),
routeDetectionFrameCount: integer(metrics.route_detection_frame_count, "L3.3 route detection frames"),
framesProcessed: integer(metrics.frames_processed, "L3.3 processed frames"),
effectiveComposedFps: number(metrics.effective_composed_fps, "L3.3 composed FPS", Number.MIN_VALUE),
composedP95Ms: number(metrics.composed_p95_ms, "L3.3 composed p95", Number.MIN_VALUE),
semanticEffectiveFps: number(metrics.semantic_effective_fps, "L3.3 semantic FPS", Number.MIN_VALUE),
lidarFusedFrames: integer(metrics.lidar_fused_frames, "L3.3 fused frames"),
rawAcceptedCuboids: integer(metrics.raw_accepted_cuboids, "L3.3 raw cuboids"),
duplicateSupportRejections: integer(
metrics.duplicate_support_rejections,
"L3.3 duplicate support rejections",
),
temporalAcceptedCuboids: integer(metrics.temporal_accepted_cuboids, "L3.3 temporal cuboids"),
worldObjectObservations: integer(metrics.world_object_observations, "L3.3 world objects"),
classCounts: Object.fromEntries(
Object.entries(classCounts).map(([key, entry]) => [key, integer(entry, `L3.3 class ${key}`)]),
),
},
frames,
limitations: array(item.limitations, "L3.3 limitations").map((entry) => string(entry, "L3.3 limitation")),
};
}
export async function fetchL33CameraFirstDetectorReview({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<L33CameraFirstDetectorReviewResult | null> {
const response = await fetcher(
"/api/v1/laboratory/l33/camera-first-detector-review/results?limit=1",
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new AdvancedLaboratoryContractError(`L3.3 недоступен: HTTP ${response.status}.`);
}
const catalog = record(await response.json(), "L3.3 catalog");
exact(catalog.schema_version, "missioncore.l33-camera-first-detector-review-catalog-results/v1", "L3.3 catalog schema");
const items = array(catalog.items, "L3.3 catalog items");
return items.length ? parseResult(items[0]) : null;
}
export async function fetchL33CameraFirstDetectorReviewFrame(
resultId: string,
frameId: string,
{
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {},
): Promise<L33VisualFrame> {
if (!RESULT_ID.test(resultId) || !FRAME_ID.test(frameId)) {
throw new AdvancedLaboratoryContractError("L3.3 frame: неверная identity.");
}
const response = await fetcher(
`/api/v1/laboratory/l33/camera-first-detector-review/${resultId}/frames/${frameId}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new AdvancedLaboratoryContractError(`L3.3 frame недоступен: HTTP ${response.status}.`);
}
const item = record(await response.json(), "L3.3 visual frame");
exact(item.schema_version, "missioncore.l33-camera-first-detector-review-frame/v1", "L3.3 frame schema");
const summary = parseSummary(item.summary);
const camera = record(item.camera, "L3.3 camera");
const points = record(item.points, "L3.3 points");
exact(points.layout, "flat-xyzi", "L3.3 point layout");
const projection = record(item.camera_projection, "L3.3 projection");
exact(projection.point_layout, "flat-xy-depth-m", "L3.3 projection layout");
const projected = array(projection.point_values, "L3.3 projected points").map(
(entry, index) => number(entry, `L3.3 projected[${index}]`, -Infinity),
);
if (projected.length !== integer(projection.point_count, "L3.3 projected count") * 3) {
throw new AdvancedLaboratoryContractError("L3.3 projection: нарушен размер.");
}
const detections = array(item.detections, "L3.3 detections").map(parseDetection);
const predictionBoxes = array(item.prediction_boxes, "L3.3 cuboids").map(parsePredictionBox);
return {
frameId,
summary,
cameraUrl: `/api/v1/laboratory/l33/camera-first-detector-review/${resultId}/frames/${frameId}/camera`,
cameraWidth: integer(camera.width, "L3.3 camera width"),
cameraHeight: integer(camera.height, "L3.3 camera height"),
pointsXyzi: array(points.values, "L3.3 point values").map(
(entry, index) => number(entry, `L3.3 points[${index}]`, -Infinity),
),
projectedPointsXyd: projected,
detections,
predictionBoxes,
};
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,436 @@
export interface L34FrameSummary {
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
predictionCount: number;
maximumScore: number;
}
export type L34PredictionLabel =
| "person"
| "bicycle"
| "motorcycle"
| "car"
| "heavy_vehicle"
| "static_obstacle"
| "animal";
export interface L34Prediction {
label: L34PredictionLabel;
score: number;
bboxXyxy: readonly [number, number, number, number];
}
export interface L34VisualFrame {
resultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
role: "anchor" | "temporal";
sessionSeconds: number;
cameraUrl: string;
cameraWidth: number;
cameraHeight: number;
cameraSha256: string;
predictionRowsSha256: string;
predictions: readonly L34Prediction[];
truthLabelsRead: false;
}
export interface L34RightYoloxTruthIslandResult {
resultId: string;
createdAtUtc: string;
status: "predictions-frozen-awaiting-independent-truth";
profileId: "RAVNOVES00_RIGHT_YOLOX_TRUTH_ISLAND_V1";
pipelineId: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
candidate: {
architecture: "YOLOX-S";
modelSha256: string;
minimumScore: number;
l33ResultId: string;
};
truthIsland: {
resultId: string;
truthState: "labels-unavailable";
};
metrics: {
frameCount: number;
temporalGroupCount: number;
predictionCount: number;
framesWithPredictions: number;
classCounts: Readonly<Record<string, number>>;
accuracyMetricsAvailable: false;
};
frames: readonly L34FrameSummary[];
decision: {
candidatePredictionsFrozen: true;
truthLabelsRead: false;
candidateAccepted: false;
modelRetrainingAuthorized: false;
nextGate: string;
};
limitations: readonly string[];
access: "read-only";
}
class L34ContractError extends Error {}
type LaboratoryFetch = (
input: RequestInfo | URL,
init?: RequestInit,
) => Promise<Response>;
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new L34ContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function array(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) {
throw new L34ContractError(`${label}: ожидался массив.`);
}
return value;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new L34ContractError(`${label}: ожидалась строка.`);
}
return value;
}
function integer(value: unknown, label: string): number {
if (!Number.isInteger(value) || Number(value) < 0) {
throw new L34ContractError(`${label}: ожидалось целое число.`);
}
return Number(value);
}
function finiteNumber(
value: unknown,
label: string,
minimum = 0,
): number {
if (typeof value !== "number" || !Number.isFinite(value) || value < minimum) {
throw new L34ContractError(`${label}: ожидалось конечное число.`);
}
return value;
}
function exact<T extends string | boolean>(
value: unknown,
expected: T,
label: string,
): T {
if (value !== expected) throw new L34ContractError(`${label}: нарушен контракт.`);
return expected;
}
function predictionLabel(value: unknown, label: string): L34PredictionLabel {
if (
value !== "person"
&& value !== "bicycle"
&& value !== "motorcycle"
&& value !== "car"
&& value !== "heavy_vehicle"
&& value !== "static_obstacle"
&& value !== "animal"
) {
throw new L34ContractError(`${label}: неизвестный класс.`);
}
return value;
}
function parseFrameSummary(value: unknown): L34FrameSummary {
const item = object(value, "L3.4 frame summary");
const maximumScore = finiteNumber(
item.maximum_score,
"L3.4 frame maximum score",
);
if (maximumScore > 1) {
throw new L34ContractError("L3.4 frame maximum score: нарушен диапазон.");
}
return {
truthIslandSequence: integer(
item.truth_island_sequence,
"L3.4 frame sequence",
),
imageId: integer(item.image_id, "L3.4 frame image"),
frameIndex: integer(item.frame_index, "L3.4 frame index"),
groupId: string(item.group_id, "L3.4 frame group"),
predictionCount: integer(
item.prediction_count,
"L3.4 frame predictions",
),
maximumScore,
};
}
function parse(itemValue: unknown): L34RightYoloxTruthIslandResult {
const item = object(itemValue, "L3.4");
const candidate = object(item.candidate, "L3.4.candidate");
const truthIsland = object(item.truth_island, "L3.4.truth_island");
const metrics = object(item.metrics, "L3.4.metrics");
const classCounts = object(metrics.class_counts, "L3.4.metrics.class_counts");
const decision = object(item.decision, "L3.4.decision");
const frames = array(item.frames, "L3.4.frames").map(parseFrameSummary);
const resultId = string(item.result_id, "L3.4.result_id");
const modelSha256 = string(candidate.model_sha256, "L3.4.candidate.model_sha256");
if (
!/^l34-right-yolox-truth-island-freeze-[a-f0-9]{64}$/.test(resultId)
|| !/^[a-f0-9]{64}$/.test(modelSha256)
) {
throw new L34ContractError("L3.4: нарушена content identity.");
}
const frameCount = integer(metrics.frame_count, "L3.4.metrics.frame_count");
const predictionCount = integer(
metrics.prediction_count,
"L3.4.metrics.prediction_count",
);
const framesWithPredictions = integer(
metrics.frames_with_predictions,
"L3.4.metrics.frames_with_predictions",
);
if (
!frames.length
|| frames.length > 32
|| frames.length !== frameCount
|| new Set(frames.map(({ truthIslandSequence }) => truthIslandSequence)).size
!== frames.length
|| frames.reduce((total, frame) => total + frame.predictionCount, 0)
!== predictionCount
|| frames.filter(({ predictionCount: count }) => count > 0).length
!== framesWithPredictions
) {
throw new L34ContractError("L3.4.frames: нарушена визуальная связность.");
}
const counts = Object.fromEntries(Object.entries(classCounts).map(([key, value]) => (
[key, integer(value, `L3.4.metrics.class_counts.${key}`)]
)));
const limitations = item.limitations;
if (!Array.isArray(limitations) || limitations.some((value) => typeof value !== "string")) {
throw new L34ContractError("L3.4.limitations: ожидался список строк.");
}
const minimumScore = candidate.minimum_score;
if (typeof minimumScore !== "number" || minimumScore !== 0.25) {
throw new L34ContractError("L3.4.candidate.minimum_score: нарушен контракт.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "L3.4.created_at_utc"),
status: exact(
item.status,
"predictions-frozen-awaiting-independent-truth",
"L3.4.status",
),
profileId: exact(
item.profile_id,
"RAVNOVES00_RIGHT_YOLOX_TRUTH_ISLAND_V1",
"L3.4.profile_id",
),
pipelineId: string(item.pipeline_id, "L3.4.pipeline_id"),
sourceSessionId: string(item.source_session_id, "L3.4.source_session_id"),
cameraSourceId: exact(
item.camera_source_id,
"sensor.camera.right",
"L3.4.camera_source_id",
),
candidate: {
architecture: exact(candidate.architecture, "YOLOX-S", "L3.4.architecture"),
modelSha256,
minimumScore,
l33ResultId: string(candidate.l33_result_id, "L3.4.candidate.l33_result_id"),
},
truthIsland: {
resultId: string(truthIsland.result_id, "L3.4.truth_island.result_id"),
truthState: exact(
truthIsland.truth_state,
"labels-unavailable",
"L3.4.truth_island.truth_state",
),
},
metrics: {
frameCount,
temporalGroupCount: integer(
metrics.temporal_group_count,
"L3.4.metrics.temporal_group_count",
),
predictionCount,
framesWithPredictions,
classCounts: counts,
accuracyMetricsAvailable: exact(
metrics.accuracy_metrics_available,
false,
"L3.4.metrics.accuracy_metrics_available",
),
},
frames,
decision: {
candidatePredictionsFrozen: exact(
decision.candidate_predictions_frozen,
true,
"L3.4.decision.candidate_predictions_frozen",
),
truthLabelsRead: exact(
decision.truth_labels_read,
false,
"L3.4.decision.truth_labels_read",
),
candidateAccepted: exact(
decision.candidate_accepted,
false,
"L3.4.decision.candidate_accepted",
),
modelRetrainingAuthorized: exact(
decision.model_retraining_authorized,
false,
"L3.4.decision.model_retraining_authorized",
),
nextGate: string(decision.next_gate, "L3.4.decision.next_gate"),
},
limitations: limitations as string[],
access: exact(item.access, "read-only", "L3.4.access"),
};
}
function parseVisualFrame(
value: unknown,
resultId: string,
sequence: number,
): L34VisualFrame {
const item = object(value, "L3.4 visual frame");
exact(
item.schema_version,
"missioncore.l34-right-yolox-truth-island-frame/v1",
"L3.4 frame schema",
);
exact(item.access, "read-only", "L3.4 frame access");
exact(item.truth_labels_read, false, "L3.4 frame truth state");
if (
item.result_id !== resultId
|| item.truth_island_sequence !== sequence
|| !Number.isInteger(sequence)
|| sequence < 1
|| sequence > 32
) {
throw new L34ContractError("L3.4 visual frame: нарушена identity.");
}
const camera = object(item.camera, "L3.4 frame camera");
const cameraWidth = integer(camera.width, "L3.4 camera width");
const cameraHeight = integer(camera.height, "L3.4 camera height");
const cameraSha256 = string(camera.sha256, "L3.4 camera sha256");
const predictionRowsSha256 = string(
item.prediction_rows_sha256,
"L3.4 prediction rows sha256",
);
if (
!/^[a-f0-9]{64}$/.test(cameraSha256)
|| !/^[a-f0-9]{64}$/.test(predictionRowsSha256)
) {
throw new L34ContractError("L3.4 visual frame: нарушена content identity.");
}
const predictions = array(item.predictions, "L3.4 frame predictions").map(
(value, index): L34Prediction => {
const prediction = object(value, `L3.4 prediction ${index}`);
const score = finiteNumber(prediction.score, `L3.4 prediction ${index} score`, 0.25);
const bbox = array(prediction.bbox_xyxy, `L3.4 prediction ${index} bbox`).map(
(entry, coordinate) => finiteNumber(
entry,
`L3.4 prediction ${index} bbox ${coordinate}`,
),
);
if (
score > 1
|| bbox.length !== 4
|| !(bbox[0] < bbox[2] && bbox[2] <= cameraWidth)
|| !(bbox[1] < bbox[3] && bbox[3] <= cameraHeight)
) {
throw new L34ContractError(`L3.4 prediction ${index}: нарушена геометрия.`);
}
return {
label: predictionLabel(prediction.label, `L3.4 prediction ${index} label`),
score,
bboxXyxy: bbox as [number, number, number, number],
};
},
);
const role = item.role;
if (role !== "anchor" && role !== "temporal") {
throw new L34ContractError("L3.4 frame role: нарушен контракт.");
}
return {
resultId,
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4 frame image"),
frameIndex: integer(item.frame_index, "L3.4 frame index"),
groupId: string(item.group_id, "L3.4 frame group"),
role,
sessionSeconds: finiteNumber(item.session_seconds, "L3.4 frame time"),
cameraUrl: `/api/v1/laboratory/l34/results/${resultId}/frames/${sequence}/camera`,
cameraWidth,
cameraHeight,
cameraSha256,
predictionRowsSha256,
predictions,
truthLabelsRead: false,
};
}
export async function fetchL34RightYoloxTruthIsland({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<L34RightYoloxTruthIslandResult | null> {
const response = await fetcher("/api/v1/laboratory/l34/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new L34ContractError(`L3.4 недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "L3.4 catalog");
exact(
catalog.schema_version,
"missioncore.l34-right-yolox-truth-island-catalog/v1",
"L3.4 catalog.schema_version",
);
exact(catalog.access, "read-only", "L3.4 catalog.access");
if (!Array.isArray(catalog.items) || catalog.items.length > 1) {
throw new L34ContractError("L3.4 catalog.items: нарушен размер.");
}
return catalog.items.length ? parse(catalog.items[0]) : null;
}
export async function fetchL34RightYoloxTruthIslandFrame(
resultId: string,
sequence: number,
{
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {},
): Promise<L34VisualFrame> {
if (!/^l34-right-yolox-truth-island-freeze-[a-f0-9]{64}$/.test(resultId)) {
throw new L34ContractError("L3.4 visual frame: неверный result id.");
}
if (!Number.isInteger(sequence) || sequence < 1 || sequence > 32) {
throw new L34ContractError("L3.4 visual frame: неверный sequence.");
}
const response = await fetcher(
`/api/v1/laboratory/l34/results/${resultId}/frames/${sequence}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new L34ContractError(`L3.4 visual frame недоступен: HTTP ${response.status}.`);
}
return parseVisualFrame(await response.json(), resultId, sequence);
}
@@ -0,0 +1,466 @@
export type L34APredictionVerdict =
| "true_positive"
| "class_mismatch"
| "duplicate_false_positive"
| "false_positive";
export type L34AAnnotationVerdict =
| "true_positive"
| "class_mismatch"
| "false_negative";
export interface L34ACaseSummaryMetrics {
predictionCount: number;
referenceCount: number;
truePositive: number;
falsePositive: number;
falseNegative: number;
classMismatch: number;
duplicateFalsePositive: number;
unmatchedFalsePositive: number;
unmatchedFalseNegative: number;
severityScore: number;
}
export interface L34ACaseSummary {
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
summary: L34ACaseSummaryMetrics;
}
export interface L34AClassMetric {
referenceCount: number;
truePositive: number;
falsePositive: number;
falseNegative: number;
precisionIou50: number;
recallIou50: number;
}
export interface L34AAssistedYoloxErrorAuditResult {
resultId: string;
createdAtUtc: string;
status: "completed-assisted-candidate-error-audit-not-truth";
profileId: string;
pipelineId: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
assistedAnnotation: {
sessionId: string;
sessionSha256: string;
revision: number;
updatedAtUtc: string;
independentTruthEligible: false;
};
metrics: {
frameCount: number;
predictionCount: number;
referenceCount: number;
truePositive: number;
falsePositive: number;
falseNegative: number;
classMismatch: number;
duplicateFalsePositive: number;
unmatchedFalsePositive: number;
unmatchedFalseNegative: number;
precisionIou50: number;
recallIou50: number;
f1Iou50: number;
errorCaseCount: number;
customReferenceCount: number;
perClass: Readonly<Record<string, L34AClassMetric>>;
};
cases: readonly L34ACaseSummary[];
caseOrder: readonly number[];
decision: {
assistedAlignmentAvailable: true;
blindAccuracyAvailable: false;
postprocessingIssueConfirmed: boolean;
ontologyGapConfirmed: boolean;
candidateAccepted: false;
modelRetrainingAuthorized: false;
l35BlindGateOpen: false;
nextAction: string;
};
limitations: readonly string[];
groundTruth: false;
access: "read-only";
}
export interface L34AAuditPrediction {
predictionIndex: number;
category: string;
score: number;
boxXyxy: readonly [number, number, number, number];
verdict: L34APredictionVerdict;
matchedObjectId: string | null;
matchIou: number | null;
}
export interface L34AAuditAnnotation {
objectId: string;
category: string;
proposedLabel: string | null;
displayCategory: string;
origin: "manual" | "frozen_candidate_seed";
boxXyxy: readonly [number, number, number, number];
occluded: boolean;
truncated: boolean;
verdict: L34AAnnotationVerdict;
matchedPredictionIndex: number | null;
matchIou: number | null;
}
export interface L34AAuditCase {
resultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
cameraWidth: number;
cameraHeight: number;
cameraUrl: string;
predictions: readonly L34AAuditPrediction[];
annotations: readonly L34AAuditAnnotation[];
summary: L34ACaseSummaryMetrics;
groundTruth: false;
access: "read-only";
}
export type L34ALaboratoryFetch = (
input: RequestInfo | URL,
init?: RequestInit,
) => Promise<Response>;
export class L34AContractError extends Error {
constructor(message: string) {
super(message);
this.name = "L34AContractError";
}
}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new L34AContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function string(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new L34AContractError(`${label}: ожидалась строка.`);
}
return value;
}
function exact<T>(value: unknown, expected: T, label: string): T {
if (value !== expected) {
throw new L34AContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function integer(value: unknown, label: string): number {
if (!Number.isInteger(value) || Number(value) < 0) {
throw new L34AContractError(`${label}: ожидалось целое число.`);
}
return Number(value);
}
function finite(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new L34AContractError(`${label}: ожидалось число.`);
}
return value;
}
function boolean(value: unknown, label: string): boolean {
if (typeof value !== "boolean") {
throw new L34AContractError(`${label}: ожидалось логическое значение.`);
}
return value;
}
function ratio(value: unknown, label: string): number {
const parsed = finite(value, label);
if (parsed < 0 || parsed > 1) {
throw new L34AContractError(`${label}: нарушен диапазон.`);
}
return parsed;
}
function sha(value: unknown, label: string): string {
const parsed = string(value, label);
if (!/^[a-f0-9]{64}$/.test(parsed)) {
throw new L34AContractError(`${label}: нарушен SHA-256.`);
}
return parsed;
}
function box(value: unknown, label: string): readonly [number, number, number, number] {
if (!Array.isArray(value) || value.length !== 4) {
throw new L34AContractError(`${label}: ожидалась рамка xyxy.`);
}
const parsed = value.map((coordinate) => finite(coordinate, label));
if (!(0 <= parsed[0] && parsed[0] < parsed[2] && parsed[2] <= 800
&& 0 <= parsed[1] && parsed[1] < parsed[3] && parsed[3] <= 600)) {
throw new L34AContractError(`${label}: нарушена геометрия.`);
}
return parsed as [number, number, number, number];
}
function summary(value: unknown, label: string): L34ACaseSummaryMetrics {
const item = object(value, label);
return {
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
severityScore: integer(item.severity_score, `${label}.severity_score`),
};
}
function parseCaseSummary(value: unknown): L34ACaseSummary {
const item = object(value, "L3.4A case summary");
const sequence = integer(item.truth_island_sequence, "L3.4A case sequence");
if (sequence < 1 || sequence > 32) {
throw new L34AContractError("L3.4A case sequence: нарушен диапазон.");
}
return {
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4A case image"),
frameIndex: integer(item.frame_index, "L3.4A case frame"),
groupId: string(item.group_id, "L3.4A case group"),
sessionSeconds: finite(item.session_seconds, "L3.4A case time"),
sourceImageSha256: sha(item.source_image_sha256, "L3.4A case source"),
summary: summary(item.summary, "L3.4A case summary.metrics"),
};
}
function parseClassMetrics(value: unknown): Readonly<Record<string, L34AClassMetric>> {
const metrics = object(value, "L3.4A per-class metrics");
return Object.fromEntries(Object.entries(metrics).map(([category, raw]) => {
const item = object(raw, `L3.4A class ${category}`);
return [category, {
referenceCount: integer(item.reference_count, `${category}.reference_count`),
truePositive: integer(item.true_positive, `${category}.true_positive`),
falsePositive: integer(item.false_positive, `${category}.false_positive`),
falseNegative: integer(item.false_negative, `${category}.false_negative`),
precisionIou50: ratio(item.precision_iou50, `${category}.precision_iou50`),
recallIou50: ratio(item.recall_iou50, `${category}.recall_iou50`),
} satisfies L34AClassMetric];
}));
}
function parseResult(value: unknown): L34AAssistedYoloxErrorAuditResult {
const item = object(value, "L3.4A");
const resultId = string(item.result_id, "L3.4A.result_id");
if (!/^l34a-assisted-yolox-error-audit-[a-f0-9]{64}$/.test(resultId)) {
throw new L34AContractError("L3.4A.result_id: нарушена идентичность.");
}
const assisted = object(item.assisted_annotation, "L3.4A assisted annotation");
const metrics = object(item.metrics, "L3.4A metrics");
const decision = object(item.decision, "L3.4A decision");
const cases = Array.isArray(item.cases) ? item.cases.map(parseCaseSummary) : [];
if (cases.length !== 32 || new Set(cases.map((entry) => entry.truthIslandSequence)).size !== 32) {
throw new L34AContractError("L3.4A cases: требуется 32 уникальных кадра.");
}
if (!Array.isArray(item.case_order) || item.case_order.length !== 32) {
throw new L34AContractError("L3.4A case order: нарушен размер.");
}
const caseOrder = item.case_order.map((entry) => integer(entry, "L3.4A case order"));
if (new Set(caseOrder).size !== 32 || caseOrder.some((entry) => entry < 1 || entry > 32)) {
throw new L34AContractError("L3.4A case order: нарушено покрытие.");
}
if (!Array.isArray(item.limitations) || item.limitations.some((entry) => typeof entry !== "string")) {
throw new L34AContractError("L3.4A limitations: ожидался список строк.");
}
const sessionId = string(assisted.session_id, "L3.4A annotation session");
if (!/^l34-annotation-session-[a-f0-9]{64}$/.test(sessionId)) {
throw new L34AContractError("L3.4A annotation session: нарушена идентичность.");
}
return {
resultId,
createdAtUtc: string(item.created_at_utc, "L3.4A.created_at_utc"),
status: exact(item.status, "completed-assisted-candidate-error-audit-not-truth", "L3.4A.status"),
profileId: string(item.profile_id, "L3.4A.profile_id"),
pipelineId: string(item.pipeline_id, "L3.4A.pipeline_id"),
sourceSessionId: string(item.source_session_id, "L3.4A.source_session_id"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "L3.4A.camera_source_id"),
assistedAnnotation: {
sessionId,
sessionSha256: sha(assisted.session_sha256, "L3.4A annotation sha"),
revision: integer(assisted.revision, "L3.4A annotation revision"),
updatedAtUtc: string(assisted.updated_at_utc, "L3.4A annotation time"),
independentTruthEligible: exact(assisted.independent_truth_eligible, false, "L3.4A independent truth"),
},
metrics: {
frameCount: integer(metrics.frame_count, "L3.4A frame count"),
predictionCount: integer(metrics.prediction_count, "L3.4A prediction count"),
referenceCount: integer(metrics.reference_count, "L3.4A reference count"),
truePositive: integer(metrics.true_positive, "L3.4A TP"),
falsePositive: integer(metrics.false_positive, "L3.4A FP"),
falseNegative: integer(metrics.false_negative, "L3.4A FN"),
classMismatch: integer(metrics.class_mismatch, "L3.4A mismatch"),
duplicateFalsePositive: integer(metrics.duplicate_false_positive, "L3.4A duplicates"),
unmatchedFalsePositive: integer(metrics.unmatched_false_positive, "L3.4A unmatched FP"),
unmatchedFalseNegative: integer(metrics.unmatched_false_negative, "L3.4A unmatched FN"),
precisionIou50: ratio(metrics.precision_iou50, "L3.4A precision"),
recallIou50: ratio(metrics.recall_iou50, "L3.4A recall"),
f1Iou50: ratio(metrics.f1_iou50, "L3.4A F1"),
errorCaseCount: integer(metrics.error_case_count, "L3.4A error cases"),
customReferenceCount: integer(metrics.custom_reference_count, "L3.4A custom references"),
perClass: parseClassMetrics(metrics.per_class),
},
cases,
caseOrder,
decision: {
assistedAlignmentAvailable: exact(decision.assisted_alignment_available, true, "L3.4A assisted alignment"),
blindAccuracyAvailable: exact(decision.blind_accuracy_available, false, "L3.4A blind accuracy"),
postprocessingIssueConfirmed: boolean(decision.postprocessing_issue_confirmed, "L3.4A postprocessing issue"),
ontologyGapConfirmed: boolean(decision.ontology_gap_confirmed, "L3.4A ontology gap"),
candidateAccepted: exact(decision.candidate_accepted, false, "L3.4A candidate acceptance"),
modelRetrainingAuthorized: exact(decision.model_retraining_authorized, false, "L3.4A retraining authority"),
l35BlindGateOpen: exact(decision.l35_blind_gate_open, false, "L3.5 gate"),
nextAction: string(decision.next_action, "L3.4A next action"),
},
limitations: item.limitations as string[],
groundTruth: exact(item.ground_truth, false, "L3.4A ground truth"),
access: exact(item.access, "read-only", "L3.4A access"),
};
}
const PREDICTION_VERDICTS: readonly L34APredictionVerdict[] = [
"true_positive",
"class_mismatch",
"duplicate_false_positive",
"false_positive",
];
const ANNOTATION_VERDICTS: readonly L34AAnnotationVerdict[] = [
"true_positive",
"class_mismatch",
"false_negative",
];
function nullableRatio(value: unknown, label: string): number | null {
return value === null ? null : ratio(value, label);
}
function parseCase(value: unknown, resultId: string, sequence: number): L34AAuditCase {
const item = object(value, "L3.4A visual case");
exact(item.schema_version, "missioncore.l34a-assisted-yolox-error-case/v1", "L3.4A case schema");
exact(item.result_id, resultId, "L3.4A case result");
exact(item.truth_island_sequence, sequence, "L3.4A case sequence");
const camera = object(item.camera, "L3.4A camera");
const rawPredictions = Array.isArray(item.predictions) ? item.predictions : [];
const rawAnnotations = Array.isArray(item.annotations) ? item.annotations : [];
const predictions = rawPredictions.map((raw, index): L34AAuditPrediction => {
const prediction = object(raw, `L3.4A prediction ${index + 1}`);
const verdict = string(prediction.verdict, "L3.4A prediction verdict") as L34APredictionVerdict;
if (!PREDICTION_VERDICTS.includes(verdict)) throw new L34AContractError("L3.4A prediction verdict: неизвестное значение.");
return {
predictionIndex: integer(prediction.prediction_index, "L3.4A prediction index"),
category: string(prediction.category, "L3.4A prediction category"),
score: ratio(prediction.score, "L3.4A prediction score"),
boxXyxy: box(prediction.box_xyxy, "L3.4A prediction box"),
verdict,
matchedObjectId: prediction.matched_object_id === null ? null : string(prediction.matched_object_id, "L3.4A matched object"),
matchIou: nullableRatio(prediction.match_iou, "L3.4A prediction IoU"),
};
});
const annotations = rawAnnotations.map((raw, index): L34AAuditAnnotation => {
const annotation = object(raw, `L3.4A annotation ${index + 1}`);
const verdict = string(annotation.verdict, "L3.4A annotation verdict") as L34AAnnotationVerdict;
if (!ANNOTATION_VERDICTS.includes(verdict)) throw new L34AContractError("L3.4A annotation verdict: неизвестное значение.");
return {
objectId: string(annotation.object_id, "L3.4A annotation id"),
category: string(annotation.category, "L3.4A annotation category"),
proposedLabel: annotation.proposed_label === null ? null : string(annotation.proposed_label, "L3.4A proposed label"),
displayCategory: string(annotation.display_category, "L3.4A display category"),
origin: exact(
annotation.origin,
annotation.origin === "manual" ? "manual" : "frozen_candidate_seed",
"L3.4A annotation origin",
),
boxXyxy: box(annotation.box_xyxy, "L3.4A annotation box"),
occluded: boolean(annotation.occluded, "L3.4A annotation occluded"),
truncated: boolean(annotation.truncated, "L3.4A annotation truncated"),
verdict,
matchedPredictionIndex: annotation.matched_prediction_index === null ? null : integer(annotation.matched_prediction_index, "L3.4A matched prediction"),
matchIou: nullableRatio(annotation.match_iou, "L3.4A annotation IoU"),
};
});
return {
resultId,
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4A case image"),
frameIndex: integer(item.frame_index, "L3.4A case frame"),
groupId: string(item.group_id, "L3.4A case group"),
sessionSeconds: finite(item.session_seconds, "L3.4A case time"),
sourceImageSha256: sha(item.source_image_sha256, "L3.4A case source"),
cameraWidth: integer(camera.width, "L3.4A camera width"),
cameraHeight: integer(camera.height, "L3.4A camera height"),
cameraUrl: `/api/v1/laboratory/l34a/results/${resultId}/cases/${sequence}/camera`,
predictions,
annotations,
summary: summary(item.summary, "L3.4A visual summary"),
groundTruth: exact(item.ground_truth, false, "L3.4A visual ground truth"),
access: exact(item.access, "read-only", "L3.4A visual access"),
};
}
export async function fetchL34AAssistedYoloxErrorAudit({
fetcher = fetch,
signal,
}: {
fetcher?: L34ALaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<L34AAssistedYoloxErrorAuditResult> {
const response = await fetcher("/api/v1/laboratory/l34a/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new L34AContractError(`L3.4A недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "L3.4A catalog");
exact(catalog.schema_version, "missioncore.l34a-assisted-yolox-error-catalog/v1", "L3.4A catalog schema");
exact(catalog.access, "read-only", "L3.4A catalog access");
if (!Array.isArray(catalog.items) || catalog.items.length !== 1) {
throw new L34AContractError("L3.4A catalog: ожидался один результат.");
}
return parseResult(catalog.items[0]);
}
export async function fetchL34AAuditCase(
resultId: string,
sequence: number,
{
fetcher = fetch,
signal,
}: {
fetcher?: L34ALaboratoryFetch;
signal?: AbortSignal;
} = {},
): Promise<L34AAuditCase> {
if (!/^l34a-assisted-yolox-error-audit-[a-f0-9]{64}$/.test(resultId) || !Number.isInteger(sequence) || sequence < 1 || sequence > 32) {
throw new L34AContractError("L3.4A visual case: неверная идентичность.");
}
const response = await fetcher(`/api/v1/laboratory/l34a/results/${resultId}/cases/${sequence}`, {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) throw new L34AContractError(`L3.4A visual case недоступен: HTTP ${response.status}.`);
return parseCase(await response.json(), resultId, sequence);
}
@@ -0,0 +1,366 @@
import type {
L34AAuditAnnotation,
L34AAuditPrediction,
L34ACaseSummaryMetrics,
L34ALaboratoryFetch,
} from "./l34aAssistedYoloxErrorAudit";
export interface L34BMetricSet {
frameCount: number;
predictionCount: number;
referenceCount: number;
truePositive: number;
falsePositive: number;
falseNegative: number;
classMismatch: number;
duplicateFalsePositive: number;
unmatchedFalsePositive: number;
unmatchedFalseNegative: number;
precisionIou50: number;
recallIou50: number;
f1Iou50: number;
errorCaseCount: number;
customReferenceCount: number;
}
export interface L34BCaseSummary {
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
beforeSummary: L34ACaseSummaryMetrics;
afterSummary: L34ACaseSummaryMetrics;
consolidationCount: number;
}
export interface L34BResult {
resultId: string;
createdAtUtc: string;
status: "completed-nested-box-consolidation-shadow-not-truth";
profile: {
profileId: string;
categoryPolicy: string;
overlapMetric: string;
overlapThreshold: number;
geometryPolicy: string;
scorePolicy: string;
scope: string;
};
pipelineId: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
metrics: {
before: L34BMetricSet;
after: L34BMetricSet;
delta: Readonly<Record<string, number>>;
consolidationCount: number;
affectedCaseCount: number;
assistedRegressionFree: boolean;
};
cases: readonly L34BCaseSummary[];
caseOrder: readonly number[];
decision: {
shadowPolicyAccepted: boolean;
classicIouNmsFixRejected: boolean;
remainingL34aDuplicateSignals: number;
nextAction: string;
};
limitations: readonly string[];
groundTruth: false;
access: "read-only";
}
export interface L34BPrediction extends L34AAuditPrediction {
sourcePredictionIndices: readonly number[];
}
export interface L34BConsolidation {
category: string;
sourcePredictionIndices: readonly number[];
sourceScores: readonly number[];
sourceBoxesXyxy: readonly (readonly [number, number, number, number])[];
mergedScore: number;
mergedBoxXyxy: readonly [number, number, number, number];
minimumOverlapOverSmaller: number;
outputPredictionIndex: number;
}
export interface L34BCase {
resultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
cameraWidth: number;
cameraHeight: number;
cameraUrl: string;
beforePredictions: readonly L34AAuditPrediction[];
afterPredictions: readonly L34BPrediction[];
annotations: readonly L34AAuditAnnotation[];
consolidations: readonly L34BConsolidation[];
beforeSummary: L34ACaseSummaryMetrics;
afterSummary: L34ACaseSummaryMetrics;
groundTruth: false;
access: "read-only";
}
export class L34BContractError extends Error {
constructor(message: string) {
super(message);
this.name = "L34BContractError";
}
}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new L34BContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function text(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) throw new L34BContractError(`${label}: ожидалась строка.`);
return value;
}
function exact<T>(value: unknown, expected: T, label: string): T {
if (value !== expected) throw new L34BContractError(`${label}: нарушен контракт.`);
return expected;
}
function integer(value: unknown, label: string): number {
if (!Number.isInteger(value) || Number(value) < 0) throw new L34BContractError(`${label}: ожидалось целое число.`);
return Number(value);
}
function finite(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) throw new L34BContractError(`${label}: ожидалось число.`);
return value;
}
function ratio(value: unknown, label: string): number {
const parsed = finite(value, label);
if (parsed < 0 || parsed > 1) throw new L34BContractError(`${label}: нарушен диапазон.`);
return parsed;
}
function bool(value: unknown, label: string): boolean {
if (typeof value !== "boolean") throw new L34BContractError(`${label}: ожидалось логическое значение.`);
return value;
}
function box(value: unknown, label: string): readonly [number, number, number, number] {
if (!Array.isArray(value) || value.length !== 4) throw new L34BContractError(`${label}: ожидалась рамка.`);
const parsed = value.map((entry) => finite(entry, label));
if (!(0 <= parsed[0] && parsed[0] < parsed[2] && parsed[2] <= 800
&& 0 <= parsed[1] && parsed[1] < parsed[3] && parsed[3] <= 600)) {
throw new L34BContractError(`${label}: нарушена геометрия.`);
}
return parsed as [number, number, number, number];
}
function summary(value: unknown, label: string): L34ACaseSummaryMetrics {
const item = object(value, label);
return {
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
severityScore: integer(item.severity_score, `${label}.severity_score`),
};
}
function metrics(value: unknown, label: string): L34BMetricSet {
const item = object(value, label);
return {
frameCount: integer(item.frame_count, `${label}.frame_count`),
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
precisionIou50: ratio(item.precision_iou50, `${label}.precision_iou50`),
recallIou50: ratio(item.recall_iou50, `${label}.recall_iou50`),
f1Iou50: ratio(item.f1_iou50, `${label}.f1_iou50`),
errorCaseCount: integer(item.error_case_count, `${label}.error_case_count`),
customReferenceCount: integer(item.custom_reference_count, `${label}.custom_reference_count`),
};
}
function parseResult(value: unknown): L34BResult {
const item = object(value, "L3.4B");
const resultId = text(item.result_id, "L3.4B.result_id");
if (!/^l34b-nested-box-consolidation-shadow-[a-f0-9]{64}$/.test(resultId)) throw new L34BContractError("L3.4B.result_id: нарушена идентичность.");
const profile = object(item.profile, "L3.4B.profile");
const rawMetrics = object(item.metrics, "L3.4B.metrics");
const rawDecision = object(item.decision, "L3.4B.decision");
const cases = Array.isArray(item.cases) ? item.cases.map((raw): L34BCaseSummary => {
const current = object(raw, "L3.4B.case summary");
return {
truthIslandSequence: integer(current.truth_island_sequence, "L3.4B.case.sequence"),
imageId: integer(current.image_id, "L3.4B.case.image"),
frameIndex: integer(current.frame_index, "L3.4B.case.frame"),
groupId: text(current.group_id, "L3.4B.case.group"),
sessionSeconds: finite(current.session_seconds, "L3.4B.case.time"),
sourceImageSha256: text(current.source_image_sha256, "L3.4B.case.source"),
beforeSummary: summary(current.before_summary, "L3.4B.case.before"),
afterSummary: summary(current.after_summary, "L3.4B.case.after"),
consolidationCount: integer(current.consolidation_count, "L3.4B.case.consolidations"),
};
}) : [];
if (cases.length !== 32 || !Array.isArray(item.case_order) || item.case_order.length !== 32) throw new L34BContractError("L3.4B: требуется 32 кадра.");
const delta = object(rawMetrics.delta, "L3.4B.metrics.delta");
return {
resultId,
createdAtUtc: text(item.created_at_utc, "L3.4B.created_at"),
status: exact(item.status, "completed-nested-box-consolidation-shadow-not-truth", "L3.4B.status"),
profile: {
profileId: text(profile.profile_id, "L3.4B.profile.id"),
categoryPolicy: text(profile.category_policy, "L3.4B.profile.category"),
overlapMetric: text(profile.overlap_metric, "L3.4B.profile.metric"),
overlapThreshold: ratio(profile.overlap_threshold, "L3.4B.profile.threshold"),
geometryPolicy: text(profile.geometry_policy, "L3.4B.profile.geometry"),
scorePolicy: text(profile.score_policy, "L3.4B.profile.score"),
scope: text(profile.scope, "L3.4B.profile.scope"),
},
pipelineId: text(item.pipeline_id, "L3.4B.pipeline"),
sourceSessionId: text(item.source_session_id, "L3.4B.session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "L3.4B.camera"),
metrics: {
before: metrics(rawMetrics.before, "L3.4B.before"),
after: metrics(rawMetrics.after, "L3.4B.after"),
delta: Object.fromEntries(Object.entries(delta).map(([key, raw]) => [key, finite(raw, `L3.4B.delta.${key}`)])),
consolidationCount: integer(rawMetrics.consolidation_count, "L3.4B.consolidation_count"),
affectedCaseCount: integer(rawMetrics.affected_case_count, "L3.4B.affected_case_count"),
assistedRegressionFree: bool(rawMetrics.assisted_regression_free, "L3.4B.regression_free"),
},
cases,
caseOrder: item.case_order.map((entry) => integer(entry, "L3.4B.case_order")),
decision: {
shadowPolicyAccepted: bool(rawDecision.shadow_policy_accepted, "L3.4B.shadow accepted"),
classicIouNmsFixRejected: bool(rawDecision.classic_iou_nms_fix_rejected, "L3.4B.NMS rejected"),
remainingL34aDuplicateSignals: integer(rawDecision.remaining_l34a_duplicate_signals, "L3.4B.remaining signals"),
nextAction: text(rawDecision.next_action, "L3.4B.next action"),
},
limitations: Array.isArray(item.limitations) ? item.limitations.map((entry) => text(entry, "L3.4B.limitation")) : [],
groundTruth: exact(item.ground_truth, false, "L3.4B.truth"),
access: exact(item.access, "read-only", "L3.4B.access"),
};
}
const PREDICTION_VERDICTS = new Set(["true_positive", "class_mismatch", "duplicate_false_positive", "false_positive"]);
const ANNOTATION_VERDICTS = new Set(["true_positive", "class_mismatch", "false_negative"]);
function parsePrediction(raw: unknown, label: string, withSources: boolean): L34BPrediction {
const item = object(raw, label);
const verdict = text(item.verdict, `${label}.verdict`);
if (!PREDICTION_VERDICTS.has(verdict)) throw new L34BContractError(`${label}: неизвестный verdict.`);
return {
predictionIndex: integer(item.prediction_index, `${label}.index`),
category: text(item.category, `${label}.category`),
score: ratio(item.score, `${label}.score`),
boxXyxy: box(item.box_xyxy, `${label}.box`),
verdict: verdict as L34AAuditPrediction["verdict"],
matchedObjectId: item.matched_object_id === null ? null : text(item.matched_object_id, `${label}.match`),
matchIou: item.match_iou === null ? null : ratio(item.match_iou, `${label}.iou`),
sourcePredictionIndices: withSources && Array.isArray(item.source_prediction_indices)
? item.source_prediction_indices.map((entry) => integer(entry, `${label}.source`))
: [integer(item.prediction_index, `${label}.index`)],
};
}
function parseAnnotation(raw: unknown, label: string): L34AAuditAnnotation {
const item = object(raw, label);
const verdict = text(item.verdict, `${label}.verdict`);
if (!ANNOTATION_VERDICTS.has(verdict)) throw new L34BContractError(`${label}: неизвестный verdict.`);
return {
objectId: text(item.object_id, `${label}.id`),
category: text(item.category, `${label}.category`),
proposedLabel: item.proposed_label === null ? null : text(item.proposed_label, `${label}.proposed`),
displayCategory: text(item.display_category, `${label}.display`),
origin: item.origin === "manual" ? "manual" : "frozen_candidate_seed",
boxXyxy: box(item.box_xyxy, `${label}.box`),
occluded: bool(item.occluded, `${label}.occluded`),
truncated: bool(item.truncated, `${label}.truncated`),
verdict: verdict as L34AAuditAnnotation["verdict"],
matchedPredictionIndex: item.matched_prediction_index === null ? null : integer(item.matched_prediction_index, `${label}.match`),
matchIou: item.match_iou === null ? null : ratio(item.match_iou, `${label}.iou`),
};
}
function parseCase(value: unknown, resultId: string, sequence: number): L34BCase {
const item = object(value, "L3.4B.case");
exact(item.schema_version, "missioncore.l34b-nested-box-consolidation-case/v1", "L3.4B.case.schema");
exact(item.result_id, resultId, "L3.4B.case.result");
exact(item.truth_island_sequence, sequence, "L3.4B.case.sequence");
const camera = object(item.camera, "L3.4B.case.camera");
const consolidations = Array.isArray(item.consolidations) ? item.consolidations.map((raw): L34BConsolidation => {
const current = object(raw, "L3.4B.consolidation");
return {
category: text(current.category, "L3.4B.consolidation.category"),
sourcePredictionIndices: Array.isArray(current.source_prediction_indices) ? current.source_prediction_indices.map((entry) => integer(entry, "L3.4B.consolidation.source")) : [],
sourceScores: Array.isArray(current.source_scores) ? current.source_scores.map((entry) => ratio(entry, "L3.4B.consolidation.score")) : [],
sourceBoxesXyxy: Array.isArray(current.source_boxes_xyxy) ? current.source_boxes_xyxy.map((entry) => box(entry, "L3.4B.consolidation.source box")) : [],
mergedScore: ratio(current.merged_score, "L3.4B.consolidation.merged score"),
mergedBoxXyxy: box(current.merged_box_xyxy, "L3.4B.consolidation.merged box"),
minimumOverlapOverSmaller: ratio(current.minimum_overlap_over_smaller, "L3.4B.consolidation.overlap"),
outputPredictionIndex: integer(current.output_prediction_index, "L3.4B.consolidation.output"),
};
}) : [];
return {
resultId,
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4B.case.image"),
frameIndex: integer(item.frame_index, "L3.4B.case.frame"),
groupId: text(item.group_id, "L3.4B.case.group"),
sessionSeconds: finite(item.session_seconds, "L3.4B.case.time"),
sourceImageSha256: text(item.source_image_sha256, "L3.4B.case.source"),
cameraWidth: integer(camera.width, "L3.4B.case.width"),
cameraHeight: integer(camera.height, "L3.4B.case.height"),
cameraUrl: `/api/v1/laboratory/l34b/results/${resultId}/cases/${sequence}/camera`,
beforePredictions: Array.isArray(item.before_predictions) ? item.before_predictions.map((raw, index) => parsePrediction(raw, `L3.4B.before.${index}`, false)) : [],
afterPredictions: Array.isArray(item.after_predictions) ? item.after_predictions.map((raw, index) => parsePrediction(raw, `L3.4B.after.${index}`, true)) : [],
annotations: Array.isArray(item.annotations) ? item.annotations.map((raw, index) => parseAnnotation(raw, `L3.4B.annotation.${index}`)) : [],
consolidations,
beforeSummary: summary(item.before_summary, "L3.4B.case.before summary"),
afterSummary: summary(item.after_summary, "L3.4B.case.after summary"),
groundTruth: exact(item.ground_truth, false, "L3.4B.case.truth"),
access: exact(item.access, "read-only", "L3.4B.case.access"),
};
}
export async function fetchL34BNestedBoxConsolidation({
fetcher = fetch,
signal,
}: { fetcher?: L34ALaboratoryFetch; signal?: AbortSignal } = {}): Promise<L34BResult> {
const response = await fetcher("/api/v1/laboratory/l34b/results?limit=1", { method: "GET", headers: { Accept: "application/json" }, signal });
if (!response.ok) throw new L34BContractError(`L3.4B недоступен: HTTP ${response.status}.`);
const catalog = object(await response.json(), "L3.4B.catalog");
exact(catalog.schema_version, "missioncore.l34b-nested-box-consolidation-catalog/v1", "L3.4B.catalog.schema");
if (!Array.isArray(catalog.items) || catalog.items.length !== 1) throw new L34BContractError("L3.4B.catalog: ожидался один результат.");
return parseResult(catalog.items[0]);
}
export async function fetchL34BCase(
resultId: string,
sequence: number,
{ fetcher = fetch, signal }: { fetcher?: L34ALaboratoryFetch; signal?: AbortSignal } = {},
): Promise<L34BCase> {
if (!/^l34b-nested-box-consolidation-shadow-[a-f0-9]{64}$/.test(resultId) || !Number.isInteger(sequence) || sequence < 1 || sequence > 32) throw new L34BContractError("L3.4B.case: неверная идентичность.");
const response = await fetcher(`/api/v1/laboratory/l34b/results/${resultId}/cases/${sequence}`, { method: "GET", headers: { Accept: "application/json" }, signal });
if (!response.ok) throw new L34BContractError(`L3.4B.case недоступен: HTTP ${response.status}.`);
return parseCase(await response.json(), resultId, sequence);
}
@@ -0,0 +1,462 @@
import type {
L34AAuditAnnotation,
L34AAuditPrediction,
L34ACaseSummaryMetrics,
L34ALaboratoryFetch,
} from "./l34aAssistedYoloxErrorAudit";
import type { L34BMetricSet } from "./l34bNestedBoxConsolidation";
export type L34CRectificationTile = "front" | "left" | "right";
export interface L34CCaseSummary {
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
beforeSummary: L34ACaseSummaryMetrics;
afterSummary: L34ACaseSummaryMetrics;
stitchCount: number;
}
export interface L34CResult {
resultId: string;
createdAtUtc: string;
status: "completed-temporal-tile-seam-stitch-shadow-not-truth";
profile: {
profileId: string;
categoryPolicy: string;
tilePolicy: string;
horizontalOverlapThreshold: number;
verticalOverlapThreshold: number;
minimumUnionAreaFraction: number;
temporalUnionIouThreshold: number;
minimumConsecutiveFrames: number;
geometryPolicy: string;
scorePolicy: string;
scope: string;
};
pipelineId: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
metrics: {
before: L34BMetricSet;
after: L34BMetricSet;
delta: Readonly<Record<string, number>>;
staticCandidateCount: number;
temporallyRejectedCandidateCount: number;
stitchCount: number;
affectedCaseCount: number;
temporalRunCount: number;
assistedRegressionFree: boolean;
};
cases: readonly L34CCaseSummary[];
caseOrder: readonly number[];
decision: {
shadowPolicyAccepted: boolean;
predictionProvenancePreserved: boolean;
globalNmsUnchanged: boolean;
remainingL34aDuplicateSignals: number;
nextAction: string;
};
limitations: readonly string[];
groundTruth: false;
access: "read-only";
}
export interface L34CBeforePrediction extends L34AAuditPrediction {
rectificationTile: L34CRectificationTile;
rawLabel: string;
classId: number;
rawCenterXy: readonly [number, number];
}
export interface L34CAfterPrediction extends L34AAuditPrediction {
sourcePredictionIndices: readonly number[];
sourceRectificationTiles: readonly L34CRectificationTile[];
}
export interface L34CStitch {
category: string;
sourcePredictionIndices: readonly number[];
sourceTiles: readonly L34CRectificationTile[];
sourceScores: readonly number[];
sourceBoxesXyxy: readonly (readonly [number, number, number, number])[];
mergedScore: number;
mergedBoxXyxy: readonly [number, number, number, number];
horizontalOverlapOverSmaller: number;
verticalOverlapOverSmaller: number;
sourceIou: number;
unionAreaFraction: number;
temporalRunId: string;
temporalRunLength: number;
}
export interface L34CCase {
resultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
cameraWidth: number;
cameraHeight: number;
cameraUrl: string;
beforePredictions: readonly L34CBeforePrediction[];
afterPredictions: readonly L34CAfterPrediction[];
annotations: readonly L34AAuditAnnotation[];
stitches: readonly L34CStitch[];
beforeSummary: L34ACaseSummaryMetrics;
afterSummary: L34ACaseSummaryMetrics;
groundTruth: false;
access: "read-only";
}
export class L34CContractError extends Error {
constructor(message: string) {
super(message);
this.name = "L34CContractError";
}
}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new L34CContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function text(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new L34CContractError(`${label}: ожидалась строка.`);
}
return value;
}
function exact<T>(value: unknown, expected: T, label: string): T {
if (value !== expected) {
throw new L34CContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function integer(value: unknown, label: string): number {
if (!Number.isInteger(value) || Number(value) < 0) {
throw new L34CContractError(`${label}: ожидалось целое число.`);
}
return Number(value);
}
function finite(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new L34CContractError(`${label}: ожидалось число.`);
}
return value;
}
function ratio(value: unknown, label: string): number {
const parsed = finite(value, label);
if (parsed < 0 || parsed > 1) {
throw new L34CContractError(`${label}: нарушен диапазон.`);
}
return parsed;
}
function bool(value: unknown, label: string): boolean {
if (typeof value !== "boolean") {
throw new L34CContractError(`${label}: ожидалось логическое значение.`);
}
return value;
}
function box(
value: unknown,
label: string,
): readonly [number, number, number, number] {
if (!Array.isArray(value) || value.length !== 4) {
throw new L34CContractError(`${label}: ожидалась рамка.`);
}
const parsed = value.map((entry) => finite(entry, label));
if (!(0 <= parsed[0] && parsed[0] < parsed[2] && parsed[2] <= 800
&& 0 <= parsed[1] && parsed[1] < parsed[3] && parsed[3] <= 600)) {
throw new L34CContractError(`${label}: нарушена геометрия.`);
}
return parsed as [number, number, number, number];
}
function point(value: unknown, label: string): readonly [number, number] {
if (!Array.isArray(value) || value.length !== 2) {
throw new L34CContractError(`${label}: ожидалась точка.`);
}
return [finite(value[0], label), finite(value[1], label)];
}
function tile(value: unknown, label: string): L34CRectificationTile {
if (value !== "front" && value !== "left" && value !== "right") {
throw new L34CContractError(`${label}: неизвестный rectification tile.`);
}
return value;
}
function summary(value: unknown, label: string): L34ACaseSummaryMetrics {
const item = object(value, label);
return {
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
severityScore: integer(item.severity_score, `${label}.severity_score`),
};
}
function metrics(value: unknown, label: string): L34BMetricSet {
const item = object(value, label);
return {
frameCount: integer(item.frame_count, `${label}.frame_count`),
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
precisionIou50: ratio(item.precision_iou50, `${label}.precision_iou50`),
recallIou50: ratio(item.recall_iou50, `${label}.recall_iou50`),
f1Iou50: ratio(item.f1_iou50, `${label}.f1_iou50`),
errorCaseCount: integer(item.error_case_count, `${label}.error_case_count`),
customReferenceCount: integer(item.custom_reference_count, `${label}.custom_reference_count`),
};
}
function parseResult(value: unknown): L34CResult {
const item = object(value, "L3.4C");
const resultId = text(item.result_id, "L3.4C.result_id");
if (!/^l34c-tile-seam-stitch-shadow-[a-f0-9]{64}$/.test(resultId)) {
throw new L34CContractError("L3.4C.result_id: нарушена идентичность.");
}
const profile = object(item.profile, "L3.4C.profile");
const rawMetrics = object(item.metrics, "L3.4C.metrics");
const rawDecision = object(item.decision, "L3.4C.decision");
const cases = Array.isArray(item.cases) ? item.cases.map((raw): L34CCaseSummary => {
const current = object(raw, "L3.4C.case summary");
return {
truthIslandSequence: integer(current.truth_island_sequence, "L3.4C.case.sequence"),
imageId: integer(current.image_id, "L3.4C.case.image"),
frameIndex: integer(current.frame_index, "L3.4C.case.frame"),
groupId: text(current.group_id, "L3.4C.case.group"),
sessionSeconds: finite(current.session_seconds, "L3.4C.case.time"),
sourceImageSha256: text(current.source_image_sha256, "L3.4C.case.source"),
beforeSummary: summary(current.before_summary, "L3.4C.case.before"),
afterSummary: summary(current.after_summary, "L3.4C.case.after"),
stitchCount: integer(current.stitch_count, "L3.4C.case.stitches"),
};
}) : [];
if (cases.length !== 32 || !Array.isArray(item.case_order) || item.case_order.length !== 32) {
throw new L34CContractError("L3.4C: требуется 32 кадра.");
}
const delta = object(rawMetrics.delta, "L3.4C.metrics.delta");
return {
resultId,
createdAtUtc: text(item.created_at_utc, "L3.4C.created_at"),
status: exact(item.status, "completed-temporal-tile-seam-stitch-shadow-not-truth", "L3.4C.status"),
profile: {
profileId: text(profile.profile_id, "L3.4C.profile.id"),
categoryPolicy: text(profile.category_policy, "L3.4C.profile.category"),
tilePolicy: text(profile.tile_policy, "L3.4C.profile.tile"),
horizontalOverlapThreshold: ratio(profile.horizontal_overlap_over_smaller_threshold, "L3.4C.profile.horizontal"),
verticalOverlapThreshold: ratio(profile.vertical_overlap_over_smaller_threshold, "L3.4C.profile.vertical"),
minimumUnionAreaFraction: ratio(profile.minimum_union_area_fraction, "L3.4C.profile.area"),
temporalUnionIouThreshold: ratio(profile.temporal_union_iou_threshold, "L3.4C.profile.temporal"),
minimumConsecutiveFrames: integer(profile.minimum_consecutive_frames, "L3.4C.profile.frames"),
geometryPolicy: text(profile.geometry_policy, "L3.4C.profile.geometry"),
scorePolicy: text(profile.score_policy, "L3.4C.profile.score"),
scope: text(profile.scope, "L3.4C.profile.scope"),
},
pipelineId: text(item.pipeline_id, "L3.4C.pipeline"),
sourceSessionId: text(item.source_session_id, "L3.4C.session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "L3.4C.camera"),
metrics: {
before: metrics(rawMetrics.before, "L3.4C.before"),
after: metrics(rawMetrics.after, "L3.4C.after"),
delta: Object.fromEntries(Object.entries(delta).map(([key, raw]) => [key, finite(raw, `L3.4C.delta.${key}`)])),
staticCandidateCount: integer(rawMetrics.static_candidate_count, "L3.4C.static candidates"),
temporallyRejectedCandidateCount: integer(rawMetrics.temporally_rejected_candidate_count, "L3.4C.rejected candidates"),
stitchCount: integer(rawMetrics.stitch_count, "L3.4C.stitch count"),
affectedCaseCount: integer(rawMetrics.affected_case_count, "L3.4C.affected cases"),
temporalRunCount: integer(rawMetrics.temporal_run_count, "L3.4C.run count"),
assistedRegressionFree: bool(rawMetrics.assisted_regression_free, "L3.4C.regression free"),
},
cases,
caseOrder: item.case_order.map((entry) => integer(entry, "L3.4C.case_order")),
decision: {
shadowPolicyAccepted: bool(rawDecision.shadow_policy_accepted, "L3.4C.shadow accepted"),
predictionProvenancePreserved: bool(rawDecision.prediction_provenance_preserved, "L3.4C.provenance"),
globalNmsUnchanged: bool(rawDecision.global_nms_unchanged, "L3.4C.NMS"),
remainingL34aDuplicateSignals: integer(rawDecision.remaining_l34a_duplicate_signals, "L3.4C.remaining signals"),
nextAction: text(rawDecision.next_action, "L3.4C.next action"),
},
limitations: Array.isArray(item.limitations) ? item.limitations.map((entry) => text(entry, "L3.4C.limitation")) : [],
groundTruth: exact(item.ground_truth, false, "L3.4C.truth"),
access: exact(item.access, "read-only", "L3.4C.access"),
};
}
const PREDICTION_VERDICTS = new Set(["true_positive", "class_mismatch", "duplicate_false_positive", "false_positive"]);
const ANNOTATION_VERDICTS = new Set(["true_positive", "class_mismatch", "false_negative"]);
function predictionBase(raw: unknown, label: string): L34AAuditPrediction {
const item = object(raw, label);
const verdict = text(item.verdict, `${label}.verdict`);
if (!PREDICTION_VERDICTS.has(verdict)) {
throw new L34CContractError(`${label}: неизвестный verdict.`);
}
return {
predictionIndex: integer(item.prediction_index, `${label}.index`),
category: text(item.category, `${label}.category`),
score: ratio(item.score, `${label}.score`),
boxXyxy: box(item.box_xyxy, `${label}.box`),
verdict: verdict as L34AAuditPrediction["verdict"],
matchedObjectId: item.matched_object_id === null ? null : text(item.matched_object_id, `${label}.match`),
matchIou: item.match_iou === null ? null : ratio(item.match_iou, `${label}.iou`),
};
}
function parseBeforePrediction(raw: unknown, label: string): L34CBeforePrediction {
const item = object(raw, label);
return {
...predictionBase(item, label),
rectificationTile: tile(item.rectification_tile, `${label}.tile`),
rawLabel: text(item.raw_label, `${label}.raw label`),
classId: integer(item.class_id, `${label}.class id`),
rawCenterXy: point(item.raw_center_xy, `${label}.raw center`),
};
}
function parseAfterPrediction(raw: unknown, label: string): L34CAfterPrediction {
const item = object(raw, label);
return {
...predictionBase(item, label),
sourcePredictionIndices: Array.isArray(item.source_prediction_indices)
? item.source_prediction_indices.map((entry) => integer(entry, `${label}.source`))
: [],
sourceRectificationTiles: Array.isArray(item.source_rectification_tiles)
? item.source_rectification_tiles.map((entry) => tile(entry, `${label}.tile`))
: [],
};
}
function parseAnnotation(raw: unknown, label: string): L34AAuditAnnotation {
const item = object(raw, label);
const verdict = text(item.verdict, `${label}.verdict`);
if (!ANNOTATION_VERDICTS.has(verdict)) {
throw new L34CContractError(`${label}: неизвестный verdict.`);
}
return {
objectId: text(item.object_id, `${label}.id`),
category: text(item.category, `${label}.category`),
proposedLabel: item.proposed_label === null ? null : text(item.proposed_label, `${label}.proposed`),
displayCategory: text(item.display_category, `${label}.display`),
origin: item.origin === "manual" ? "manual" : "frozen_candidate_seed",
boxXyxy: box(item.box_xyxy, `${label}.box`),
occluded: bool(item.occluded, `${label}.occluded`),
truncated: bool(item.truncated, `${label}.truncated`),
verdict: verdict as L34AAuditAnnotation["verdict"],
matchedPredictionIndex: item.matched_prediction_index === null ? null : integer(item.matched_prediction_index, `${label}.match`),
matchIou: item.match_iou === null ? null : ratio(item.match_iou, `${label}.iou`),
};
}
function parseStitch(raw: unknown): L34CStitch {
const item = object(raw, "L3.4C.stitch");
return {
category: text(item.category, "L3.4C.stitch.category"),
sourcePredictionIndices: Array.isArray(item.source_prediction_indices) ? item.source_prediction_indices.map((entry) => integer(entry, "L3.4C.stitch.source")) : [],
sourceTiles: Array.isArray(item.source_tiles) ? item.source_tiles.map((entry) => tile(entry, "L3.4C.stitch.tile")) : [],
sourceScores: Array.isArray(item.source_scores) ? item.source_scores.map((entry) => ratio(entry, "L3.4C.stitch.score")) : [],
sourceBoxesXyxy: Array.isArray(item.source_boxes_xyxy) ? item.source_boxes_xyxy.map((entry) => box(entry, "L3.4C.stitch.source box")) : [],
mergedScore: ratio(item.merged_score, "L3.4C.stitch.merged score"),
mergedBoxXyxy: box(item.merged_box_xyxy, "L3.4C.stitch.merged box"),
horizontalOverlapOverSmaller: ratio(item.horizontal_overlap_over_smaller, "L3.4C.stitch.horizontal"),
verticalOverlapOverSmaller: ratio(item.vertical_overlap_over_smaller, "L3.4C.stitch.vertical"),
sourceIou: ratio(item.source_iou, "L3.4C.stitch.iou"),
unionAreaFraction: ratio(item.union_area_fraction, "L3.4C.stitch.area"),
temporalRunId: text(item.temporal_run_id, "L3.4C.stitch.run"),
temporalRunLength: integer(item.temporal_run_length, "L3.4C.stitch.run length"),
};
}
function parseCase(value: unknown, resultId: string, sequence: number): L34CCase {
const item = object(value, "L3.4C.case");
exact(item.schema_version, "missioncore.l34c-tile-seam-stitch-case/v1", "L3.4C.case.schema");
exact(item.result_id, resultId, "L3.4C.case.result");
exact(item.truth_island_sequence, sequence, "L3.4C.case.sequence");
const camera = object(item.camera, "L3.4C.case.camera");
return {
resultId,
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4C.case.image"),
frameIndex: integer(item.frame_index, "L3.4C.case.frame"),
groupId: text(item.group_id, "L3.4C.case.group"),
sessionSeconds: finite(item.session_seconds, "L3.4C.case.time"),
sourceImageSha256: text(item.source_image_sha256, "L3.4C.case.source"),
cameraWidth: integer(camera.width, "L3.4C.case.width"),
cameraHeight: integer(camera.height, "L3.4C.case.height"),
cameraUrl: `/api/v1/laboratory/l34c/results/${resultId}/cases/${sequence}/camera`,
beforePredictions: Array.isArray(item.before_predictions) ? item.before_predictions.map((raw, index) => parseBeforePrediction(raw, `L3.4C.before.${index}`)) : [],
afterPredictions: Array.isArray(item.after_predictions) ? item.after_predictions.map((raw, index) => parseAfterPrediction(raw, `L3.4C.after.${index}`)) : [],
annotations: Array.isArray(item.annotations) ? item.annotations.map((raw, index) => parseAnnotation(raw, `L3.4C.annotation.${index}`)) : [],
stitches: Array.isArray(item.stitches) ? item.stitches.map(parseStitch) : [],
beforeSummary: summary(item.before_summary, "L3.4C.case.before summary"),
afterSummary: summary(item.after_summary, "L3.4C.case.after summary"),
groundTruth: exact(item.ground_truth, false, "L3.4C.case.truth"),
access: exact(item.access, "read-only", "L3.4C.case.access"),
};
}
export async function fetchL34CTileSeamStitch({
fetcher = fetch,
signal,
}: { fetcher?: L34ALaboratoryFetch; signal?: AbortSignal } = {}): Promise<L34CResult> {
const response = await fetcher("/api/v1/laboratory/l34c/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) {
throw new L34CContractError(`L3.4C недоступен: HTTP ${response.status}.`);
}
const catalog = object(await response.json(), "L3.4C.catalog");
exact(catalog.schema_version, "missioncore.l34c-tile-seam-stitch-catalog/v1", "L3.4C.catalog.schema");
if (!Array.isArray(catalog.items) || catalog.items.length !== 1) {
throw new L34CContractError("L3.4C.catalog: ожидался один результат.");
}
return parseResult(catalog.items[0]);
}
export async function fetchL34CCase(
resultId: string,
sequence: number,
{ fetcher = fetch, signal }: { fetcher?: L34ALaboratoryFetch; signal?: AbortSignal } = {},
): Promise<L34CCase> {
if (!/^l34c-tile-seam-stitch-shadow-[a-f0-9]{64}$/.test(resultId)
|| !Number.isInteger(sequence) || sequence < 1 || sequence > 32) {
throw new L34CContractError("L3.4C.case: неверная идентичность.");
}
const response = await fetcher(
`/api/v1/laboratory/l34c/results/${resultId}/cases/${sequence}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new L34CContractError(`L3.4C.case недоступен: HTTP ${response.status}.`);
}
return parseCase(await response.json(), resultId, sequence);
}
@@ -0,0 +1,535 @@
import type {
L34AAuditAnnotation,
L34AAuditPrediction,
L34ACaseSummaryMetrics,
L34ALaboratoryFetch,
} from "./l34aAssistedYoloxErrorAudit";
import type { L34BMetricSet } from "./l34bNestedBoxConsolidation";
import type {
L34CBeforePrediction,
L34CRectificationTile,
} from "./l34cTileSeamStitch";
export type L34DOperationType =
| "nested-box-consolidation"
| "temporal-tile-seam-stitch";
export interface L34DCaseSummary {
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
beforeSummary: L34ACaseSummaryMetrics;
afterSummary: L34ACaseSummaryMetrics;
operationCount: number;
operationTypes: readonly L34DOperationType[];
}
export interface L34DResult {
resultId: string;
createdAtUtc: string;
status: "completed-cumulative-postprocessing-candidate-freeze-not-truth";
profile: {
profileId: string;
operationOrder: string;
conflictPolicy: string;
geometryPolicy: string;
scorePolicy: string;
scope: string;
};
pipelineId: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
metrics: {
before: L34BMetricSet;
after: L34BMetricSet;
delta: Readonly<Record<string, number>>;
nestedConsolidationCount: number;
temporalStitchCount: number;
cumulativeOperationCount: number;
affectedCaseCount: number;
operationConflictCount: number;
countEffectsAdditive: boolean;
assistedRegressionFree: boolean;
};
cases: readonly L34DCaseSummary[];
caseOrder: readonly number[];
decision: {
cumulativeShadowAccepted: boolean;
candidateFrozen: boolean;
candidateAccepted: boolean;
predictionProvenancePreserved: boolean;
operationSetsDisjoint: boolean;
globalNmsUnchanged: boolean;
independentTruthAvailable: boolean;
l35BlindGateOpen: boolean;
nextAction: string;
};
limitations: readonly string[];
groundTruth: false;
access: "read-only";
}
export interface L34DAfterPrediction extends L34AAuditPrediction {
sourcePredictionIndices: readonly number[];
sourceRectificationTiles: readonly L34CRectificationTile[];
operationTypes: readonly L34DOperationType[];
}
export interface L34DOperation {
operationType: L34DOperationType;
category: string;
sourcePredictionIndices: readonly number[];
sourceTiles: readonly L34CRectificationTile[];
sourceScores: readonly number[];
sourceBoxesXyxy: readonly (readonly [number, number, number, number])[];
mergedScore: number;
mergedBoxXyxy: readonly [number, number, number, number];
temporalRunId: string | null;
temporalRunLength: number | null;
}
export interface L34DCase {
resultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
cameraWidth: number;
cameraHeight: number;
cameraUrl: string;
beforePredictions: readonly L34CBeforePrediction[];
afterPredictions: readonly L34DAfterPrediction[];
annotations: readonly L34AAuditAnnotation[];
operations: readonly L34DOperation[];
beforeSummary: L34ACaseSummaryMetrics;
afterSummary: L34ACaseSummaryMetrics;
groundTruth: false;
access: "read-only";
}
export class L34DContractError extends Error {
constructor(message: string) {
super(message);
this.name = "L34DContractError";
}
}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new L34DContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function text(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new L34DContractError(`${label}: ожидалась строка.`);
}
return value;
}
function exact<T>(value: unknown, expected: T, label: string): T {
if (value !== expected) {
throw new L34DContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function integer(value: unknown, label: string): number {
if (!Number.isInteger(value) || Number(value) < 0) {
throw new L34DContractError(`${label}: ожидалось целое число.`);
}
return Number(value);
}
function finite(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new L34DContractError(`${label}: ожидалось число.`);
}
return value;
}
function ratio(value: unknown, label: string): number {
const parsed = finite(value, label);
if (parsed < 0 || parsed > 1) {
throw new L34DContractError(`${label}: нарушен диапазон.`);
}
return parsed;
}
function bool(value: unknown, label: string): boolean {
if (typeof value !== "boolean") {
throw new L34DContractError(`${label}: ожидалось логическое значение.`);
}
return value;
}
function box(
value: unknown,
label: string,
): readonly [number, number, number, number] {
if (!Array.isArray(value) || value.length !== 4) {
throw new L34DContractError(`${label}: ожидалась рамка.`);
}
const parsed = value.map((entry) => finite(entry, label));
if (!(0 <= parsed[0] && parsed[0] < parsed[2] && parsed[2] <= 800
&& 0 <= parsed[1] && parsed[1] < parsed[3] && parsed[3] <= 600)) {
throw new L34DContractError(`${label}: нарушена геометрия.`);
}
return parsed as [number, number, number, number];
}
function point(value: unknown, label: string): readonly [number, number] {
if (!Array.isArray(value) || value.length !== 2) {
throw new L34DContractError(`${label}: ожидалась точка.`);
}
return [finite(value[0], label), finite(value[1], label)];
}
function tile(value: unknown, label: string): L34CRectificationTile {
if (value !== "front" && value !== "left" && value !== "right") {
throw new L34DContractError(`${label}: неизвестный rectification tile.`);
}
return value;
}
function operationType(value: unknown, label: string): L34DOperationType {
if (value !== "nested-box-consolidation"
&& value !== "temporal-tile-seam-stitch") {
throw new L34DContractError(`${label}: неизвестная операция.`);
}
return value;
}
function summary(value: unknown, label: string): L34ACaseSummaryMetrics {
const item = object(value, label);
return {
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
severityScore: integer(item.severity_score, `${label}.severity_score`),
};
}
function metrics(value: unknown, label: string): L34BMetricSet {
const item = object(value, label);
return {
frameCount: integer(item.frame_count, `${label}.frame_count`),
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
precisionIou50: ratio(item.precision_iou50, `${label}.precision_iou50`),
recallIou50: ratio(item.recall_iou50, `${label}.recall_iou50`),
f1Iou50: ratio(item.f1_iou50, `${label}.f1_iou50`),
errorCaseCount: integer(item.error_case_count, `${label}.error_case_count`),
customReferenceCount: integer(item.custom_reference_count, `${label}.custom_reference_count`),
};
}
const PREDICTION_VERDICTS = new Set([
"true_positive",
"class_mismatch",
"duplicate_false_positive",
"false_positive",
]);
const ANNOTATION_VERDICTS = new Set([
"true_positive",
"class_mismatch",
"false_negative",
]);
function predictionBase(raw: unknown, label: string): L34AAuditPrediction {
const item = object(raw, label);
const verdict = text(item.verdict, `${label}.verdict`);
if (!PREDICTION_VERDICTS.has(verdict)) {
throw new L34DContractError(`${label}: неизвестный verdict.`);
}
return {
predictionIndex: integer(item.prediction_index, `${label}.index`),
category: text(item.category, `${label}.category`),
score: ratio(item.score, `${label}.score`),
boxXyxy: box(item.box_xyxy, `${label}.box`),
verdict: verdict as L34AAuditPrediction["verdict"],
matchedObjectId: item.matched_object_id === null
? null
: text(item.matched_object_id, `${label}.match`),
matchIou: item.match_iou === null
? null
: ratio(item.match_iou, `${label}.iou`),
};
}
function parseBeforePrediction(raw: unknown, label: string): L34CBeforePrediction {
const item = object(raw, label);
return {
...predictionBase(item, label),
rectificationTile: tile(item.rectification_tile, `${label}.tile`),
rawLabel: text(item.raw_label, `${label}.raw label`),
classId: integer(item.class_id, `${label}.class id`),
rawCenterXy: point(item.raw_center_xy, `${label}.raw center`),
};
}
function parseAfterPrediction(raw: unknown, label: string): L34DAfterPrediction {
const item = object(raw, label);
return {
...predictionBase(item, label),
sourcePredictionIndices: Array.isArray(item.source_prediction_indices)
? item.source_prediction_indices.map((entry) => integer(entry, `${label}.source`))
: [],
sourceRectificationTiles: Array.isArray(item.source_rectification_tiles)
? item.source_rectification_tiles.map((entry) => tile(entry, `${label}.tile`))
: [],
operationTypes: Array.isArray(item.operation_types)
? item.operation_types.map((entry) => operationType(entry, `${label}.operation`))
: [],
};
}
function parseAnnotation(raw: unknown, label: string): L34AAuditAnnotation {
const item = object(raw, label);
const verdict = text(item.verdict, `${label}.verdict`);
if (!ANNOTATION_VERDICTS.has(verdict)) {
throw new L34DContractError(`${label}: неизвестный verdict.`);
}
return {
objectId: text(item.object_id, `${label}.id`),
category: text(item.category, `${label}.category`),
proposedLabel: item.proposed_label === null
? null
: text(item.proposed_label, `${label}.proposed`),
displayCategory: text(item.display_category, `${label}.display`),
origin: item.origin === "manual" ? "manual" : "frozen_candidate_seed",
boxXyxy: box(item.box_xyxy, `${label}.box`),
occluded: bool(item.occluded, `${label}.occluded`),
truncated: bool(item.truncated, `${label}.truncated`),
verdict: verdict as L34AAuditAnnotation["verdict"],
matchedPredictionIndex: item.matched_prediction_index === null
? null
: integer(item.matched_prediction_index, `${label}.match`),
matchIou: item.match_iou === null
? null
: ratio(item.match_iou, `${label}.iou`),
};
}
function parseOperation(raw: unknown): L34DOperation {
const item = object(raw, "L3.4D.operation");
const type = operationType(item.operation_type, "L3.4D.operation.type");
return {
operationType: type,
category: text(item.category, "L3.4D.operation.category"),
sourcePredictionIndices: Array.isArray(item.source_prediction_indices)
? item.source_prediction_indices.map((entry) => integer(entry, "L3.4D.operation.source"))
: [],
sourceTiles: Array.isArray(item.source_tiles)
? item.source_tiles.map((entry) => tile(entry, "L3.4D.operation.tile"))
: [],
sourceScores: Array.isArray(item.source_scores)
? item.source_scores.map((entry) => ratio(entry, "L3.4D.operation.score"))
: [],
sourceBoxesXyxy: Array.isArray(item.source_boxes_xyxy)
? item.source_boxes_xyxy.map((entry) => box(entry, "L3.4D.operation.box"))
: [],
mergedScore: ratio(item.merged_score, "L3.4D.operation.merged score"),
mergedBoxXyxy: box(item.merged_box_xyxy, "L3.4D.operation.merged box"),
temporalRunId: type === "temporal-tile-seam-stitch"
? text(item.temporal_run_id, "L3.4D.operation.run")
: null,
temporalRunLength: type === "temporal-tile-seam-stitch"
? integer(item.temporal_run_length, "L3.4D.operation.run length")
: null,
};
}
function parseResult(value: unknown): L34DResult {
const item = object(value, "L3.4D");
const resultId = text(item.result_id, "L3.4D.result_id");
if (!/^l34d-cumulative-postprocessing-candidate-[a-f0-9]{64}$/.test(resultId)) {
throw new L34DContractError("L3.4D.result_id: нарушена идентичность.");
}
const profile = object(item.profile, "L3.4D.profile");
const rawMetrics = object(item.metrics, "L3.4D.metrics");
const rawDecision = object(item.decision, "L3.4D.decision");
const cases = Array.isArray(item.cases)
? item.cases.map((raw): L34DCaseSummary => {
const current = object(raw, "L3.4D.case summary");
return {
truthIslandSequence: integer(current.truth_island_sequence, "L3.4D.case.sequence"),
imageId: integer(current.image_id, "L3.4D.case.image"),
frameIndex: integer(current.frame_index, "L3.4D.case.frame"),
groupId: text(current.group_id, "L3.4D.case.group"),
sessionSeconds: finite(current.session_seconds, "L3.4D.case.time"),
sourceImageSha256: text(current.source_image_sha256, "L3.4D.case.source"),
beforeSummary: summary(current.before_summary, "L3.4D.case.before"),
afterSummary: summary(current.after_summary, "L3.4D.case.after"),
operationCount: integer(current.operation_count, "L3.4D.case.operations"),
operationTypes: Array.isArray(current.operation_types)
? current.operation_types.map((entry) => operationType(entry, "L3.4D.case.operation"))
: [],
};
})
: [];
if (cases.length !== 32 || !Array.isArray(item.case_order)
|| item.case_order.length !== 32) {
throw new L34DContractError("L3.4D: требуется 32 кадра.");
}
const delta = object(rawMetrics.delta, "L3.4D.metrics.delta");
return {
resultId,
createdAtUtc: text(item.created_at_utc, "L3.4D.created_at"),
status: exact(
item.status,
"completed-cumulative-postprocessing-candidate-freeze-not-truth",
"L3.4D.status",
),
profile: {
profileId: text(profile.profile_id, "L3.4D.profile.id"),
operationOrder: text(profile.operation_order, "L3.4D.profile.order"),
conflictPolicy: text(profile.conflict_policy, "L3.4D.profile.conflict"),
geometryPolicy: text(profile.geometry_policy, "L3.4D.profile.geometry"),
scorePolicy: text(profile.score_policy, "L3.4D.profile.score"),
scope: text(profile.scope, "L3.4D.profile.scope"),
},
pipelineId: text(item.pipeline_id, "L3.4D.pipeline"),
sourceSessionId: text(item.source_session_id, "L3.4D.session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "L3.4D.camera"),
metrics: {
before: metrics(rawMetrics.before, "L3.4D.before"),
after: metrics(rawMetrics.after, "L3.4D.after"),
delta: Object.fromEntries(
Object.entries(delta).map(([key, raw]) => [key, finite(raw, `L3.4D.delta.${key}`)]),
),
nestedConsolidationCount: integer(rawMetrics.nested_consolidation_count, "L3.4D.nested"),
temporalStitchCount: integer(rawMetrics.temporal_stitch_count, "L3.4D.stitches"),
cumulativeOperationCount: integer(rawMetrics.cumulative_operation_count, "L3.4D.operations"),
affectedCaseCount: integer(rawMetrics.affected_case_count, "L3.4D.affected"),
operationConflictCount: integer(rawMetrics.operation_conflict_count, "L3.4D.conflicts"),
countEffectsAdditive: bool(rawMetrics.count_effects_additive, "L3.4D.additive"),
assistedRegressionFree: bool(rawMetrics.assisted_regression_free, "L3.4D.regression"),
},
cases,
caseOrder: item.case_order.map((entry) => integer(entry, "L3.4D.case_order")),
decision: {
cumulativeShadowAccepted: bool(rawDecision.cumulative_shadow_accepted, "L3.4D.shadow"),
candidateFrozen: bool(rawDecision.candidate_frozen, "L3.4D.frozen"),
candidateAccepted: bool(rawDecision.candidate_accepted, "L3.4D.accepted"),
predictionProvenancePreserved: bool(rawDecision.prediction_provenance_preserved, "L3.4D.provenance"),
operationSetsDisjoint: bool(rawDecision.operation_sets_disjoint, "L3.4D.disjoint"),
globalNmsUnchanged: bool(rawDecision.global_nms_unchanged, "L3.4D.NMS"),
independentTruthAvailable: bool(rawDecision.independent_truth_available, "L3.4D.truth available"),
l35BlindGateOpen: bool(rawDecision.l35_blind_gate_open, "L3.4D.gate"),
nextAction: text(rawDecision.next_action, "L3.4D.next action"),
},
limitations: Array.isArray(item.limitations)
? item.limitations.map((entry) => text(entry, "L3.4D.limitation"))
: [],
groundTruth: exact(item.ground_truth, false, "L3.4D.truth"),
access: exact(item.access, "read-only", "L3.4D.access"),
};
}
function parseCase(value: unknown, resultId: string, sequence: number): L34DCase {
const item = object(value, "L3.4D.case");
exact(item.schema_version, "missioncore.l34d-cumulative-postprocessing-case/v1", "L3.4D.case.schema");
exact(item.result_id, resultId, "L3.4D.case.result");
exact(item.truth_island_sequence, sequence, "L3.4D.case.sequence");
const camera = object(item.camera, "L3.4D.case.camera");
return {
resultId,
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4D.case.image"),
frameIndex: integer(item.frame_index, "L3.4D.case.frame"),
groupId: text(item.group_id, "L3.4D.case.group"),
sessionSeconds: finite(item.session_seconds, "L3.4D.case.time"),
sourceImageSha256: text(item.source_image_sha256, "L3.4D.case.source"),
cameraWidth: integer(camera.width, "L3.4D.case.width"),
cameraHeight: integer(camera.height, "L3.4D.case.height"),
cameraUrl: `/api/v1/laboratory/l34d/results/${resultId}/cases/${sequence}/camera`,
beforePredictions: Array.isArray(item.before_predictions)
? item.before_predictions.map((raw, index) => parseBeforePrediction(raw, `L3.4D.before.${index}`))
: [],
afterPredictions: Array.isArray(item.after_predictions)
? item.after_predictions.map((raw, index) => parseAfterPrediction(raw, `L3.4D.after.${index}`))
: [],
annotations: Array.isArray(item.annotations)
? item.annotations.map((raw, index) => parseAnnotation(raw, `L3.4D.annotation.${index}`))
: [],
operations: Array.isArray(item.operations)
? item.operations.map(parseOperation)
: [],
beforeSummary: summary(item.before_summary, "L3.4D.case.before summary"),
afterSummary: summary(item.after_summary, "L3.4D.case.after summary"),
groundTruth: exact(item.ground_truth, false, "L3.4D.case.truth"),
access: exact(item.access, "read-only", "L3.4D.case.access"),
};
}
export async function fetchL34DCumulativePostprocessing({
fetcher = fetch,
signal,
}: {
fetcher?: L34ALaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<L34DResult> {
const response = await fetcher("/api/v1/laboratory/l34d/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) {
throw new L34DContractError(`L3.4D недоступен: HTTP ${response.status}.`);
}
const catalog = object(await response.json(), "L3.4D.catalog");
exact(
catalog.schema_version,
"missioncore.l34d-cumulative-postprocessing-catalog/v1",
"L3.4D.catalog.schema",
);
if (!Array.isArray(catalog.items) || catalog.items.length !== 1) {
throw new L34DContractError("L3.4D.catalog: ожидался один результат.");
}
return parseResult(catalog.items[0]);
}
export async function fetchL34DCase(
resultId: string,
sequence: number,
{
fetcher = fetch,
signal,
}: {
fetcher?: L34ALaboratoryFetch;
signal?: AbortSignal;
} = {},
): Promise<L34DCase> {
if (!/^l34d-cumulative-postprocessing-candidate-[a-f0-9]{64}$/.test(resultId)
|| !Number.isInteger(sequence) || sequence < 1 || sequence > 32) {
throw new L34DContractError("L3.4D.case: неверная идентичность.");
}
const response = await fetcher(
`/api/v1/laboratory/l34d/results/${resultId}/cases/${sequence}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new L34DContractError(`L3.4D.case недоступен: HTTP ${response.status}.`);
}
return parseCase(await response.json(), resultId, sequence);
}
@@ -0,0 +1,554 @@
import type { L34ALaboratoryFetch } from "./l34aAssistedYoloxErrorAudit";
export type L34EDiagnosticVerdict =
| "strict_alignment"
| "strict_class_mismatch"
| "localization_disagreement"
| "class_and_localization_disagreement"
| "prediction_only"
| "reference_only";
export interface L34EStrictCaseSummary {
predictionCount: number;
referenceCount: number;
truePositive: number;
falsePositive: number;
falseNegative: number;
classMismatch: number;
duplicateFalsePositive: number;
unmatchedFalsePositive: number;
unmatchedFalseNegative: number;
severityScore: number;
}
export interface L34EDiagnosticSummary {
predictionCount: number;
referenceCount: number;
associatedPairCount: number;
strictAlignment: number;
strictClassMismatch: number;
localizationDisagreement: number;
classAndLocalizationDisagreement: number;
predictionOnly: number;
referenceOnly: number;
candidateAssociationCoverage: number;
referenceAssociationCoverage: number;
severityScore: number;
}
export interface L34ECaseSummary {
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
strictSummary: L34EStrictCaseSummary;
diagnosticSummary: L34EDiagnosticSummary;
}
export interface L34EPrediction {
predictionIndex: number;
category: string;
score: number;
boxXyxy: readonly [number, number, number, number];
strictVerdict: string;
diagnosticVerdict: L34EDiagnosticVerdict;
associatedObjectId: string | null;
associationIou: number | null;
associationOverlapOverSmaller: number | null;
sourcePredictionIndices: readonly number[];
sourceRectificationTiles: readonly string[];
operationTypes: readonly string[];
}
export interface L34EReference {
objectId: string;
category: string;
displayCategory: string;
proposedLabel: string | null;
boxXyxy: readonly [number, number, number, number];
occluded: boolean;
truncated: boolean;
strictVerdict: string;
diagnosticVerdict: L34EDiagnosticVerdict;
associatedPredictionIndex: number | null;
associationIou: number | null;
associationOverlapOverSmaller: number | null;
}
export interface L34EAssociation {
predictionIndex: number;
objectId: string;
predictionCategory: string;
referenceCategory: string;
iou: number;
overlapOverSmaller: number;
classification: Exclude<
L34EDiagnosticVerdict,
"prediction_only" | "reference_only"
>;
}
export interface L34ECase {
resultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
cameraWidth: number;
cameraHeight: number;
cameraUrl: string;
predictions: readonly L34EPrediction[];
references: readonly L34EReference[];
associations: readonly L34EAssociation[];
strictSummary: L34EStrictCaseSummary;
diagnosticSummary: L34EDiagnosticSummary;
groundTruth: false;
access: "read-only";
}
export interface L34EResult {
resultId: string;
createdAtUtc: string;
status: "completed-self-review-diagnostic-not-truth";
profile: {
profileId: string;
strictMatcher: string;
diagnosticMatcher: string;
classPolicy: string;
referencePolicy: string;
scope: string;
};
pipelineId: string;
sourceSessionId: string;
cameraSourceId: "sensor.camera.right";
metrics: {
strictIou50: {
frameCount: number;
predictionCount: number;
referenceCount: number;
truePositive: number;
falsePositive: number;
falseNegative: number;
classMismatch: number;
duplicateFalsePositive: number;
unmatchedFalsePositive: number;
unmatchedFalseNegative: number;
precisionIou50: number;
recallIou50: number;
f1Iou50: number;
errorCaseCount: number;
customReferenceCount: number;
};
diagnosticAssociation: Omit<L34EDiagnosticSummary, "severityScore"> & {
errorCaseCount: number;
};
frameCountDisagreement: {
candidateSurplusLowerBound: number;
referenceSurplusLowerBound: number;
equalCountFrameCount: number;
};
referenceQuality: "not-metric-grade-self-review";
};
cases: readonly L34ECaseSummary[];
caseOrder: readonly number[];
decision: {
selfReviewComplete: boolean;
diagnosticAlignmentAvailable: boolean;
metricGradeReferenceAvailable: boolean;
independentTruthAvailable: boolean;
detectorRetuningAuthorized: boolean;
candidateAccepted: boolean;
l35BlindGateOpen: boolean;
nextAction: string;
};
limitations: readonly string[];
groundTruth: false;
access: "read-only";
}
export class L34EContractError extends Error {
constructor(message: string) {
super(message);
this.name = "L34EContractError";
}
}
function object(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new L34EContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function text(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new L34EContractError(`${label}: ожидалась строка.`);
}
return value;
}
function exact<T>(value: unknown, expected: T, label: string): T {
if (value !== expected) {
throw new L34EContractError(`${label}: нарушен контракт.`);
}
return expected;
}
function finite(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new L34EContractError(`${label}: ожидалось число.`);
}
return value;
}
function integer(value: unknown, label: string): number {
const parsed = finite(value, label);
if (!Number.isInteger(parsed) || parsed < 0) {
throw new L34EContractError(`${label}: ожидалось целое число.`);
}
return parsed;
}
function ratio(value: unknown, label: string): number {
const parsed = finite(value, label);
if (parsed < 0 || parsed > 1) {
throw new L34EContractError(`${label}: нарушен диапазон.`);
}
return parsed;
}
function bool(value: unknown, label: string): boolean {
if (typeof value !== "boolean") {
throw new L34EContractError(`${label}: ожидалось логическое значение.`);
}
return value;
}
function box(
value: unknown,
label: string,
): readonly [number, number, number, number] {
if (!Array.isArray(value) || value.length !== 4) {
throw new L34EContractError(`${label}: ожидалась рамка.`);
}
const parsed = value.map((entry) => finite(entry, label));
if (!(0 <= parsed[0] && parsed[0] < parsed[2] && parsed[2] <= 800
&& 0 <= parsed[1] && parsed[1] < parsed[3] && parsed[3] <= 600)) {
throw new L34EContractError(`${label}: нарушена геометрия.`);
}
return parsed as [number, number, number, number];
}
const DIAGNOSTIC_VERDICTS = new Set<L34EDiagnosticVerdict>([
"strict_alignment",
"strict_class_mismatch",
"localization_disagreement",
"class_and_localization_disagreement",
"prediction_only",
"reference_only",
]);
function diagnosticVerdict(value: unknown, label: string): L34EDiagnosticVerdict {
const parsed = text(value, label) as L34EDiagnosticVerdict;
if (!DIAGNOSTIC_VERDICTS.has(parsed)) {
throw new L34EContractError(`${label}: неизвестный verdict.`);
}
return parsed;
}
function nullableText(value: unknown, label: string): string | null {
return value === null ? null : text(value, label);
}
function nullableRatio(value: unknown, label: string): number | null {
return value === null ? null : ratio(value, label);
}
function strictSummary(value: unknown, label: string): L34EStrictCaseSummary {
const item = object(value, label);
return {
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
truePositive: integer(item.true_positive, `${label}.true_positive`),
falsePositive: integer(item.false_positive, `${label}.false_positive`),
falseNegative: integer(item.false_negative, `${label}.false_negative`),
classMismatch: integer(item.class_mismatch, `${label}.class_mismatch`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate_false_positive`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_false_positive`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_false_negative`),
severityScore: integer(item.severity_score, `${label}.severity_score`),
};
}
function diagnosticSummary(value: unknown, label: string): L34EDiagnosticSummary {
const item = object(value, label);
return {
predictionCount: integer(item.prediction_count, `${label}.prediction_count`),
referenceCount: integer(item.reference_count, `${label}.reference_count`),
associatedPairCount: integer(item.associated_pair_count, `${label}.pairs`),
strictAlignment: integer(item.strict_alignment, `${label}.aligned`),
strictClassMismatch: integer(item.strict_class_mismatch, `${label}.class`),
localizationDisagreement: integer(item.localization_disagreement, `${label}.localization`),
classAndLocalizationDisagreement: integer(item.class_and_localization_disagreement, `${label}.class_localization`),
predictionOnly: integer(item.prediction_only, `${label}.prediction_only`),
referenceOnly: integer(item.reference_only, `${label}.reference_only`),
candidateAssociationCoverage: ratio(item.candidate_association_coverage, `${label}.candidate_coverage`),
referenceAssociationCoverage: ratio(item.reference_association_coverage, `${label}.reference_coverage`),
severityScore: integer(item.severity_score, `${label}.severity`),
};
}
function aggregateStrict(value: unknown, label: string) {
const item = object(value, label);
return {
frameCount: integer(item.frame_count, `${label}.frames`),
predictionCount: integer(item.prediction_count, `${label}.predictions`),
referenceCount: integer(item.reference_count, `${label}.references`),
truePositive: integer(item.true_positive, `${label}.tp`),
falsePositive: integer(item.false_positive, `${label}.fp`),
falseNegative: integer(item.false_negative, `${label}.fn`),
classMismatch: integer(item.class_mismatch, `${label}.class`),
duplicateFalsePositive: integer(item.duplicate_false_positive, `${label}.duplicate`),
unmatchedFalsePositive: integer(item.unmatched_false_positive, `${label}.unmatched_fp`),
unmatchedFalseNegative: integer(item.unmatched_false_negative, `${label}.unmatched_fn`),
precisionIou50: ratio(item.precision_iou50, `${label}.precision`),
recallIou50: ratio(item.recall_iou50, `${label}.recall`),
f1Iou50: ratio(item.f1_iou50, `${label}.f1`),
errorCaseCount: integer(item.error_case_count, `${label}.error_cases`),
customReferenceCount: integer(item.custom_reference_count, `${label}.custom`),
};
}
function parseResult(value: unknown): L34EResult {
const item = object(value, "L3.4E");
const resultId = text(item.result_id, "L3.4E.result_id");
if (!/^l34e-self-review-diagnostic-[a-f0-9]{64}$/.test(resultId)) {
throw new L34EContractError("L3.4E.result_id: нарушена идентичность.");
}
const profile = object(item.profile, "L3.4E.profile");
const metrics = object(item.metrics, "L3.4E.metrics");
const diagnostic = object(metrics.diagnostic_association, "L3.4E.diagnostic");
const counts = object(metrics.frame_count_disagreement, "L3.4E.counts");
const decision = object(item.decision, "L3.4E.decision");
const cases = Array.isArray(item.cases)
? item.cases.map((raw): L34ECaseSummary => {
const current = object(raw, "L3.4E.case summary");
return {
truthIslandSequence: integer(current.truth_island_sequence, "L3.4E.case.sequence"),
imageId: integer(current.image_id, "L3.4E.case.image"),
frameIndex: integer(current.frame_index, "L3.4E.case.frame"),
groupId: text(current.group_id, "L3.4E.case.group"),
sessionSeconds: finite(current.session_seconds, "L3.4E.case.time"),
sourceImageSha256: text(current.source_image_sha256, "L3.4E.case.source"),
strictSummary: strictSummary(current.strict_summary, "L3.4E.case.strict"),
diagnosticSummary: diagnosticSummary(current.diagnostic_summary, "L3.4E.case.diagnostic"),
};
})
: [];
if (cases.length !== 32 || !Array.isArray(item.case_order)
|| item.case_order.length !== 32) {
throw new L34EContractError("L3.4E: требуется 32 кадра.");
}
return {
resultId,
createdAtUtc: text(item.created_at_utc, "L3.4E.created_at"),
status: exact(item.status, "completed-self-review-diagnostic-not-truth", "L3.4E.status"),
profile: {
profileId: text(profile.profile_id, "L3.4E.profile.id"),
strictMatcher: text(profile.strict_matcher, "L3.4E.profile.strict"),
diagnosticMatcher: text(profile.diagnostic_matcher, "L3.4E.profile.diagnostic"),
classPolicy: text(profile.class_policy, "L3.4E.profile.class"),
referencePolicy: text(profile.reference_policy, "L3.4E.profile.reference"),
scope: text(profile.scope, "L3.4E.profile.scope"),
},
pipelineId: text(item.pipeline_id, "L3.4E.pipeline"),
sourceSessionId: text(item.source_session_id, "L3.4E.session"),
cameraSourceId: exact(item.camera_source_id, "sensor.camera.right", "L3.4E.camera"),
metrics: {
strictIou50: aggregateStrict(metrics.strict_iou50, "L3.4E.strict"),
diagnosticAssociation: {
predictionCount: integer(diagnostic.prediction_count, "L3.4E.diagnostic.predictions"),
referenceCount: integer(diagnostic.reference_count, "L3.4E.diagnostic.references"),
associatedPairCount: integer(diagnostic.associated_pair_count, "L3.4E.diagnostic.pairs"),
strictAlignment: integer(diagnostic.strict_alignment, "L3.4E.diagnostic.aligned"),
strictClassMismatch: integer(diagnostic.strict_class_mismatch, "L3.4E.diagnostic.class"),
localizationDisagreement: integer(diagnostic.localization_disagreement, "L3.4E.diagnostic.localization"),
classAndLocalizationDisagreement: integer(diagnostic.class_and_localization_disagreement, "L3.4E.diagnostic.class_localization"),
predictionOnly: integer(diagnostic.prediction_only, "L3.4E.diagnostic.prediction_only"),
referenceOnly: integer(diagnostic.reference_only, "L3.4E.diagnostic.reference_only"),
candidateAssociationCoverage: ratio(diagnostic.candidate_association_coverage, "L3.4E.diagnostic.candidate_coverage"),
referenceAssociationCoverage: ratio(diagnostic.reference_association_coverage, "L3.4E.diagnostic.reference_coverage"),
errorCaseCount: integer(diagnostic.error_case_count, "L3.4E.diagnostic.error_cases"),
},
frameCountDisagreement: {
candidateSurplusLowerBound: integer(counts.candidate_surplus_lower_bound, "L3.4E.counts.candidate"),
referenceSurplusLowerBound: integer(counts.reference_surplus_lower_bound, "L3.4E.counts.reference"),
equalCountFrameCount: integer(counts.equal_count_frame_count, "L3.4E.counts.equal"),
},
referenceQuality: exact(metrics.reference_quality, "not-metric-grade-self-review", "L3.4E.reference quality"),
},
cases,
caseOrder: item.case_order.map((entry) => integer(entry, "L3.4E.case_order")),
decision: {
selfReviewComplete: bool(decision.self_review_complete, "L3.4E.decision.review"),
diagnosticAlignmentAvailable: bool(decision.diagnostic_alignment_available, "L3.4E.decision.alignment"),
metricGradeReferenceAvailable: bool(decision.metric_grade_reference_available, "L3.4E.decision.metric"),
independentTruthAvailable: bool(decision.independent_truth_available, "L3.4E.decision.truth"),
detectorRetuningAuthorized: bool(decision.detector_retuning_authorized, "L3.4E.decision.retuning"),
candidateAccepted: bool(decision.candidate_accepted, "L3.4E.decision.accepted"),
l35BlindGateOpen: bool(decision.l35_blind_gate_open, "L3.4E.decision.gate"),
nextAction: text(decision.next_action, "L3.4E.decision.next"),
},
limitations: Array.isArray(item.limitations)
? item.limitations.map((entry) => text(entry, "L3.4E.limitation"))
: [],
groundTruth: exact(item.ground_truth, false, "L3.4E.truth"),
access: exact(item.access, "read-only", "L3.4E.access"),
};
}
function parsePrediction(raw: unknown, label: string): L34EPrediction {
const item = object(raw, label);
return {
predictionIndex: integer(item.prediction_index, `${label}.index`),
category: text(item.category, `${label}.category`),
score: ratio(item.score, `${label}.score`),
boxXyxy: box(item.box_xyxy, `${label}.box`),
strictVerdict: text(item.verdict, `${label}.strict`),
diagnosticVerdict: diagnosticVerdict(item.diagnostic_verdict, `${label}.diagnostic`),
associatedObjectId: nullableText(item.associated_object_id, `${label}.object`),
associationIou: nullableRatio(item.association_iou, `${label}.iou`),
associationOverlapOverSmaller: nullableRatio(item.association_overlap_over_smaller, `${label}.overlap`),
sourcePredictionIndices: Array.isArray(item.source_prediction_indices)
? item.source_prediction_indices.map((entry) => integer(entry, `${label}.source`))
: [],
sourceRectificationTiles: Array.isArray(item.source_rectification_tiles)
? item.source_rectification_tiles.map((entry) => text(entry, `${label}.tile`))
: [],
operationTypes: Array.isArray(item.operation_types)
? item.operation_types.map((entry) => text(entry, `${label}.operation`))
: [],
};
}
function parseReference(raw: unknown, label: string): L34EReference {
const item = object(raw, label);
return {
objectId: text(item.object_id, `${label}.id`),
category: text(item.category, `${label}.category`),
displayCategory: text(item.display_category, `${label}.display`),
proposedLabel: nullableText(item.proposed_label, `${label}.proposed`),
boxXyxy: box(item.box_xyxy, `${label}.box`),
occluded: bool(item.occluded, `${label}.occluded`),
truncated: bool(item.truncated, `${label}.truncated`),
strictVerdict: text(item.verdict, `${label}.strict`),
diagnosticVerdict: diagnosticVerdict(item.diagnostic_verdict, `${label}.diagnostic`),
associatedPredictionIndex: item.associated_prediction_index === null
? null
: integer(item.associated_prediction_index, `${label}.prediction`),
associationIou: nullableRatio(item.association_iou, `${label}.iou`),
associationOverlapOverSmaller: nullableRatio(item.association_overlap_over_smaller, `${label}.overlap`),
};
}
function parseAssociation(raw: unknown, label: string): L34EAssociation {
const item = object(raw, label);
const classification = diagnosticVerdict(item.classification, `${label}.class`);
if (classification === "prediction_only" || classification === "reference_only") {
throw new L34EContractError(`${label}: ожидалась парная ассоциация.`);
}
return {
predictionIndex: integer(item.prediction_index, `${label}.prediction`),
objectId: text(item.object_id, `${label}.object`),
predictionCategory: text(item.prediction_category, `${label}.prediction_category`),
referenceCategory: text(item.reference_category, `${label}.reference_category`),
iou: ratio(item.iou, `${label}.iou`),
overlapOverSmaller: ratio(item.overlap_over_smaller, `${label}.overlap`),
classification,
};
}
function parseCase(value: unknown, resultId: string, sequence: number): L34ECase {
const item = object(value, "L3.4E.case");
exact(item.schema_version, "missioncore.l34e-self-review-diagnostic-case/v1", "L3.4E.case.schema");
exact(item.result_id, resultId, "L3.4E.case.result");
exact(item.truth_island_sequence, sequence, "L3.4E.case.sequence");
const camera = object(item.camera, "L3.4E.case.camera");
return {
resultId,
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4E.case.image"),
frameIndex: integer(item.frame_index, "L3.4E.case.frame"),
groupId: text(item.group_id, "L3.4E.case.group"),
sessionSeconds: finite(item.session_seconds, "L3.4E.case.time"),
sourceImageSha256: text(item.source_image_sha256, "L3.4E.case.source"),
cameraWidth: integer(camera.width, "L3.4E.case.width"),
cameraHeight: integer(camera.height, "L3.4E.case.height"),
cameraUrl: `/api/v1/laboratory/l34e/results/${resultId}/cases/${sequence}/camera`,
predictions: Array.isArray(item.predictions)
? item.predictions.map((raw, index) => parsePrediction(raw, `L3.4E.prediction.${index}`))
: [],
references: Array.isArray(item.references)
? item.references.map((raw, index) => parseReference(raw, `L3.4E.reference.${index}`))
: [],
associations: Array.isArray(item.associations)
? item.associations.map((raw, index) => parseAssociation(raw, `L3.4E.association.${index}`))
: [],
strictSummary: strictSummary(item.strict_summary, "L3.4E.case.strict"),
diagnosticSummary: diagnosticSummary(item.diagnostic_summary, "L3.4E.case.diagnostic"),
groundTruth: exact(item.ground_truth, false, "L3.4E.case.truth"),
access: exact(item.access, "read-only", "L3.4E.case.access"),
};
}
export async function fetchL34ESelfReviewDiagnostic({
fetcher = fetch,
signal,
}: {
fetcher?: L34ALaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<L34EResult> {
const response = await fetcher("/api/v1/laboratory/l34e/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
if (!response.ok) {
throw new L34EContractError(`L3.4E недоступен: HTTP ${response.status}.`);
}
const catalog = object(await response.json(), "L3.4E.catalog");
exact(catalog.schema_version, "missioncore.l34e-self-review-diagnostic-catalog/v1", "L3.4E.catalog.schema");
if (!Array.isArray(catalog.items) || catalog.items.length !== 1) {
throw new L34EContractError("L3.4E.catalog: ожидался один результат.");
}
return parseResult(catalog.items[0]);
}
export async function fetchL34ECase(
resultId: string,
sequence: number,
{
fetcher = fetch,
signal,
}: {
fetcher?: L34ALaboratoryFetch;
signal?: AbortSignal;
} = {},
): Promise<L34ECase> {
if (!/^l34e-self-review-diagnostic-[a-f0-9]{64}$/.test(resultId)
|| !Number.isInteger(sequence) || sequence < 1 || sequence > 32) {
throw new L34EContractError("L3.4E.case: неверная идентичность.");
}
const response = await fetcher(
`/api/v1/laboratory/l34e/results/${resultId}/cases/${sequence}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new L34EContractError(`L3.4E.case недоступен: HTTP ${response.status}.`);
}
return parseCase(await response.json(), resultId, sequence);
}
@@ -0,0 +1,495 @@
import {
annotationOperationKey,
type L34AnnotationCategory,
} from "./l34Annotation";
import type { L34EDiagnosticVerdict } from "./l34eSelfReviewDiagnostic";
export interface L34FCandidateObject {
candidateId: string;
predictionIndex: number;
category: string;
boxXyxy: readonly [number, number, number, number];
diagnosticVerdict: L34EDiagnosticVerdict;
associatedObjectId: string | null;
}
export interface L34FCase {
diagnosticResultId: string;
truthIslandSequence: number;
imageId: number;
frameIndex: number;
groupId: string;
sessionSeconds: number;
sourceImageSha256: string;
cameraWidth: number;
cameraHeight: number;
cameraUrl: string;
candidateObjects: readonly L34FCandidateObject[];
severityScore: number;
modelScoresIncluded: false;
groundTruth: false;
}
export interface L34FObject {
objectId: string;
category: L34AnnotationCategory;
proposedLabel: string | null;
origin: "self_review_seed" | "adjudicated_manual";
boxXyxy: readonly [number, number, number, number];
occluded: boolean;
truncated: boolean;
}
export interface L34FFrame {
truthIslandSequence: number;
imageId: number;
frameIndex: number;
sourceSha256: string;
reviewed: boolean;
objects: readonly L34FObject[];
}
export interface L34FProgress {
reviewedFrameCount: number;
frameCount: 32;
objectCount: number;
complete: boolean;
}
export interface L34FSessionSummary {
sessionId: string;
diagnosticResultId: string;
title: string;
reviewerSlot: number;
revision: number;
state: "draft" | "saved";
createdAtUtc: string;
updatedAtUtc: string;
progress: L34FProgress;
}
export interface L34FSession extends L34FSessionSummary {
frames: readonly L34FFrame[];
}
export interface L34FFrozenResult {
resultId: string;
createdAtUtc: string;
sourceSessionId: "RAVNOVES00";
diagnosticResultId: string;
adjudicationSessionId: string;
status: "completed-candidate-visible-adjudication-not-truth";
metrics: {
frameCount: number;
sourceReferenceCount: number;
adjudicatedReferenceCount: number;
unchangedObjectCount: number;
geometryChangedObjectCount: number;
classChangedObjectCount: number;
attributeChangedObjectCount: number;
addedObjectCount: number;
deletedObjectCount: number;
changedFrameCount: number;
};
decision: {
adjudicationComplete: boolean;
engineeringReferenceAvailable: boolean;
metricGradeReferenceAvailable: boolean;
independentTruthAvailable: boolean;
candidateAccepted: boolean;
detectorRetuningAuthorized: boolean;
l35BlindGateOpen: boolean;
nextAction: string;
};
limitations: readonly string[];
groundTruth: false;
}
type LaboratoryFetch = (
input: RequestInfo | URL,
init?: RequestInit,
) => Promise<Response>;
export class L34FContractError extends Error {}
function record(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new L34FContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function list(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) throw new L34FContractError(`${label}: ожидался массив.`);
return value;
}
function text(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new L34FContractError(`${label}: ожидалась строка.`);
}
return value;
}
function integer(value: unknown, label: string): number {
if (!Number.isInteger(value) || Number(value) < 0) {
throw new L34FContractError(`${label}: ожидалось целое число.`);
}
return Number(value);
}
function finite(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new L34FContractError(`${label}: ожидалось число.`);
}
return value;
}
function boolean(value: unknown, label: string): boolean {
if (typeof value !== "boolean") throw new L34FContractError(`${label}: ожидался boolean.`);
return value;
}
function exact<T>(value: unknown, expected: T, label: string): T {
if (value !== expected) throw new L34FContractError(`${label}: нарушен контракт.`);
return expected;
}
function box(value: unknown, label: string): readonly [number, number, number, number] {
if (!Array.isArray(value) || value.length !== 4) {
throw new L34FContractError(`${label}: ожидалась рамка.`);
}
const parsed = value.map((entry) => finite(entry, label));
if (!(0 <= parsed[0] && parsed[0] < parsed[2] && parsed[2] <= 800
&& 0 <= parsed[1] && parsed[1] < parsed[3] && parsed[3] <= 600)) {
throw new L34FContractError(`${label}: нарушена геометрия.`);
}
return parsed as [number, number, number, number];
}
function category(value: unknown, label: string): L34AnnotationCategory {
if (![
"person", "bicycle", "motorcycle", "car", "heavy_vehicle",
"static_obstacle", "animal", "unmapped",
].includes(String(value))) {
throw new L34FContractError(`${label}: неизвестный класс.`);
}
return value as L34AnnotationCategory;
}
function verdict(value: unknown, label: string): L34EDiagnosticVerdict {
if (![
"strict_alignment", "strict_class_mismatch", "localization_disagreement",
"class_and_localization_disagreement", "prediction_only", "reference_only",
].includes(String(value))) {
throw new L34FContractError(`${label}: неизвестный verdict.`);
}
return value as L34EDiagnosticVerdict;
}
function parseObject(value: unknown, label: string): L34FObject {
const item = record(value, label);
const parsedCategory = category(item.category, `${label}.category`);
const proposedLabel = item.proposed_label;
if (parsedCategory === "unmapped") text(proposedLabel, `${label}.proposed_label`);
if (parsedCategory !== "unmapped" && proposedLabel !== null) {
throw new L34FContractError(`${label}: unexpected proposed label.`);
}
const origin = item.origin;
if (origin !== "self_review_seed" && origin !== "adjudicated_manual") {
throw new L34FContractError(`${label}: неизвестное происхождение.`);
}
return {
objectId: text(item.object_id, `${label}.id`),
category: parsedCategory,
proposedLabel: proposedLabel === null ? null : text(proposedLabel, `${label}.label`),
origin,
boxXyxy: box(item.box_xyxy, `${label}.box`),
occluded: boolean(item.occluded, `${label}.occluded`),
truncated: boolean(item.truncated, `${label}.truncated`),
};
}
function parseProgress(value: unknown): L34FProgress {
const item = record(value, "L3.4F.progress");
const frameCount = integer(item.frame_count, "L3.4F.frame_count");
if (frameCount !== 32) throw new L34FContractError("L3.4F: ожидались 32 кадра.");
return {
reviewedFrameCount: integer(item.reviewed_frame_count, "L3.4F.reviewed"),
frameCount: 32,
objectCount: integer(item.object_count, "L3.4F.objects"),
complete: boolean(item.complete, "L3.4F.complete"),
};
}
function parseSummary(value: unknown): L34FSessionSummary {
const item = record(value, "L3.4F.session");
exact(item.schema_version, "missioncore.l34f-adjudication-session/v1", "L3.4F.schema");
exact(item.contract_id, "l34e-candidate-visible-adjudication/v1", "L3.4F.contract");
const authority = record(item.authority, "L3.4F.authority");
exact(authority.ground_truth, false, "L3.4F.truth");
exact(authority.independent_truth, false, "L3.4F.independent");
exact(authority.metric_grade_reference, false, "L3.4F.metric_grade");
exact(authority.candidate_accepted, false, "L3.4F.accepted");
const assistance = record(item.assistance, "L3.4F.assistance");
exact(assistance.mode, "candidate-visible-human-adjudication", "L3.4F.mode");
exact(assistance.independent_truth_eligible, false, "L3.4F.eligible");
const state = item.state;
if (state !== "draft" && state !== "saved") {
throw new L34FContractError("L3.4F.state: нарушен контракт.");
}
return {
sessionId: text(item.session_id, "L3.4F.session_id"),
diagnosticResultId: text(item.diagnostic_result_id, "L3.4F.result_id"),
title: text(item.title, "L3.4F.title"),
reviewerSlot: integer(item.reviewer_slot, "L3.4F.reviewer"),
revision: integer(item.revision, "L3.4F.revision"),
state,
createdAtUtc: text(item.created_at_utc, "L3.4F.created"),
updatedAtUtc: text(item.updated_at_utc, "L3.4F.updated"),
progress: parseProgress(item.progress),
};
}
function parseSession(value: unknown): L34FSession {
const item = record(value, "L3.4F.session");
const summary = parseSummary(item);
const frames = list(item.frames, "L3.4F.frames").map((raw, index) => {
const frame = record(raw, `L3.4F.frame.${index}`);
return {
truthIslandSequence: integer(frame.truth_island_sequence, `L3.4F.frame.${index}.sequence`),
imageId: integer(frame.image_id, `L3.4F.frame.${index}.image`),
frameIndex: integer(frame.frame_index, `L3.4F.frame.${index}.frame`),
sourceSha256: text(frame.source_sha256, `L3.4F.frame.${index}.source`),
reviewed: boolean(frame.reviewed, `L3.4F.frame.${index}.reviewed`),
objects: list(frame.objects, `L3.4F.frame.${index}.objects`).map(
(object, objectIndex) => parseObject(object, `L3.4F.object.${objectIndex}`),
),
};
});
if (frames.length !== 32) throw new L34FContractError("L3.4F: ожидались 32 кадра.");
return { ...summary, frames };
}
async function responseJson(response: Response, label: string): Promise<unknown> {
if (response.ok) return response.json();
let detail = "";
try {
const payload = record(await response.json(), label);
detail = typeof payload.detail === "string" ? `: ${payload.detail}` : "";
} catch {
detail = "";
}
throw new L34FContractError(`${label} недоступен: HTTP ${response.status}${detail}.`);
}
function assertDiagnosticId(resultId: string): void {
if (!/^l34e-self-review-diagnostic-[a-f0-9]{64}$/.test(resultId)) {
throw new L34FContractError("L3.4F: неверный diagnostic result id.");
}
}
function base(resultId: string): string {
assertDiagnosticId(resultId);
return `/api/v1/laboratory/l34f/diagnostics/${resultId}`;
}
export async function fetchL34FCase(
resultId: string,
sequence: number,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
): Promise<L34FCase> {
const response = await fetcher(`${base(resultId)}/cases/${sequence}`, {
method: "GET", headers: { Accept: "application/json" }, signal,
});
const item = record(await responseJson(response, "Кадр L3.4F"), "L3.4F.case");
exact(item.schema_version, "missioncore.l34f-adjudication-case/v1", "L3.4F.case.schema");
exact(item.diagnostic_result_id, resultId, "L3.4F.case.result");
exact(item.truth_island_sequence, sequence, "L3.4F.case.sequence");
exact(item.model_scores_included, false, "L3.4F.case.scores");
exact(item.ground_truth, false, "L3.4F.case.truth");
const camera = record(item.camera, "L3.4F.camera");
const summary = record(item.diagnostic_summary, "L3.4F.summary");
return {
diagnosticResultId: resultId,
truthIslandSequence: sequence,
imageId: integer(item.image_id, "L3.4F.case.image"),
frameIndex: integer(item.frame_index, "L3.4F.case.frame"),
groupId: text(item.group_id, "L3.4F.case.group"),
sessionSeconds: finite(item.session_seconds, "L3.4F.case.time"),
sourceImageSha256: text(item.source_image_sha256, "L3.4F.case.source"),
cameraWidth: integer(camera.width, "L3.4F.case.width"),
cameraHeight: integer(camera.height, "L3.4F.case.height"),
cameraUrl: text(item.camera_url, "L3.4F.case.camera_url"),
candidateObjects: list(item.candidate_objects, "L3.4F.candidates").map((raw, index) => {
const object = record(raw, `L3.4F.candidate.${index}`);
return {
candidateId: text(object.candidate_id, `L3.4F.candidate.${index}.id`),
predictionIndex: integer(object.prediction_index, `L3.4F.candidate.${index}.index`),
category: text(object.category, `L3.4F.candidate.${index}.category`),
boxXyxy: box(object.box_xyxy, `L3.4F.candidate.${index}.box`),
diagnosticVerdict: verdict(object.diagnostic_verdict, `L3.4F.candidate.${index}.verdict`),
associatedObjectId: object.associated_object_id === null
? null
: text(object.associated_object_id, `L3.4F.candidate.${index}.association`),
};
}),
severityScore: integer(summary.severity_score, "L3.4F.case.severity"),
modelScoresIncluded: false,
groundTruth: false,
};
}
export async function fetchL34FSessions(
resultId: string,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
): Promise<readonly L34FSessionSummary[]> {
const response = await fetcher(`${base(resultId)}/sessions`, {
method: "GET", headers: { Accept: "application/json" }, signal,
});
const catalog = record(await responseJson(response, "Сессии L3.4F"), "L3.4F.catalog");
exact(catalog.schema_version, "missioncore.l34f-adjudication-session-catalog/v1", "L3.4F.catalog.schema");
exact(catalog.diagnostic_result_id, resultId, "L3.4F.catalog.result");
return list(catalog.items, "L3.4F.catalog.items").map(parseSummary);
}
export async function fetchL34FSession(
resultId: string,
sessionId: string,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
): Promise<L34FSession> {
const response = await fetcher(`${base(resultId)}/sessions/${sessionId}`, {
method: "GET", headers: { Accept: "application/json" }, signal,
});
return parseSession(await responseJson(response, "Сессия L3.4F"));
}
export async function createL34FSession(
resultId: string,
{ fetcher = fetch }: { fetcher?: LaboratoryFetch } = {},
): Promise<L34FSession> {
const response = await fetcher(`${base(resultId)}/sessions`, {
method: "POST",
headers: { Accept: "application/json", "Content-Type": "application/json" },
body: JSON.stringify({ idempotency_key: annotationOperationKey("create-l34f") }),
});
return parseSession(await responseJson(response, "Создание сессии L3.4F"));
}
export async function saveL34FSession(
session: L34FSession,
title: string,
frames: readonly L34FFrame[],
{ fetcher = fetch }: { fetcher?: LaboratoryFetch } = {},
): Promise<L34FSession> {
const response = await fetcher(
`${base(session.diagnosticResultId)}/sessions/${session.sessionId}`,
{
method: "PUT",
headers: { Accept: "application/json", "Content-Type": "application/json" },
body: JSON.stringify({
expected_revision: session.revision,
idempotency_key: annotationOperationKey("save-l34f"),
title,
frames: frames.map((frame) => ({
truth_island_sequence: frame.truthIslandSequence,
reviewed: frame.reviewed,
objects: frame.objects.map((object) => ({
object_id: object.objectId,
category: object.category,
proposed_label: object.proposedLabel,
origin: object.origin,
box_xyxy: [...object.boxXyxy],
occluded: object.occluded,
truncated: object.truncated,
})),
})),
}),
},
);
return parseSession(await responseJson(response, "Сохранение сессии L3.4F"));
}
export async function freezeL34FSession(
session: L34FSession,
{ fetcher = fetch }: { fetcher?: LaboratoryFetch } = {},
): Promise<L34FFrozenResult> {
const response = await fetcher(
`${base(session.diagnosticResultId)}/sessions/${session.sessionId}/freeze`,
{
method: "POST",
headers: { Accept: "application/json", "Content-Type": "application/json" },
body: JSON.stringify({ expected_revision: session.revision }),
},
);
return parseFrozenResult(await responseJson(response, "Freeze L3.4F"));
}
export async function fetchL34FFrozenResult({
fetcher = fetch,
signal,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<L34FFrozenResult> {
const response = await fetcher("/api/v1/laboratory/l34f/results?limit=1", {
method: "GET",
headers: { Accept: "application/json" },
signal,
});
const catalog = record(await responseJson(response, "L3.4F"), "L3.4F.catalog");
exact(
catalog.schema_version,
"missioncore.l34f-adjudicated-reference-catalog/v1",
"L3.4F.catalog.schema",
);
const items = list(catalog.items, "L3.4F.catalog.items");
if (items.length !== 1) {
throw new L34FContractError("L3.4F.catalog: ожидался один результат.");
}
return parseFrozenResult(items[0]);
}
export function parseFrozenResult(value: unknown): L34FFrozenResult {
const item = record(value, "L3.4F.result");
const metrics = record(item.metrics, "L3.4F.metrics");
const decision = record(item.decision, "L3.4F.decision");
const resultId = text(item.result_id, "L3.4F.result_id");
if (!/^l34f-adjudicated-reference-[a-f0-9]{64}$/.test(resultId)) {
throw new L34FContractError("L3.4F.result_id: нарушена идентичность.");
}
const diagnosticResultId = text(item.diagnostic_result_id, "L3.4F.diagnostic_result_id");
assertDiagnosticId(diagnosticResultId);
return {
resultId,
createdAtUtc: text(item.created_at_utc, "L3.4F.created_at"),
sourceSessionId: exact(item.source_session_id, "RAVNOVES00", "L3.4F.source_session_id"),
diagnosticResultId,
adjudicationSessionId: text(item.adjudication_session_id, "L3.4F.adjudication_session_id"),
status: exact(item.status, "completed-candidate-visible-adjudication-not-truth", "L3.4F.status"),
metrics: {
frameCount: integer(metrics.frame_count, "L3.4F.frames"),
sourceReferenceCount: integer(metrics.source_reference_count, "L3.4F.source_references"),
adjudicatedReferenceCount: integer(metrics.adjudicated_reference_count, "L3.4F.references"),
unchangedObjectCount: integer(metrics.unchanged_object_count, "L3.4F.unchanged"),
geometryChangedObjectCount: integer(metrics.geometry_changed_object_count, "L3.4F.geometry"),
classChangedObjectCount: integer(metrics.class_changed_object_count, "L3.4F.class"),
attributeChangedObjectCount: integer(metrics.attribute_changed_object_count, "L3.4F.attributes"),
addedObjectCount: integer(metrics.added_object_count, "L3.4F.added"),
deletedObjectCount: integer(metrics.deleted_object_count, "L3.4F.deleted"),
changedFrameCount: integer(metrics.changed_frame_count, "L3.4F.changed_frames"),
},
decision: {
adjudicationComplete: boolean(decision.adjudication_complete, "L3.4F.complete"),
engineeringReferenceAvailable: boolean(decision.engineering_reference_available, "L3.4F.engineering"),
metricGradeReferenceAvailable: boolean(decision.metric_grade_reference_available, "L3.4F.metric_grade"),
independentTruthAvailable: boolean(decision.independent_truth_available, "L3.4F.independent"),
candidateAccepted: boolean(decision.candidate_accepted, "L3.4F.accepted"),
detectorRetuningAuthorized: boolean(decision.detector_retuning_authorized, "L3.4F.retuning"),
l35BlindGateOpen: boolean(decision.l35_blind_gate_open, "L3.4F.l35"),
nextAction: text(decision.next_action, "L3.4F.next"),
},
limitations: list(item.limitations, "L3.4F.limitations").map((raw, index) => text(raw, `L3.4F.limitation.${index}`)),
groundTruth: exact(item.ground_truth, false, "L3.4F.truth"),
};
}
@@ -28,6 +28,7 @@ export interface L3VisualBox {
| "false-positive"
| "model-prediction";
score: number | null;
temporalStatus?: string;
}
export interface L3VisualFrame {