feat(control-station): review native raw fisheye risk cases
This commit is contained in:
@@ -136,7 +136,7 @@ const RESULT_PREFIX: Readonly<Record<AdvancedLaboratoryWorkId, string>> = {
|
|||||||
"m48-object-centric-quality": "m48-object-quality-(?:pack|result)",
|
"m48-object-centric-quality": "m48-object-quality-(?:pack|result)",
|
||||||
"m48-small-static-passage-regression": "m48-small-static-passage-regression",
|
"m48-small-static-passage-regression": "m48-small-static-passage-regression",
|
||||||
"m48s-fixed-class-detector": "m48s-fixed-class-detector-lab",
|
"m48s-fixed-class-detector": "m48s-fixed-class-detector-lab",
|
||||||
"m48t-risk-quality-temporal": "m48t-risk-quality-temporal-lab",
|
"m48t-risk-quality-temporal": "(?:m48t-risk-quality-temporal-lab|m48q-native-risk-quality-lab)",
|
||||||
"m47-reference-graph-shadow": "m47-reference-graph-lab",
|
"m47-reference-graph-shadow": "m47-reference-graph-lab",
|
||||||
"m4-replay-threat": "m4-threat-replay",
|
"m4-replay-threat": "m4-threat-replay",
|
||||||
"l3-pointpillars-visual-audit": "l3-pointpillars-visual-audit",
|
"l3-pointpillars-visual-audit": "l3-pointpillars-visual-audit",
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ export interface M48TReviewCase {
|
|||||||
sha256: string;
|
sha256: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface M48TRiskQualityResult {
|
export interface M48TLegacyRiskQualityResult {
|
||||||
|
variant: "legacy-coco-quality";
|
||||||
resultId: string;
|
resultId: string;
|
||||||
createdAtUtc: string;
|
createdAtUtc: string;
|
||||||
source: {
|
source: {
|
||||||
@@ -93,6 +94,90 @@ export interface M48TRiskQualityResult {
|
|||||||
limitations: readonly string[];
|
limitations: readonly string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type M48QRiskFamily = "person" | "animal" | "light-road-user" | "vehicle";
|
||||||
|
|
||||||
|
export interface M48QNativeProposal {
|
||||||
|
proposalId: string;
|
||||||
|
className: string;
|
||||||
|
riskFamily: M48QRiskFamily;
|
||||||
|
score: number;
|
||||||
|
boxXyxy: readonly [number, number, number, number];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface M48QNativeReviewCase {
|
||||||
|
caseId: string;
|
||||||
|
sequence: number;
|
||||||
|
frameId: string;
|
||||||
|
evidenceTimeNs: number;
|
||||||
|
imageUrl: string;
|
||||||
|
width: 800;
|
||||||
|
height: 600;
|
||||||
|
byteLength: number;
|
||||||
|
sha256: string;
|
||||||
|
selectionBuckets: readonly string[];
|
||||||
|
nativeDetectionCount: number;
|
||||||
|
legacyDetectionCount: number;
|
||||||
|
matchedDetectionCount: number;
|
||||||
|
proposals: readonly M48QNativeProposal[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface M48QNativeRiskQualityResult {
|
||||||
|
variant: "native-risk-review";
|
||||||
|
resultId: string;
|
||||||
|
createdAtUtc: string;
|
||||||
|
source: {
|
||||||
|
sourceId: "RAVNOVES00";
|
||||||
|
frameCount: 4489;
|
||||||
|
width: 800;
|
||||||
|
height: 600;
|
||||||
|
geometricResampling: false;
|
||||||
|
};
|
||||||
|
candidate: {
|
||||||
|
providerId: string;
|
||||||
|
modelId: "rf_detr_large_native_kb4:1";
|
||||||
|
preprocessId: "raw-kb4-uint8-fused-mask-rgb-pad8-imagenet-trt/v0";
|
||||||
|
minimumScore: 0.25;
|
||||||
|
};
|
||||||
|
execution: {
|
||||||
|
effectiveWorldStateFps: number;
|
||||||
|
worldStateCompletionP95Ms: number;
|
||||||
|
detectorTotalP95Ms: number;
|
||||||
|
gpuUtilizationP95Percent: number;
|
||||||
|
gpuMemoryMaximumMib: number;
|
||||||
|
additionalInferencePasses: 0;
|
||||||
|
};
|
||||||
|
selection: {
|
||||||
|
caseCount: 24;
|
||||||
|
minimumSequenceSeparation: number;
|
||||||
|
bucketCoverage: Readonly<Record<string, number>>;
|
||||||
|
classCounts: Readonly<Record<string, number>>;
|
||||||
|
};
|
||||||
|
runtime: {
|
||||||
|
deliveryRatio: number;
|
||||||
|
integratedGatePassed: true;
|
||||||
|
operatingTargetGatePassed: true;
|
||||||
|
};
|
||||||
|
parity: {
|
||||||
|
precision: number;
|
||||||
|
recall: number;
|
||||||
|
meanIou: number;
|
||||||
|
};
|
||||||
|
acceptance: {
|
||||||
|
reviewReady: true;
|
||||||
|
independentQualityEvaluated: false;
|
||||||
|
semanticCandidateAccepted: false;
|
||||||
|
};
|
||||||
|
review: {
|
||||||
|
cases: readonly M48QNativeReviewCase[];
|
||||||
|
};
|
||||||
|
method: M48TLaboratoryMethod;
|
||||||
|
limitations: readonly string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type M48TRiskQualityResult =
|
||||||
|
| M48TLegacyRiskQualityResult
|
||||||
|
| M48QNativeRiskQualityResult;
|
||||||
|
|
||||||
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
||||||
|
|
||||||
export class M48TContractError extends Error {}
|
export class M48TContractError extends Error {}
|
||||||
@@ -173,9 +258,10 @@ function method(value: unknown): M48TLaboratoryMethod {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseResult(value: unknown, expectedResultId: string): M48TRiskQualityResult {
|
function parseLegacyResult(value: unknown, expectedResultId: string): M48TLegacyRiskQualityResult {
|
||||||
const raw = object(value, "M4.8T result");
|
const raw = object(value, "M4.8T result");
|
||||||
exact(raw.schema_version, "missioncore.m48t-risk-quality-temporal-view/v1", "M4.8T schema");
|
exact(raw.schema_version, "missioncore.m48t-risk-quality-temporal-view/v1", "M4.8T schema");
|
||||||
|
exact(raw.variant, "legacy-coco-quality", "M4.8T variant");
|
||||||
exact(raw.result_id, expectedResultId, "M4.8T identity");
|
exact(raw.result_id, expectedResultId, "M4.8T identity");
|
||||||
exact(raw.status, "complete-quality-gate-failed-temporal-invariant-passed", "M4.8T status");
|
exact(raw.status, "complete-quality-gate-failed-temporal-invariant-passed", "M4.8T status");
|
||||||
exact(raw.access, "read-only", "M4.8T access");
|
exact(raw.access, "read-only", "M4.8T access");
|
||||||
@@ -234,6 +320,7 @@ function parseResult(value: unknown, expectedResultId: string): M48TRiskQualityR
|
|||||||
for (const [key, count] of Object.entries(failures)) parsedFailures[key] = integer(count, `M4.8T failure ${key}`);
|
for (const [key, count] of Object.entries(failures)) parsedFailures[key] = integer(count, `M4.8T failure ${key}`);
|
||||||
const temporalConfiguration = object(configuration.temporal, "M4.8T temporal configuration");
|
const temporalConfiguration = object(configuration.temporal, "M4.8T temporal configuration");
|
||||||
return {
|
return {
|
||||||
|
variant: "legacy-coco-quality",
|
||||||
resultId: expectedResultId,
|
resultId: expectedResultId,
|
||||||
createdAtUtc: text(raw.created_at_utc, "M4.8T created at"),
|
createdAtUtc: text(raw.created_at_utc, "M4.8T created at"),
|
||||||
source: {
|
source: {
|
||||||
@@ -306,6 +393,207 @@ function parseResult(value: unknown, expectedResultId: string): M48TRiskQualityR
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function numberRecord(value: unknown, label: string): Readonly<Record<string, number>> {
|
||||||
|
const raw = object(value, label);
|
||||||
|
const parsed: Record<string, number> = {};
|
||||||
|
for (const [key, item] of Object.entries(raw)) parsed[key] = integer(item, `${label}.${key}`);
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nativeRiskFamily(value: unknown): M48QRiskFamily {
|
||||||
|
const parsed = text(value, "M4.8Q risk family");
|
||||||
|
if (!["person", "animal", "light-road-user", "vehicle"].includes(parsed)) {
|
||||||
|
throw new M48TContractError("M4.8Q risk family: неизвестное значение.");
|
||||||
|
}
|
||||||
|
return parsed as M48QRiskFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nativeProposal(value: unknown): M48QNativeProposal {
|
||||||
|
const raw = object(value, "M4.8Q proposal");
|
||||||
|
const coordinates = array(raw.box_xyxy, "M4.8Q proposal box").map((item) =>
|
||||||
|
number(item, "M4.8Q proposal coordinate")
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
coordinates.length !== 4
|
||||||
|
|| coordinates[0] >= coordinates[2]
|
||||||
|
|| coordinates[1] >= coordinates[3]
|
||||||
|
|| coordinates[2] > 800
|
||||||
|
|| coordinates[3] > 600
|
||||||
|
) {
|
||||||
|
throw new M48TContractError("M4.8Q proposal box: нарушена raw-raster геометрия.");
|
||||||
|
}
|
||||||
|
const score = number(raw.score, "M4.8Q proposal score");
|
||||||
|
if (score < 0.25 || score > 1) throw new M48TContractError("M4.8Q proposal score: нарушен threshold.");
|
||||||
|
return {
|
||||||
|
proposalId: text(raw.proposal_id, "M4.8Q proposal id"),
|
||||||
|
className: text(raw.class_name, "M4.8Q proposal class"),
|
||||||
|
riskFamily: nativeRiskFamily(raw.risk_family),
|
||||||
|
score,
|
||||||
|
boxXyxy: coordinates as [number, number, number, number],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseNativeResult(value: unknown, expectedResultId: string): M48QNativeRiskQualityResult {
|
||||||
|
const raw = object(value, "M4.8Q result");
|
||||||
|
exact(raw.schema_version, "missioncore.m48q-native-risk-quality-view/v1", "M4.8Q schema");
|
||||||
|
exact(raw.variant, "native-risk-review", "M4.8Q variant");
|
||||||
|
exact(raw.result_id, expectedResultId, "M4.8Q identity");
|
||||||
|
exact(raw.status, "complete-review-ready-quality-not-adjudicated", "M4.8Q status");
|
||||||
|
exact(raw.access, "read-only", "M4.8Q access");
|
||||||
|
exact(raw.ground_truth, false, "M4.8Q ground truth");
|
||||||
|
|
||||||
|
const source = object(raw.source, "M4.8Q source");
|
||||||
|
exact(source.source_id, "RAVNOVES00", "M4.8Q source id");
|
||||||
|
exact(source.frame_count, 4489, "M4.8Q source frames");
|
||||||
|
exact(source.raster_width, 800, "M4.8Q source width");
|
||||||
|
exact(source.raster_height, 600, "M4.8Q source height");
|
||||||
|
exact(source.geometric_resampling, false, "M4.8Q source resampling");
|
||||||
|
exact(source.rectification, false, "M4.8Q source rectification");
|
||||||
|
exact(source.warp, false, "M4.8Q source warp");
|
||||||
|
|
||||||
|
const configuration = object(raw.configuration, "M4.8Q configuration");
|
||||||
|
const candidate = object(configuration.candidate, "M4.8Q candidate");
|
||||||
|
const execution = object(raw.execution, "M4.8Q execution");
|
||||||
|
const metrics = object(raw.metrics, "M4.8Q metrics");
|
||||||
|
const selection = object(metrics.selection, "M4.8Q selection");
|
||||||
|
const runtime = object(metrics.runtime, "M4.8Q runtime");
|
||||||
|
const parity = object(metrics.native_tensor_parity, "M4.8Q parity");
|
||||||
|
const acceptance = object(raw.acceptance, "M4.8Q acceptance");
|
||||||
|
exact(acceptance.review_ready, true, "M4.8Q review readiness");
|
||||||
|
exact(acceptance.integrated_runtime_gate_passed, true, "M4.8Q runtime gate");
|
||||||
|
exact(acceptance.independent_quality_evaluated, false, "M4.8Q quality state");
|
||||||
|
exact(acceptance.semantic_candidate_accepted, false, "M4.8Q candidate state");
|
||||||
|
exact(selection.case_count, 24, "M4.8Q selected cases");
|
||||||
|
|
||||||
|
const review = object(raw.review, "M4.8Q review");
|
||||||
|
const raster = object(review.source_raster, "M4.8Q review raster");
|
||||||
|
exact(raster.width, 800, "M4.8Q review width");
|
||||||
|
exact(raster.height, 600, "M4.8Q review height");
|
||||||
|
const overlay = object(review.overlay, "M4.8Q overlay");
|
||||||
|
exact(overlay.client_rendered, true, "M4.8Q client overlay");
|
||||||
|
exact(overlay.toggleable, true, "M4.8Q overlay toggle");
|
||||||
|
const cases = array(review.cases, "M4.8Q review cases").map((value) => {
|
||||||
|
const item = object(value, "M4.8Q review case");
|
||||||
|
const caseId = text(item.case_id, "M4.8Q case id");
|
||||||
|
if (!/^[0-9]{6}$/.test(caseId)) throw new M48TContractError("M4.8Q case identity нарушена.");
|
||||||
|
const sequence = integer(item.sequence, "M4.8Q case sequence");
|
||||||
|
exact(caseId, sequence.toString().padStart(6, "0"), "M4.8Q case/sequence identity");
|
||||||
|
exact(item.frame_id, `frame-${caseId}`, "M4.8Q frame identity");
|
||||||
|
exact(item.media_type, "image/jpeg", "M4.8Q case media");
|
||||||
|
exact(item.width, 800, "M4.8Q case width");
|
||||||
|
exact(item.height, 600, "M4.8Q case height");
|
||||||
|
exact(item.geometric_resampling, false, "M4.8Q case resampling");
|
||||||
|
const comparison = object(item.comparison, "M4.8Q comparison");
|
||||||
|
const proposals = array(item.proposals, "M4.8Q proposals").map(nativeProposal);
|
||||||
|
if (!proposals.length) throw new M48TContractError("M4.8Q proposals: пустой review case.");
|
||||||
|
return {
|
||||||
|
caseId,
|
||||||
|
sequence,
|
||||||
|
frameId: `frame-${caseId}`,
|
||||||
|
evidenceTimeNs: integer(item.evidence_time_ns, "M4.8Q evidence time"),
|
||||||
|
imageUrl: text(item.image_url, "M4.8Q image URL"),
|
||||||
|
width: 800 as const,
|
||||||
|
height: 600 as const,
|
||||||
|
byteLength: integer(item.byte_length, "M4.8Q image bytes"),
|
||||||
|
sha256: sha(item.sha256, "M4.8Q image SHA"),
|
||||||
|
selectionBuckets: array(item.selection_buckets, "M4.8Q selection buckets").map((bucket) =>
|
||||||
|
text(bucket, "M4.8Q selection bucket")
|
||||||
|
),
|
||||||
|
nativeDetectionCount: integer(comparison.native_detection_count, "M4.8Q native count"),
|
||||||
|
legacyDetectionCount: integer(comparison.legacy_704_detection_count, "M4.8Q legacy count"),
|
||||||
|
matchedDetectionCount: integer(
|
||||||
|
comparison.matched_detection_count_iou_at_least_0_5,
|
||||||
|
"M4.8Q matched count",
|
||||||
|
),
|
||||||
|
proposals,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (cases.length !== 24 || new Set(cases.map(({ caseId }) => caseId)).size !== 24) {
|
||||||
|
throw new M48TContractError("M4.8Q review catalog: нарушен размер.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
variant: "native-risk-review",
|
||||||
|
resultId: expectedResultId,
|
||||||
|
createdAtUtc: text(raw.created_at_utc, "M4.8Q created at"),
|
||||||
|
source: {
|
||||||
|
sourceId: "RAVNOVES00",
|
||||||
|
frameCount: 4489,
|
||||||
|
width: 800,
|
||||||
|
height: 600,
|
||||||
|
geometricResampling: false,
|
||||||
|
},
|
||||||
|
candidate: {
|
||||||
|
providerId: text(candidate.provider_id, "M4.8Q provider"),
|
||||||
|
modelId: exact(candidate.model_id, "rf_detr_large_native_kb4:1", "M4.8Q model"),
|
||||||
|
preprocessId: exact(
|
||||||
|
candidate.preprocess_id,
|
||||||
|
"raw-kb4-uint8-fused-mask-rgb-pad8-imagenet-trt/v0",
|
||||||
|
"M4.8Q preprocess",
|
||||||
|
),
|
||||||
|
minimumScore: exact(candidate.minimum_score, 0.25, "M4.8Q threshold"),
|
||||||
|
},
|
||||||
|
execution: {
|
||||||
|
effectiveWorldStateFps: number(execution.effective_world_state_fps, "M4.8Q FPS"),
|
||||||
|
worldStateCompletionP95Ms: number(
|
||||||
|
execution.world_state_completion_p95_ms,
|
||||||
|
"M4.8Q world-state p95",
|
||||||
|
),
|
||||||
|
detectorTotalP95Ms: number(execution.detector_total_p95_ms, "M4.8Q detector p95"),
|
||||||
|
gpuUtilizationP95Percent: number(
|
||||||
|
execution.gpu_utilization_p95_percent,
|
||||||
|
"M4.8Q GPU p95",
|
||||||
|
),
|
||||||
|
gpuMemoryMaximumMib: number(
|
||||||
|
execution.gpu_memory_used_maximum_mib,
|
||||||
|
"M4.8Q VRAM maximum",
|
||||||
|
),
|
||||||
|
additionalInferencePasses: exact(
|
||||||
|
execution.additional_inference_passes,
|
||||||
|
0,
|
||||||
|
"M4.8Q inference passes",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
selection: {
|
||||||
|
caseCount: 24,
|
||||||
|
minimumSequenceSeparation: integer(
|
||||||
|
selection.minimum_sequence_separation,
|
||||||
|
"M4.8Q case separation",
|
||||||
|
),
|
||||||
|
bucketCoverage: numberRecord(selection.selected_bucket_coverage, "M4.8Q bucket coverage"),
|
||||||
|
classCounts: numberRecord(selection.selected_class_counts, "M4.8Q class counts"),
|
||||||
|
},
|
||||||
|
runtime: {
|
||||||
|
deliveryRatio: number(runtime.delivery_ratio, "M4.8Q delivery ratio"),
|
||||||
|
integratedGatePassed: exact(
|
||||||
|
runtime.integrated_runtime_gate_passed,
|
||||||
|
true,
|
||||||
|
"M4.8Q integrated gate",
|
||||||
|
),
|
||||||
|
operatingTargetGatePassed: exact(
|
||||||
|
runtime.operating_target_gate_passed,
|
||||||
|
true,
|
||||||
|
"M4.8Q target gate",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
parity: {
|
||||||
|
precision: number(parity.risk_detection_precision, "M4.8Q parity precision"),
|
||||||
|
recall: number(parity.risk_detection_recall, "M4.8Q parity recall"),
|
||||||
|
meanIou: number(parity.matched_mean_iou, "M4.8Q parity IoU"),
|
||||||
|
},
|
||||||
|
acceptance: {
|
||||||
|
reviewReady: true,
|
||||||
|
independentQualityEvaluated: false,
|
||||||
|
semanticCandidateAccepted: false,
|
||||||
|
},
|
||||||
|
review: { cases },
|
||||||
|
method: method(raw.method),
|
||||||
|
limitations: array(raw.limitations, "M4.8Q limitations").map((item) =>
|
||||||
|
text(item, "M4.8Q limitation")
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchM48TRiskQualityResult(
|
export async function fetchM48TRiskQualityResult(
|
||||||
resultId: string,
|
resultId: string,
|
||||||
{
|
{
|
||||||
@@ -313,7 +601,7 @@ export async function fetchM48TRiskQualityResult(
|
|||||||
signal,
|
signal,
|
||||||
}: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
|
}: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
|
||||||
): Promise<M48TRiskQualityResult> {
|
): Promise<M48TRiskQualityResult> {
|
||||||
if (!/^m48t-risk-quality-temporal-lab-[a-f0-9]{64}$/.test(resultId)) {
|
if (!/^(?:m48t-risk-quality-temporal-lab|m48q-native-risk-quality-lab)-[a-f0-9]{64}$/.test(resultId)) {
|
||||||
throw new M48TContractError("M4.8T result identity недопустима.");
|
throw new M48TContractError("M4.8T result identity недопустима.");
|
||||||
}
|
}
|
||||||
const response = await fetcher(`/api/v1/laboratory/m48t/risk-quality/results/${resultId}`, {
|
const response = await fetcher(`/api/v1/laboratory/m48t/risk-quality/results/${resultId}`, {
|
||||||
@@ -322,5 +610,9 @@ export async function fetchM48TRiskQualityResult(
|
|||||||
signal,
|
signal,
|
||||||
});
|
});
|
||||||
if (!response.ok) throw new M48TContractError(`M4.8T недоступен: HTTP ${response.status}.`);
|
if (!response.ok) throw new M48TContractError(`M4.8T недоступен: HTTP ${response.status}.`);
|
||||||
return parseResult(await response.json(), resultId);
|
const payload: unknown = await response.json();
|
||||||
|
const raw = object(payload, "M4.8T/M4.8Q result");
|
||||||
|
return raw.schema_version === "missioncore.m48q-native-risk-quality-view/v1"
|
||||||
|
? parseNativeResult(payload, resultId)
|
||||||
|
: parseLegacyResult(payload, resultId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ import {
|
|||||||
LaboratorySummary,
|
LaboratorySummary,
|
||||||
LaboratoryWorkTemplate,
|
LaboratoryWorkTemplate,
|
||||||
} from "../../components/laboratory/LaboratoryPresentation";
|
} from "../../components/laboratory/LaboratoryPresentation";
|
||||||
import type { M48TRiskQualityResult } from "../../core/laboratory/m48tRiskQuality";
|
import type {
|
||||||
|
M48QNativeRiskQualityResult,
|
||||||
|
M48TLegacyRiskQualityResult,
|
||||||
|
M48TRiskQualityResult,
|
||||||
|
} from "../../core/laboratory/m48tRiskQuality";
|
||||||
import { M48TRiskQualityVisual } from "./M48TRiskQualityVisual";
|
import { M48TRiskQualityVisual } from "./M48TRiskQualityVisual";
|
||||||
|
|
||||||
function percent(value: number, digits = 1): string {
|
function percent(value: number, digits = 1): string {
|
||||||
@@ -21,6 +25,19 @@ export function M48TRiskQualityResultView({
|
|||||||
}: {
|
}: {
|
||||||
rigLabel: string;
|
rigLabel: string;
|
||||||
result: M48TRiskQualityResult;
|
result: M48TRiskQualityResult;
|
||||||
|
}) {
|
||||||
|
if (result.variant === "native-risk-review") {
|
||||||
|
return <M48QNativeRiskQualityResultView rigLabel={rigLabel} result={result} />;
|
||||||
|
}
|
||||||
|
return <M48TLegacyRiskQualityResultView rigLabel={rigLabel} result={result} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function M48TLegacyRiskQualityResultView({
|
||||||
|
rigLabel,
|
||||||
|
result,
|
||||||
|
}: {
|
||||||
|
rigLabel: string;
|
||||||
|
result: M48TLegacyRiskQualityResult;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<LaboratoryWorkTemplate
|
<LaboratoryWorkTemplate
|
||||||
@@ -77,3 +94,69 @@ export function M48TRiskQualityResultView({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function M48QNativeRiskQualityResultView({
|
||||||
|
rigLabel,
|
||||||
|
result,
|
||||||
|
}: {
|
||||||
|
rigLabel: string;
|
||||||
|
result: M48QNativeRiskQualityResult;
|
||||||
|
}) {
|
||||||
|
const classes = Object.entries(result.selection.classCounts)
|
||||||
|
.map(([name, count]) => `${name} ${count}`)
|
||||||
|
.join(" · ");
|
||||||
|
return (
|
||||||
|
<LaboratoryWorkTemplate
|
||||||
|
summary={(
|
||||||
|
<LaboratorySummary
|
||||||
|
title="M4.8Q · native raw-fisheye risk review"
|
||||||
|
description="Нативный RF-DETR прогнан внутри полного reference graph прямо на исходном KB4 raster 800×600: без rectification, warp, resize и обратного преобразования. Из immutable frame ledger детерминированно отобраны реальные risk-кейсы для операторской проверки в существующем M4.8 image-case instrument."
|
||||||
|
status="Runtime принят · 24 native cases готовы · quality ещё не adjudicated"
|
||||||
|
statusTone="success"
|
||||||
|
facts={[
|
||||||
|
{ label: "Source", value: `${rigLabel} · ${result.source.frameCount.toLocaleString("ru-RU")} raw frames · 800×600` },
|
||||||
|
{ label: "Candidate", value: `${result.candidate.modelId} · score ≥ ${decimal(result.candidate.minimumScore, 2)}` },
|
||||||
|
{ label: "Image path", value: "RAW KB4 → fused GPU graph · geometric resampling NO" },
|
||||||
|
{ label: "Authority", value: "SHADOW ONLY · independent quality NO · production NO" },
|
||||||
|
]}
|
||||||
|
brief={{
|
||||||
|
question: "Работает ли нативная risk-классификация на нашей исходной fisheye-картинке в realtime envelope, и какие реальные кадры надо проверить человеком?",
|
||||||
|
approach: `Полный ${result.source.frameCount.toLocaleString("ru-RU")}-кадровый native graph оставлен неизменным. Повторной инференс-сессии для лабы нет: 24 кадра выбраны из его hash-bound ledger по person, animal, light-road-user, vehicle, low-confidence, fisheye-edge и расхождениям с диагностической legacy 704 веткой.`,
|
||||||
|
principalResult: `${decimal(result.execution.effectiveWorldStateFps, 3)} FPS при detector p95 ${decimal(result.execution.detectorTotalP95Ms, 2)} ms и world-state p95 ${decimal(result.execution.worldStateCompletionP95Ms, 2)} ms. В review pack реально попали ${classes}.`,
|
||||||
|
limitation: "Это диагностическая выборка маршрута без независимой разметки. Наличие бокса и класса можно осмотреть, но precision/recall и корректность каждого класса этой фазой ещё не доказаны.",
|
||||||
|
}}
|
||||||
|
method={result.method}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
evidence={(
|
||||||
|
<LaboratoryEvidence
|
||||||
|
eyebrow="M4.8Q VISUAL EVIDENCE · NATIVE RAW KB4"
|
||||||
|
title="24 исходных fisheye-кадра с отключаемым client-side overlay"
|
||||||
|
kind="diagnostic-model"
|
||||||
|
resizable
|
||||||
|
>
|
||||||
|
<M48TRiskQualityVisual result={result} />
|
||||||
|
</LaboratoryEvidence>
|
||||||
|
)}
|
||||||
|
result={(
|
||||||
|
<LaboratoryResultSummary
|
||||||
|
title="Native runtime закрыт; следующий честный шаг — adjudication этих кейсов"
|
||||||
|
status="Review-ready · quality-not-adjudicated"
|
||||||
|
statusTone="success"
|
||||||
|
metrics={[
|
||||||
|
{ label: "Full graph", value: `${decimal(result.execution.effectiveWorldStateFps, 3)} FPS`, hint: `delivery ${percent(result.runtime.deliveryRatio, 2)} · 4 489/4 489` },
|
||||||
|
{ label: "Detector / world-state p95", value: `${decimal(result.execution.detectorTotalP95Ms, 2)} / ${decimal(result.execution.worldStateCompletionP95Ms, 2)} ms`, hint: "один native pass · additional inference 0" },
|
||||||
|
{ label: "GPU / VRAM peak", value: `${decimal(result.execution.gpuUtilizationP95Percent, 1)}% / ${decimal(result.execution.gpuMemoryMaximumMib / 1024, 2)} GiB`, hint: "Worker 006 · RTX 4090 envelope" },
|
||||||
|
{ label: "Native parity", value: `${percent(result.parity.precision, 2)} / ${percent(result.parity.recall, 2)}`, hint: `precision / recall · mean IoU ${percent(result.parity.meanIou, 2)}` },
|
||||||
|
{ label: "Review pack", value: `${result.selection.caseCount}/24 cases`, hint: "8 diagnostic buckets · raw 800×600" },
|
||||||
|
]}
|
||||||
|
conclusion={{
|
||||||
|
proved: `Полный reference graph доставил все ${result.source.frameCount.toLocaleString("ru-RU")} world states на ${decimal(result.execution.effectiveWorldStateFps, 3)} FPS. Детектор использовал ровно один native 800×600 KB4 pass без геометрического resampling. Hash-bound review содержит person, dog, bicycle, skateboard, car и truck; боксы рисуются поверх чистого кадра и отключаются кнопкой.`,
|
||||||
|
notProved: "Не доказаны route-domain precision/recall, истинность 24 классов и боксов, child/adult, поведение объектов, физическая track identity и безопасность навигации. Legacy 704 count delta остаётся только диагностикой, потому что старая ветка растягивала 4:3 raster.",
|
||||||
|
decision: "Не добавлять второй detector и не менять realtime graph. Использовать эти 24 кейса как вход существующего M4.8 review/correction workflow; только после независимой adjudication считать route-domain semantic quality.",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,18 +1,35 @@
|
|||||||
import { useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { Icon, IconButton } from "@nodedc/ui-react";
|
import { Icon, IconButton } from "@nodedc/ui-react";
|
||||||
|
|
||||||
import { LaboratoryEvidenceViewer } from "../../components/laboratory/LaboratoryEvidenceViewer";
|
import { LaboratoryEvidenceViewer } from "../../components/laboratory/LaboratoryEvidenceViewer";
|
||||||
import type { M48TRiskQualityResult } from "../../core/laboratory/m48tRiskQuality";
|
import { RecordedEvidenceImageScene } from "../../components/laboratory/RecordedEvidenceImageScene";
|
||||||
|
import type {
|
||||||
|
RecordedEvidenceBox,
|
||||||
|
RecordedEvidenceBoxTone,
|
||||||
|
} from "../../components/laboratory/RecordedEvidenceBoxOverlay";
|
||||||
|
import type {
|
||||||
|
M48QNativeRiskQualityResult,
|
||||||
|
M48QRiskFamily,
|
||||||
|
M48TLegacyRiskQualityResult,
|
||||||
|
M48TRiskQualityResult,
|
||||||
|
} from "../../core/laboratory/m48tRiskQuality";
|
||||||
|
|
||||||
export function M48TRiskQualityVisual({ result }: { result: M48TRiskQualityResult }) {
|
function navigateIndex(current: number, offset: -1 | 1, length: number): number {
|
||||||
|
return (current + offset + length) % length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function familyTone(family: M48QRiskFamily): RecordedEvidenceBoxTone {
|
||||||
|
if (family === "person" || family === "animal") return "danger";
|
||||||
|
if (family === "light-road-user") return "warning";
|
||||||
|
return "accent";
|
||||||
|
}
|
||||||
|
|
||||||
|
function LegacyVisual({ result }: { result: M48TLegacyRiskQualityResult }) {
|
||||||
const [index, setIndex] = useState(0);
|
const [index, setIndex] = useState(0);
|
||||||
const [expanded, setExpanded] = useState(false);
|
const [expanded, setExpanded] = useState(false);
|
||||||
const item = result.review.cases[index] ?? null;
|
const item = result.review.cases[index] ?? null;
|
||||||
const navigate = (offset: -1 | 1) => {
|
const navigate = (offset: -1 | 1) =>
|
||||||
setIndex((current) => (
|
setIndex((current) => navigateIndex(current, offset, result.review.cases.length));
|
||||||
current + offset + result.review.cases.length
|
|
||||||
) % result.review.cases.length);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="l3-visual-audit">
|
<div className="l3-visual-audit">
|
||||||
@@ -61,3 +78,85 @@ export function M48TRiskQualityVisual({ result }: { result: M48TRiskQualityResul
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function NativeVisual({ result }: { result: M48QNativeRiskQualityResult }) {
|
||||||
|
const [index, setIndex] = useState(0);
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
const [boxesVisible, setBoxesVisible] = useState(true);
|
||||||
|
const item = result.review.cases[index] ?? null;
|
||||||
|
const boxes = useMemo<readonly RecordedEvidenceBox[]>(() => {
|
||||||
|
if (!item || !boxesVisible) return [];
|
||||||
|
return item.proposals.map((proposal) => ({
|
||||||
|
boxXyxy: proposal.boxXyxy,
|
||||||
|
label: `${proposal.className} · ${proposal.score.toFixed(2)}`,
|
||||||
|
tone: familyTone(proposal.riskFamily),
|
||||||
|
}));
|
||||||
|
}, [boxesVisible, item]);
|
||||||
|
const navigate = (offset: -1 | 1) =>
|
||||||
|
setIndex((current) => navigateIndex(current, offset, result.review.cases.length));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="l3-visual-audit">
|
||||||
|
<LaboratoryEvidenceViewer
|
||||||
|
label="M4.8Q native raw-fisheye risk review"
|
||||||
|
mode="native"
|
||||||
|
modes={[{ value: "native", label: "NATIVE RF-DETR" }]}
|
||||||
|
expanded={expanded}
|
||||||
|
onModeChange={() => undefined}
|
||||||
|
onExpandedChange={setExpanded}
|
||||||
|
actions={(
|
||||||
|
<div className="l3-visual-audit__pagination">
|
||||||
|
<IconButton label="Предыдущий M4.8Q review case" onClick={() => navigate(-1)}>
|
||||||
|
<Icon name="chevron-left" size={16} />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton label="Следующий M4.8Q review case" onClick={() => navigate(1)}>
|
||||||
|
<Icon name="chevron-right" size={16} />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
trailingActions={(
|
||||||
|
<IconButton
|
||||||
|
label={boxesVisible ? "Скрыть native RF-DETR боксы" : "Показать native RF-DETR боксы"}
|
||||||
|
onClick={() => setBoxesVisible((visible) => !visible)}
|
||||||
|
>
|
||||||
|
<Icon name={boxesVisible ? "eye-off" : "eye"} size={16} />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
overlay={item ? (
|
||||||
|
<div className="l3-visual-audit__overlay">
|
||||||
|
<div>
|
||||||
|
<span>RAVNOVES00 · raw KB4 800×600 · resampling NO</span>
|
||||||
|
<strong>
|
||||||
|
case {index + 1}/{result.review.cases.length} · frame {item.sequence} · {item.proposals.length} native boxes
|
||||||
|
</strong>
|
||||||
|
<small>
|
||||||
|
{item.selectionBuckets.join(" · ")} · native/legacy {item.nativeDetectionCount}/{item.legacyDetectionCount} (diagnostic only)
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
>
|
||||||
|
{item ? (
|
||||||
|
<RecordedEvidenceImageScene
|
||||||
|
src={item.imageUrl}
|
||||||
|
imageWidth={item.width}
|
||||||
|
imageHeight={item.height}
|
||||||
|
boxes={boxes}
|
||||||
|
ariaLabel={`M4.8Q frame ${item.sequence}: ${boxes.length} visible native risk boxes`}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="l3-visual-audit__state" role="alert">
|
||||||
|
<Icon name="alert" size={18} />
|
||||||
|
M4.8Q native visual evidence недоступно.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</LaboratoryEvidenceViewer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function M48TRiskQualityVisual({ result }: { result: M48TRiskQualityResult }) {
|
||||||
|
return result.variant === "native-risk-review"
|
||||||
|
? <NativeVisual result={result} />
|
||||||
|
: <LegacyVisual result={result} />;
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,10 +86,10 @@ const KNOWN_WORKS: Readonly<Record<Exclude<LaboratoryWorkId, `session:${string}`
|
|||||||
},
|
},
|
||||||
"m48t-risk-quality-temporal": {
|
"m48t-risk-quality-temporal": {
|
||||||
profileId: "rig-ravnoves-perception-gate-v1",
|
profileId: "rig-ravnoves-perception-gate-v1",
|
||||||
profileName: (rigLabel) => `${rig(rigLabel)} RIGHT · COCO quality + bounded temporal identity`,
|
profileName: (rigLabel) => `${rig(rigLabel)} RIGHT · Native raw-fisheye perception gate`,
|
||||||
experimentId: "m48t-risk-quality-temporal",
|
experimentId: "m48t-risk-quality-temporal",
|
||||||
experimentName: "RF-DETR independent semantic quality and temporal identity",
|
experimentName: "RF-DETR native risk review and temporal identity",
|
||||||
variantName: "M4.8T · COCO val2017 truth + RAVNOVES00 temporal shadow",
|
variantName: "M4.8Q · native raw KB4 review · quality not adjudicated",
|
||||||
},
|
},
|
||||||
"m47-reference-graph-shadow": {
|
"m47-reference-graph-shadow": {
|
||||||
profileId: "rig-dual-evidence-virtual-corridor-v1",
|
profileId: "rig-dual-evidence-virtual-corridor-v1",
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { after, before, test } from "node:test";
|
||||||
|
import { readFile } from "node:fs/promises";
|
||||||
|
import { createServer } from "vite";
|
||||||
|
|
||||||
|
let server;
|
||||||
|
let fetchM48TRiskQualityResult;
|
||||||
|
|
||||||
|
const resultId = `m48q-native-risk-quality-lab-${"a".repeat(64)}`;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
server = await createServer({
|
||||||
|
appType: "custom",
|
||||||
|
logLevel: "silent",
|
||||||
|
server: { middlewareMode: true },
|
||||||
|
});
|
||||||
|
({ fetchM48TRiskQualityResult } = await server.ssrLoadModule(
|
||||||
|
"/src/core/laboratory/m48tRiskQuality.ts",
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => server?.close());
|
||||||
|
|
||||||
|
function response(value) {
|
||||||
|
return { ok: true, status: 200, json: async () => value };
|
||||||
|
}
|
||||||
|
|
||||||
|
function payload() {
|
||||||
|
return {
|
||||||
|
schema_version: "missioncore.m48q-native-risk-quality-view/v1",
|
||||||
|
variant: "native-risk-review",
|
||||||
|
result_id: resultId,
|
||||||
|
created_at_utc: "2026-08-26T10:00:00Z",
|
||||||
|
status: "complete-review-ready-quality-not-adjudicated",
|
||||||
|
access: "read-only",
|
||||||
|
ground_truth: false,
|
||||||
|
source: {
|
||||||
|
source_id: "RAVNOVES00",
|
||||||
|
frame_count: 4489,
|
||||||
|
raster_width: 800,
|
||||||
|
raster_height: 600,
|
||||||
|
geometric_resampling: false,
|
||||||
|
rectification: false,
|
||||||
|
warp: false,
|
||||||
|
},
|
||||||
|
configuration: {
|
||||||
|
candidate: {
|
||||||
|
provider_id: "triton-rf-detr-large-coco-native-kb4-risk-fp16-shadow/v0",
|
||||||
|
model_id: "rf_detr_large_native_kb4:1",
|
||||||
|
preprocess_id: "raw-kb4-uint8-fused-mask-rgb-pad8-imagenet-trt/v0",
|
||||||
|
minimum_score: 0.25,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
method: {
|
||||||
|
schema_version: "missioncore.laboratory-method/v1",
|
||||||
|
completeness: "complete",
|
||||||
|
execution_class: "hybrid",
|
||||||
|
pipeline_id: "m48q-native-raw-fisheye-risk-case-review/v1",
|
||||||
|
components: [{
|
||||||
|
kind: "model",
|
||||||
|
name: "RF-DETR-L native KB4 TensorRT",
|
||||||
|
version: "rf_detr_large_native_kb4:1",
|
||||||
|
role: "risk proposals",
|
||||||
|
identity_sha256: "b".repeat(64),
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
execution: {
|
||||||
|
effective_world_state_fps: 11.84338,
|
||||||
|
world_state_completion_p95_ms: 47.940779,
|
||||||
|
detector_total_p95_ms: 21.19895,
|
||||||
|
gpu_utilization_p95_percent: 53,
|
||||||
|
gpu_memory_used_maximum_mib: 9718,
|
||||||
|
additional_inference_passes: 0,
|
||||||
|
},
|
||||||
|
metrics: {
|
||||||
|
selection: {
|
||||||
|
case_count: 24,
|
||||||
|
minimum_sequence_separation: 12,
|
||||||
|
selected_bucket_coverage: { person: 22, animal: 3 },
|
||||||
|
selected_class_counts: { person: 44, dog: 3 },
|
||||||
|
},
|
||||||
|
runtime: {
|
||||||
|
delivery_ratio: 1,
|
||||||
|
integrated_runtime_gate_passed: true,
|
||||||
|
operating_target_gate_passed: true,
|
||||||
|
},
|
||||||
|
native_tensor_parity: {
|
||||||
|
risk_detection_precision: 0.9887,
|
||||||
|
risk_detection_recall: 0.9831,
|
||||||
|
matched_mean_iou: 0.9882,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
acceptance: {
|
||||||
|
review_ready: true,
|
||||||
|
integrated_runtime_gate_passed: true,
|
||||||
|
independent_quality_evaluated: false,
|
||||||
|
semantic_candidate_accepted: false,
|
||||||
|
},
|
||||||
|
review: {
|
||||||
|
source_raster: { width: 800, height: 600 },
|
||||||
|
overlay: { client_rendered: true, toggleable: true },
|
||||||
|
cases: Array.from({ length: 24 }, (_, index) => {
|
||||||
|
const caseId = String(index * 20 + 12).padStart(6, "0");
|
||||||
|
return {
|
||||||
|
case_id: caseId,
|
||||||
|
sequence: Number(caseId),
|
||||||
|
frame_id: `frame-${caseId}`,
|
||||||
|
evidence_time_ns: 35_000_000_000 + index * 1_000_000,
|
||||||
|
image_url: `/review/${caseId}.jpg`,
|
||||||
|
media_type: "image/jpeg",
|
||||||
|
width: 800,
|
||||||
|
height: 600,
|
||||||
|
byte_length: 1000 + index,
|
||||||
|
sha256: String(index.toString(16)).padStart(64, "0"),
|
||||||
|
geometric_resampling: false,
|
||||||
|
selection_buckets: [index % 2 ? "person" : "animal"],
|
||||||
|
comparison: {
|
||||||
|
native_detection_count: 1,
|
||||||
|
legacy_704_detection_count: 1,
|
||||||
|
matched_detection_count_iou_at_least_0_5: 1,
|
||||||
|
},
|
||||||
|
proposals: [{
|
||||||
|
proposal_id: `proposal-${index}-0`,
|
||||||
|
class_name: index % 2 ? "person" : "dog",
|
||||||
|
risk_family: index % 2 ? "person" : "animal",
|
||||||
|
score: 0.75,
|
||||||
|
box_xyxy: [10, 20, 100, 200],
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
limitations: ["No independent route truth."],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test("M4.8Q parser accepts only the native 800x600 no-resampling review contract", async () => {
|
||||||
|
const result = await fetchM48TRiskQualityResult(resultId, {
|
||||||
|
fetcher: async () => response(payload()),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(result.variant, "native-risk-review");
|
||||||
|
assert.equal(result.review.cases.length, 24);
|
||||||
|
assert.equal(result.review.cases[0].width, 800);
|
||||||
|
assert.equal(result.review.cases[0].proposals[0].className, "dog");
|
||||||
|
assert.equal(result.execution.additionalInferencePasses, 0);
|
||||||
|
assert.equal(result.acceptance.independentQualityEvaluated, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("M4.8Q parser fails closed if raw-fisheye geometry is resampled", async () => {
|
||||||
|
const invalid = payload();
|
||||||
|
invalid.source.geometric_resampling = true;
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
fetchM48TRiskQualityResult(resultId, {
|
||||||
|
fetcher: async () => response(invalid),
|
||||||
|
}),
|
||||||
|
/source resampling/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("M4.8Q reuses the canonical image scene and viewer overlay toggle", async () => {
|
||||||
|
const source = await readFile(
|
||||||
|
new URL("../src/workspaces/laboratory/M48TRiskQualityVisual.tsx", import.meta.url),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.match(source, /<LaboratoryEvidenceViewer/);
|
||||||
|
assert.match(source, /<RecordedEvidenceImageScene/);
|
||||||
|
assert.match(source, /name=\{boxesVisible \? "eye-off" : "eye"\}/);
|
||||||
|
assert.match(source, /raw KB4 800×600 · resampling NO/);
|
||||||
|
assert.doesNotMatch(source, /<canvas/);
|
||||||
|
});
|
||||||
@@ -256,7 +256,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"catalog_id": "m48t-risk-quality-temporal",
|
"catalog_id": "m48t-risk-quality-temporal",
|
||||||
"evidence_id": "m48t-risk-quality-temporal-lab-ed5355fe0adb9b18942d75aff2362d79190b9e864f070ebe7a1c15fccbc0fbfb",
|
"evidence_id": "m48q-native-risk-quality-lab-e8961d4db8ffb751503b9646bc8eeebec6c80c948ce2f5b4fa5b89c471e673c1",
|
||||||
"signal": "progress",
|
"signal": "progress",
|
||||||
"lifecycle": "current",
|
"lifecycle": "current",
|
||||||
"visual_evidence": "available"
|
"visual_evidence": "available"
|
||||||
|
|||||||
@@ -1445,6 +1445,36 @@ configuration, dataset release, metrics and ONNX identity; only then is a
|
|||||||
candidate loaded through the existing Triton seam and measured by a new
|
candidate loaded through the existing Triton seam and measured by a new
|
||||||
append-only M4.8R run plus an independent validation gate.
|
append-only M4.8R run plus an independent validation gate.
|
||||||
|
|
||||||
|
### 2026-08-26 — M4.8Q native raw-fisheye risk review ready
|
||||||
|
|
||||||
|
The terminal phase of the existing `m48t-risk-quality-temporal` work is now the
|
||||||
|
content-addressed M4.8Q result
|
||||||
|
`m48q-native-risk-quality-lab-e8961d4db8ffb751503b9646bc8eeebec6c80c948ce2f5b4fa5b89c471e673c1`.
|
||||||
|
It replaces neither the historical M4.8T evidence nor either admitted M4 viewer.
|
||||||
|
The result projects `24` deterministic diagnostic cases into the existing M4.8
|
||||||
|
image-case review instrument, with source-pixel boxes rendered by the client and
|
||||||
|
an explicit clean-image toggle. The JPEG review derivatives retain the exact
|
||||||
|
`800×600` raster geometry; rectification, warp and geometric resampling are all
|
||||||
|
false. Boxes are not baked into the images.
|
||||||
|
|
||||||
|
Worker 006 selected the cases from the immutable full native reference-graph
|
||||||
|
ledger without another inference pass. The selection covers person, animal,
|
||||||
|
light-road-user, vehicle, low-confidence, fisheye-edge and both directions of
|
||||||
|
native-versus-legacy count divergence, with at least 12 source frames between
|
||||||
|
selected cases. The source graph delivered all `4,489/4,489` frames at
|
||||||
|
`11.84338 FPS`; detector p95 was `21.19895 ms`, world-state completion p95 was
|
||||||
|
`47.940779 ms`, GPU utilization p95 was `53%`, and maximum used GPU memory was
|
||||||
|
`9,718 MiB`. The isolated case-mining container was removed after execution and
|
||||||
|
the canonical Triton predecessor was verified healthy and unchanged.
|
||||||
|
|
||||||
|
This closes evidence preparation, not semantic quality. The cases are
|
||||||
|
diagnostic samples rather than independent route truth; native-versus-legacy
|
||||||
|
count differences are not a verdict because the legacy `704×704` path stretches
|
||||||
|
the raw 4:3 image. Accordingly `review_ready=true`, while ground truth,
|
||||||
|
candidate acceptance, production acceptance, navigation, safety, commands and
|
||||||
|
actuation authority remain false. The next action is operator adjudication in
|
||||||
|
the existing M4.8 review instrument.
|
||||||
|
|
||||||
## Implementation order
|
## Implementation order
|
||||||
|
|
||||||
The implementation sequence is intentionally strict:
|
The implementation sequence is intentionally strict:
|
||||||
|
|||||||
Reference in New Issue
Block a user