feat(perception): integrate vegetation policy review

This commit is contained in:
DCCONSTRUCTIONS
2026-08-28 11:22:00 +03:00
parent 30080c51aa
commit c4c2392c79
17 changed files with 2388 additions and 105 deletions
@@ -55,7 +55,9 @@ export interface VegetationVideoSemanticClass {
classId: number; classId: number;
label: string; label: string;
colorRgb: readonly [number, number, number]; colorRgb: readonly [number, number, number];
disposition: "prediction" | "undefined"; disposition: "labeled" | "ambiguous" | "prediction" | "undefined";
materialClass: string | null;
evidenceState: string | null;
} }
export interface VegetationRouteVideo { export interface VegetationRouteVideo {
@@ -67,8 +69,12 @@ export interface VegetationRouteVideo {
height: 600; height: 600;
centerCropXyxy: readonly [100, 0, 700, 600]; centerCropXyxy: readonly [100, 0, 700, 600];
outsideCropState: "undefined"; outsideCropState: "undefined";
viewKind: "fine-semantic-prediction" | "coarse-material-policy-review";
linkedTgsResultId: string | null;
taxonomy: readonly VegetationVideoSemanticClass[]; taxonomy: readonly VegetationVideoSemanticClass[];
aggregatePredictionPixels: readonly number[]; aggregatePredictionPixels: readonly number[];
policyPresets: Readonly<Record<string, Readonly<Record<string, string>>>> | null;
fusionMode: "synchronised-multilayer-review" | null;
} }
export interface VegetationShadowResult { export interface VegetationShadowResult {
@@ -257,6 +263,9 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
"vegetation.route_video.m47_reference_graph_result_id", "vegetation.route_video.m47_reference_graph_result_id",
); );
const baseM4ResultId = textValue(row.base_m4_result_id, "vegetation.route_video.base_m4_result_id"); const baseM4ResultId = textValue(row.base_m4_result_id, "vegetation.route_video.base_m4_result_id");
const viewKind = row.view_kind === undefined
? "fine-semantic-prediction"
: textValue(row.view_kind, "vegetation.route_video.view_kind");
if ( if (
!/^lab-v1-ravnoves-video-ddrnet-[a-f0-9]{64}$/.test(workerResultId) !/^lab-v1-ravnoves-video-ddrnet-[a-f0-9]{64}$/.test(workerResultId)
|| !/^m47-reference-graph-lab-[a-f0-9]{64}$/.test(m47ReferenceGraphResultId) || !/^m47-reference-graph-lab-[a-f0-9]{64}$/.test(m47ReferenceGraphResultId)
@@ -264,6 +273,15 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
) { ) {
throw new VegetationShadowContractError("vegetation.route_video: identity invalid."); throw new VegetationShadowContractError("vegetation.route_video: identity invalid.");
} }
if (viewKind !== "fine-semantic-prediction" && viewKind !== "coarse-material-policy-review") {
throw new VegetationShadowContractError("vegetation.route_video: view kind invalid.");
}
const linkedTgsResultId = viewKind === "coarse-material-policy-review"
? textValue(row.linked_tgs_result_id, "vegetation.route_video.linked_tgs_result_id")
: null;
if (linkedTgsResultId && !/^m49-tgs-full-shadow-[a-f0-9]{64}$/.test(linkedTgsResultId)) {
throw new VegetationShadowContractError("vegetation.route_video: TGS identity invalid.");
}
exact(row.frame_count, 4489, "vegetation.route_video.frame_count"); exact(row.frame_count, 4489, "vegetation.route_video.frame_count");
exact(row.width, 800, "vegetation.route_video.width"); exact(row.width, 800, "vegetation.route_video.width");
exact(row.height, 600, "vegetation.route_video.height"); exact(row.height, 600, "vegetation.route_video.height");
@@ -279,11 +297,9 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
throw new VegetationShadowContractError("vegetation.route_video: crop contract changed."); throw new VegetationShadowContractError("vegetation.route_video: crop contract changed.");
} }
const taxonomy = objectValue(row.taxonomy, "vegetation.route_video.taxonomy"); const taxonomy = objectValue(row.taxonomy, "vegetation.route_video.taxonomy");
exact( exact(taxonomy.schema_version, viewKind === "coarse-material-policy-review"
taxonomy.schema_version, ? "missioncore.lab-v1-terrain-policy-taxonomy/v1"
"missioncore.lab-v1-vegetation-taxonomy/v1", : "missioncore.lab-v1-vegetation-taxonomy/v1", "vegetation.route_video.taxonomy.schema");
"vegetation.route_video.taxonomy.schema",
);
const classes = arrayValue(taxonomy.classes, "vegetation.route_video.taxonomy.classes") const classes = arrayValue(taxonomy.classes, "vegetation.route_video.taxonomy.classes")
.map((value, expectedId): VegetationVideoSemanticClass => { .map((value, expectedId): VegetationVideoSemanticClass => {
const item = objectValue(value, `vegetation.route_video.taxonomy[${expectedId}]`); const item = objectValue(value, `vegetation.route_video.taxonomy[${expectedId}]`);
@@ -296,36 +312,78 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
if (color.length !== 3 || color.some((channel) => channel > 255)) { if (color.length !== 3 || color.some((channel) => channel > 255)) {
throw new VegetationShadowContractError("vegetation.route_video: taxonomy color invalid."); throw new VegetationShadowContractError("vegetation.route_video: taxonomy color invalid.");
} }
const disposition: VegetationVideoSemanticClass["disposition"] = expectedId === 0 const disposition = item.disposition;
? "undefined" if (
: "prediction"; disposition !== "labeled"
if (item.disposition !== disposition) { && disposition !== "ambiguous"
&& disposition !== "prediction"
&& disposition !== "undefined"
) {
throw new VegetationShadowContractError("vegetation.route_video: taxonomy disposition changed."); throw new VegetationShadowContractError("vegetation.route_video: taxonomy disposition changed.");
} }
if (
viewKind === "fine-semantic-prediction"
&& disposition !== (expectedId === 0 ? "undefined" : "prediction")
) {
throw new VegetationShadowContractError("vegetation.route_video: fine taxonomy disposition changed.");
}
const materialClass = item.material_class === null || item.material_class === undefined
? null
: textValue(item.material_class, `vegetation.route_video.material[${expectedId}]`);
const evidenceState = item.evidence_state === null || item.evidence_state === undefined
? null
: textValue(item.evidence_state, `vegetation.route_video.evidence[${expectedId}]`);
return { return {
classId, classId,
label: textValue(item.label, `vegetation.route_video.label[${expectedId}]`), label: textValue(item.label, `vegetation.route_video.label[${expectedId}]`),
colorRgb: color as unknown as readonly [number, number, number], colorRgb: color as unknown as readonly [number, number, number],
disposition, disposition,
materialClass,
evidenceState,
}; };
}); });
if (classes.length !== 64) { const expectedClassCount = viewKind === "coarse-material-policy-review" ? 9 : 64;
throw new VegetationShadowContractError("vegetation.route_video: taxonomy must contain 64 classes."); if (classes.length !== expectedClassCount) {
throw new VegetationShadowContractError("vegetation.route_video: taxonomy size changed.");
} }
const aggregatePredictionPixels = arrayValue( const aggregatePredictionPixels = arrayValue(
row.aggregate_prediction_pixels, row.aggregate_prediction_pixels,
"vegetation.route_video.aggregate_prediction_pixels", "vegetation.route_video.aggregate_prediction_pixels",
).map((value, index) => integerValue(value, `vegetation.route_video.pixels[${index}]`)); ).map((value, index) => integerValue(value, `vegetation.route_video.pixels[${index}]`));
if (aggregatePredictionPixels.length !== 64) { if (aggregatePredictionPixels.length !== expectedClassCount) {
throw new VegetationShadowContractError("vegetation.route_video: class accounting changed."); throw new VegetationShadowContractError("vegetation.route_video: class accounting changed.");
} }
const maskArchive = objectValue(row.mask_archive, "vegetation.route_video.mask_archive"); const maskArchive = objectValue(row.mask_archive, "vegetation.route_video.mask_archive");
exact(maskArchive.path, "video/ddrnet-semantic-masks.zip", "vegetation.route_video.mask_archive.path"); exact(maskArchive.path, viewKind === "coarse-material-policy-review"
? "video/coarse-material-policy-masks.zip"
: "video/ddrnet-semantic-masks.zip", "vegetation.route_video.mask_archive.path");
const archiveSha256 = textValue(maskArchive.sha256, "vegetation.route_video.mask_archive.sha256"); const archiveSha256 = textValue(maskArchive.sha256, "vegetation.route_video.mask_archive.sha256");
if (!SHA256.test(archiveSha256)) { if (!SHA256.test(archiveSha256)) {
throw new VegetationShadowContractError("vegetation.route_video: archive digest invalid."); throw new VegetationShadowContractError("vegetation.route_video: archive digest invalid.");
} }
integerValue(maskArchive.byte_length, "vegetation.route_video.mask_archive.byte_length"); integerValue(maskArchive.byte_length, "vegetation.route_video.mask_archive.byte_length");
let policyPresets: VegetationRouteVideo["policyPresets"] = null;
let fusionMode: VegetationRouteVideo["fusionMode"] = null;
if (viewKind === "coarse-material-policy-review") {
const policy = objectValue(row.policy, "vegetation.route_video.policy");
const presets = objectValue(policy.presets, "vegetation.route_video.policy.presets");
policyPresets = Object.fromEntries(Object.entries(presets).map(([presetId, rawRules]) => {
const rules = objectValue(rawRules, `vegetation.route_video.policy.${presetId}`);
return [presetId, Object.fromEntries(Object.entries(rules).map(([material, action]) => [
material,
textValue(action, `vegetation.route_video.policy.${presetId}.${material}`),
]))];
}));
const fusion = objectValue(row.fusion, "vegetation.route_video.fusion");
exact(fusion.pixel_raster_fusion, false, "vegetation.route_video.fusion.pixel_raster_fusion");
exact(fusion.camera_semantic_temporal_filter, "none", "vegetation.route_video.fusion.camera_filter");
exact(
fusion.mode,
"synchronised-multilayer-review",
"vegetation.route_video.fusion.mode",
);
fusionMode = "synchronised-multilayer-review";
}
return { return {
workerResultId, workerResultId,
m47ReferenceGraphResultId, m47ReferenceGraphResultId,
@@ -335,8 +393,12 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
height: 600, height: 600,
centerCropXyxy: [100, 0, 700, 600], centerCropXyxy: [100, 0, 700, 600],
outsideCropState: "undefined", outsideCropState: "undefined",
viewKind,
linkedTgsResultId,
taxonomy: classes, taxonomy: classes,
aggregatePredictionPixels, aggregatePredictionPixels,
policyPresets,
fusionMode,
}; };
} }
@@ -22,6 +22,7 @@ import {
import { import {
M4ReplayThreatVisual, M4ReplayThreatVisual,
type M4ReplayClassifiedSpatialFrame, type M4ReplayClassifiedSpatialFrame,
type M4ReplayThreatSemanticLayer,
} from "./M4ReplayThreatVisual"; } from "./M4ReplayThreatVisual";
const CLASSES: readonly RecordedEvidenceSemanticClass[] = [ const CLASSES: readonly RecordedEvidenceSemanticClass[] = [
@@ -42,7 +43,15 @@ function message(error: unknown): string {
: "Полный TGS spatial frame недоступен."; : "Полный TGS spatial frame недоступен.";
} }
export function M49TgsFullShadowEvidence({ result }: { result: M49TgsFullShadowResult }) { export function M49TgsFullShadowEvidence({
result,
semanticOverride,
evidenceLabel = "M49 · full TGS shadow",
}: {
result: M49TgsFullShadowResult;
semanticOverride?: M4ReplayThreatSemanticLayer;
evidenceLabel?: string;
}) {
const [activeSequence, setActiveSequence] = useState<number | null>(null); const [activeSequence, setActiveSequence] = useState<number | null>(null);
const [semantic, setSemantic] = useState<E47SemanticSlamResult | null>(null); const [semantic, setSemantic] = useState<E47SemanticSlamResult | null>(null);
const [semanticError, setSemanticError] = useState<string | null>(null); const [semanticError, setSemanticError] = useState<string | null>(null);
@@ -62,6 +71,7 @@ export function M49TgsFullShadowEvidence({ result }: { result: M49TgsFullShadowR
const controller = new AbortController(); const controller = new AbortController();
setSemantic(null); setSemantic(null);
setSemanticError(null); setSemanticError(null);
if (semanticOverride) return () => controller.abort();
void fetchE47SemanticSlamResult({ void fetchE47SemanticSlamResult({
resultId: result.source.linkedSemanticResultId, resultId: result.source.linkedSemanticResultId,
signal: controller.signal, signal: controller.signal,
@@ -77,7 +87,7 @@ export function M49TgsFullShadowEvidence({ result }: { result: M49TgsFullShadowR
if (!controller.signal.aborted) setSemanticError(message(caught)); if (!controller.signal.aborted) setSemanticError(message(caught));
}); });
return () => controller.abort(); return () => controller.abort();
}, [result.source.linkedSemanticResultId, result.source.linkedVisualResultId]); }, [result.source.linkedSemanticResultId, result.source.linkedVisualResultId, semanticOverride]);
useEffect(() => { useEffect(() => {
const controller = new AbortController(); const controller = new AbortController();
@@ -196,13 +206,13 @@ export function M49TgsFullShadowEvidence({ result }: { result: M49TgsFullShadowR
<> <>
<M4ReplayThreatVisual <M4ReplayThreatVisual
resultId={result.source.linkedVisualResultId} resultId={result.source.linkedVisualResultId}
semantic={semantic ? { semantic={semanticOverride ?? (semantic ? {
resultId: semantic.resultId, resultId: semantic.resultId,
taxonomy: semantic.taxonomy, taxonomy: semantic.taxonomy,
} : undefined} } : undefined)}
showReviewAnchorBoxes={false} showReviewAnchorBoxes={false}
reviewLabel="4 489 source-paced TGS frames" reviewLabel="4 489 source-paced TGS frames"
evidenceLabel="M49 · full TGS shadow" evidenceLabel={evidenceLabel}
initialSpatialMode="3d" initialSpatialMode="3d"
onActiveSequenceChange={handleSequenceChange} onActiveSequenceChange={handleSequenceChange}
classifiedSpatialLayer={{ classifiedSpatialLayer={{
@@ -217,7 +227,7 @@ export function M49TgsFullShadowEvidence({ result }: { result: M49TgsFullShadowR
replacePointCloud: false, replacePointCloud: false,
}} }}
/> />
{semanticError ? ( {!semanticOverride && semanticError ? (
<div className="m4-replay-threat-visual__pane-status" role="alert"> <div className="m4-replay-threat-visual__pane-status" role="alert">
Semantic overlay недоступен: {semanticError} Semantic overlay недоступен: {semanticError}
</div> </div>
@@ -378,12 +378,12 @@ export function M4ReplayThreatVisual({
); );
}, [frame, metadata.timeline, showReferenceMediaLayers, showStaticObstacles]); }, [frame, metadata.timeline, showReferenceMediaLayers, showStaticObstacles]);
const activeBoxes = useMemo( const activeBoxes = useMemo(
() => classifiedSpatialLayer || !showReferenceMediaLayers ? [] : [ () => !showReferenceMediaLayers ? [] : [
...boxes(frame?.cameraProposals ?? []), ...boxes(frame?.cameraProposals ?? []),
...staticObstacleBoxes, ...staticObstacleBoxes,
...reviewAnchorBoxes, ...reviewAnchorBoxes,
], ],
[classifiedSpatialLayer, frame, reviewAnchorBoxes, showReferenceMediaLayers, staticObstacleBoxes], [frame, reviewAnchorBoxes, showReferenceMediaLayers, staticObstacleBoxes],
); );
const semanticClasses = useMemo<readonly RecordedEvidenceSemanticClass[]>( const semanticClasses = useMemo<readonly RecordedEvidenceSemanticClass[]>(
() => semantic?.taxonomy.map((item) => ({ () => semantic?.taxonomy.map((item) => ({
@@ -1,3 +1,5 @@
import { useEffect, useState } from "react";
import { import {
LaboratoryEvidence, LaboratoryEvidence,
LaboratoryResultSummary, LaboratoryResultSummary,
@@ -8,11 +10,16 @@ import {
vegetationVideoMaskUrl, vegetationVideoMaskUrl,
type VegetationShadowResult, type VegetationShadowResult,
} from "../../core/laboratory/vegetationShadow"; } from "../../core/laboratory/vegetationShadow";
import {
fetchM49TgsFullShadowResult,
type M49TgsFullShadowResult,
} from "../../core/laboratory/m49TgsFullShadow";
import { import {
M48MaskComparisonVisual, M48MaskComparisonVisual,
type M48MaskComparisonCase, type M48MaskComparisonCase,
} from "./M48FailureAtlasVisual"; } from "./M48FailureAtlasVisual";
import { M4ReplayThreatVisual } from "./M4ReplayThreatVisual"; import { M4ReplayThreatVisual } from "./M4ReplayThreatVisual";
import { M49TgsFullShadowEvidence } from "./M49TgsFullShadowEvidence";
function decimal(value: number, digits = 1): string { function decimal(value: number, digits = 1): string {
return value.toLocaleString("ru-RU", { maximumFractionDigits: digits }); return value.toLocaleString("ru-RU", { maximumFractionDigits: digits });
@@ -49,6 +56,75 @@ function comparisonCases(result: VegetationShadowResult): readonly M48MaskCompar
}); });
} }
function VegetationRouteEvidence({ result }: { result: VegetationShadowResult }) {
const route = result.routeVideo!;
const [tgs, setTgs] = useState<M49TgsFullShadowResult | null>(null);
const [tgsError, setTgsError] = useState<string | null>(null);
useEffect(() => {
const controller = new AbortController();
setTgs(null);
setTgsError(null);
if (!route.linkedTgsResultId) return () => controller.abort();
void fetchM49TgsFullShadowResult(route.linkedTgsResultId, {
signal: controller.signal,
}).then((next) => {
if (controller.signal.aborted) return;
if (next.source.linkedVisualResultId !== route.baseM4ResultId) {
throw new Error("TGS и camera timeline имеют разные source identities.");
}
setTgs(next);
}).catch((caught: unknown) => {
if (!controller.signal.aborted) {
setTgsError(caught instanceof Error ? caught.message : "Sealed TGS недоступен.");
}
});
return () => controller.abort();
}, [route.baseM4ResultId, route.linkedTgsResultId]);
const semantic = {
resultId: route.workerResultId,
spatialResultId: null,
taxonomy: route.taxonomy,
maskUrl: (sequence: number) => vegetationVideoMaskUrl(result.resultId, sequence),
label: route.viewKind === "coarse-material-policy-review"
? "Coarse material evidence · recorded video"
: "DDRNet vegetation prediction · recorded video",
maskAriaLabel: route.viewKind === "coarse-material-policy-review"
? "Coarse material policy evidence"
: "DDRNet vegetation prediction",
} as const;
if (route.linkedTgsResultId && tgs) {
return (
<M49TgsFullShadowEvidence
result={tgs}
semanticOverride={semantic}
evidenceLabel="LAB V1 · MATERIAL + YOLOX + TGS"
/>
);
}
if (route.linkedTgsResultId && !tgsError) {
return <div className="m4-replay-threat-visual__pane-status" role="status">Открываем sealed TGS и coarse material timeline</div>;
}
return (
<>
<M4ReplayThreatVisual
resultId={route.baseM4ResultId}
evidenceLabel="LAB V1 · DDRNet"
showReferenceMediaLayers={route.viewKind === "coarse-material-policy-review"}
showSpatialOverlaySummary={false}
semantic={semantic}
/>
{tgsError ? (
<div className="m4-replay-threat-visual__pane-status" role="alert">
TGS слой недоступен: {tgsError}
</div>
) : null}
</>
);
}
export function VegetationShadowResultView({ export function VegetationShadowResultView({
rigLabel, rigLabel,
result, result,
@@ -68,10 +144,14 @@ export function VegetationShadowResultView({
<LaboratorySummary <LaboratorySummary
title="LAB V1 · готовые модели растительности" title="LAB V1 · готовые модели растительности"
description={result.routeVideo description={result.routeVideo
? "M4.8 сохраняет truth-backed сравнение моделей, а штатный M4.7 viewer показывает фактический DDRNet prediction на всей записи RAVNOVES00. Все 4489 масок запечатаны локально и открываются без Worker 006." ? result.routeVideo.viewKind === "coarse-material-policy-review"
? "M4.8 сохраняет truth-backed сравнение моделей, а штатный M4.7 синхронно показывает coarse material evidence, frozen YOLOX vetoes и causal TGS на всей записи RAVNOVES00. Все слои запечатаны локально и открываются без Worker 006."
: "M4.8 сохраняет truth-backed сравнение моделей, а штатный M4.7 viewer показывает фактический DDRNet prediction на всей записи RAVNOVES00. Все 4489 масок запечатаны локально и открываются без Worker 006."
: "Штатный M4.8-инструмент сравнивает две готовые fine-64 модели на полном GOOSE validation split и на 12 truth-backed hard cases, выбранных только по наличию нужной растительности. Sealed evidence открывается локально без Worker 006."} : "Штатный M4.8-инструмент сравнивает две готовые fine-64 модели на полном GOOSE validation split и на 12 truth-backed hard cases, выбранных только по наличию нужной растительности. Sealed evidence открывается локально без Worker 006."}
status={result.routeVideo status={result.routeVideo
? "DDRNet full-video prediction ready · route truth отсутствует" ? result.routeVideo.viewKind === "coarse-material-policy-review"
? "MULTILAYER POLICY REVIEW · commands OFF · route truth отсутствует"
: "DDRNet full-video prediction ready · route truth отсутствует"
: "Truth-backed model comparison · route transfer не принят"} : "Truth-backed model comparison · route transfer не принят"}
statusTone="warning" statusTone="warning"
facts={[ facts={[
@@ -80,15 +160,17 @@ export function VegetationShadowResultView({
{ label: "Кейсы", value: "трава · куст · ствол · крона · изгородь · лес · посевы" }, { label: "Кейсы", value: "трава · куст · ствол · крона · изгородь · лес · посевы" },
...(result.routeVideo ? [{ ...(result.routeVideo ? [{
label: "Видео", label: "Видео",
value: "RAVNOVES00 · 4489/4489 DDRNet masks · exact recorded sequence", value: result.routeVideo.viewKind === "coarse-material-policy-review"
? "RAVNOVES00 · 4489/4489 coarse masks + YOLOX + TGS · exact sequence"
: "RAVNOVES00 · 4489/4489 DDRNet masks · exact recorded sequence",
}] : []), }] : []),
{ label: "Authority", value: `${rigLabel} · MODEL QUALIFICATION ONLY · commands OFF` }, { label: "Authority", value: `${rigLabel} · MODEL QUALIFICATION ONLY · commands OFF` },
]} ]}
brief={{ brief={{
question: "Какие готовые веса лучше различают проезжаемую траву, кусты и стволы на размеченных off-road кадрах?", question: "Какие готовые веса лучше различают проезжаемую траву, кусты и стволы на размеченных off-road кадрах?",
approach: "Обе модели последовательно прогнаны в одном изолированном CUDA-runtime на 962 кадрах. 12 визуальных кейсов выбраны детерминированно по truth-поддержке восьми растительных классов; один M4.8 viewer показывает source, truth, prediction и material-error для выбранной модели.", approach: "Обе модели последовательно прогнаны в одном изолированном CUDA-runtime на 962 кадрах. 12 визуальных кейсов выбраны детерминированно по truth-поддержке восьми растительных классов; один M4.8 viewer показывает source, truth, prediction и material-error для выбранной модели.",
principalResult: `${selected.loadedModelName} лидирует по vegetation IoU: ${decimal(selected.vegetationMeanIouPercent, 2)}% против ${decimal(alternative.vegetationMeanIouPercent, 2)}%. ${result.routeVideo ? "Его фактическая temporal stability теперь видна на всех 4489 кадрах штатного recorded viewer." : "Ошибки по каждому типу проверяются в одном штатном инструменте."}`, principalResult: `${selected.loadedModelName} лидирует по vegetation IoU: ${decimal(selected.vegetationMeanIouPercent, 2)}% против ${decimal(alternative.vegetationMeanIouPercent, 2)}%. ${result.routeVideo?.viewKind === "coarse-material-policy-review" ? "Fine-64 prediction сведён к mission-neutral материалам; YOLOX и TGS сохраняют независимое veto." : result.routeVideo ? "Его фактическая temporal stability теперь видна на всех 4489 кадрах штатного recorded viewer." : "Ошибки по каждому типу проверяются в одном штатном инструменте."}`,
limitation: "GOOSE — внешний размеченный домен; RAVNOVES00 — наш fisheye, но без ручной truth-разметки. Full-video слой показывает prediction, а не доказывает правильность. Папоротник отдельным классом отсутствует.", limitation: "GOOSE — внешний размеченный домен; RAVNOVES00 — наш fisheye, но без ручной truth-разметки. Материалы — prediction, а не доказательство проходимости. TGS не проецируется в пиксели без отдельной принятой калибровки.",
}} }}
method={{ method={{
completeness: "complete", completeness: "complete",
@@ -120,32 +202,25 @@ export function VegetationShadowResultView({
{result.routeVideo ? ( {result.routeVideo ? (
<LaboratoryEvidence <LaboratoryEvidence
eyebrow="M4.7 · RAVNOVES00 FULL VIDEO" eyebrow="M4.7 · RAVNOVES00 FULL VIDEO"
title="DDRNet PREDICTION · 4489/4489 кадров · TRUTH для этой записи отсутствует" title={result.routeVideo.viewKind === "coarse-material-policy-review"
? "COARSE MATERIAL + YOLOX VETO + CAUSAL TGS · 4489/4489 · TRUTH отсутствует"
: "DDRNet PREDICTION · 4489/4489 кадров · TRUTH для этой записи отсутствует"}
kind="diagnostic-model" kind="diagnostic-model"
resizable resizable
> >
<M4ReplayThreatVisual <VegetationRouteEvidence result={result} />
resultId={result.routeVideo.baseM4ResultId}
evidenceLabel="LAB V1 · DDRNet"
showReferenceMediaLayers={false}
showSpatialOverlaySummary={false}
semantic={{
resultId: result.routeVideo.workerResultId,
spatialResultId: null,
taxonomy: result.routeVideo.taxonomy,
maskUrl: (sequence) => vegetationVideoMaskUrl(result.resultId, sequence),
label: "DDRNet vegetation prediction · recorded video",
maskAriaLabel: "DDRNet vegetation prediction",
}}
/>
</LaboratoryEvidence> </LaboratoryEvidence>
) : null} ) : null}
</> </>
)} )}
result={( result={(
<LaboratoryResultSummary <LaboratoryResultSummary
title="DDRNet — стартовые веса; перенос на ровер ещё не доказан" title={result.routeVideo?.viewKind === "coarse-material-policy-review"
status={`${selected.loadedModelName} выбран только как vegetation candidate`} ? "Слои собраны для визуального policy review; управление не авторизовано"
: "DDRNet — стартовые веса; перенос на ровер ещё не доказан"}
status={result.routeVideo?.viewKind === "coarse-material-policy-review"
? "Materials are advisory · YOLOX/TGS veto cannot be cleared"
: `${selected.loadedModelName} выбран только как vegetation candidate`}
statusTone="warning" statusTone="warning"
metrics={[ metrics={[
{ {
@@ -186,13 +261,17 @@ export function VegetationShadowResultView({
...(result.routeVideo ? [{ ...(result.routeVideo ? [{
label: "Route video", label: "Route video",
value: "4489/4489 masks", value: "4489/4489 masks",
hint: "DDRNet prediction · exact sequence · Worker-independent playback", hint: result.routeVideo.viewKind === "coarse-material-policy-review"
? "9 coarse states · YOLOX + causal TGS · Worker-independent playback"
: "DDRNet prediction · exact sequence · Worker-independent playback",
}] : []), }] : []),
]} ]}
conclusion={{ conclusion={{
proved: "Обе официальные fine-64 модели воспроизводимо запускаются на Worker 006; DDRNet лучше по aggregate vegetation IoU. Truth-backed hard cases прямо показывают траву, кусты и стволы, а не случайные автомобили и здания.", proved: "Обе официальные fine-64 модели воспроизводимо запускаются на Worker 006; DDRNet лучше по aggregate vegetation IoU. Truth-backed hard cases прямо показывают траву, кусты и стволы, а не случайные автомобили и здания.",
notProved: "Не доказаны accuracy на нашем fisheye-домене, папоротник как отдельный материал, collision safety и physical-live поведение ровера. Видео позволяет увидеть temporal stability, но без truth не превращает её в метрику качества.", notProved: "Не доказаны accuracy на нашем fisheye-домене, папоротник как отдельный материал, collision safety и physical-live поведение ровера. Видео позволяет увидеть temporal stability, но без truth не превращает её в метрику качества.",
decision: "Смотреть полный prediction на видео и собирать конкретные temporal/domain failure cases. DDRNet остаётся diagnostic candidate; LiDAR/TGS fail-closed геометрию не ослаблять.", decision: result.routeVideo?.viewKind === "coarse-material-policy-review"
? "На одном M4.7 проверить ложные LOW GRASS/HIGH GRASS кандидаты против YOLOX и TGS. До truth-кейсов и integrated load этот слой не подключать к planner/actuation."
: "Смотреть полный prediction на видео и собирать конкретные temporal/domain failure cases. DDRNet остаётся diagnostic candidate; LiDAR/TGS fail-closed геометрию не ослаблять.",
}} }}
/> />
)} )}
@@ -108,7 +108,9 @@ test("M4.9T5 viewer prefers autonomous chunks and keeps a sealed legacy fallback
assert.doesNotMatch(source, /centersXyM\.map\(/); assert.doesNotMatch(source, /centersXyM\.map\(/);
assert.match(source, /fetchE47SemanticSlamResult/); assert.match(source, /fetchE47SemanticSlamResult/);
assert.match(source, /next\.baseM4ResultId !== result\.source\.linkedVisualResultId/); assert.match(source, /next\.baseM4ResultId !== result\.source\.linkedVisualResultId/);
assert.match(source, /semantic=\{semantic \? \{/); assert.match(source, /semantic=\{semanticOverride \?\? \(semantic \? \{/);
assert.match(source, /semanticOverride/);
assert.doesNotMatch(visual, /classifiedSpatialLayer \|\| !showReferenceMediaLayers \? \[\]/);
assert.match( assert.match(
visual, visual,
/classifiedSpatialFrame\s*&&\s*classifiedSpatialFrame\.sampleAvailable !== false/, /classifiedSpatialFrame\s*&&\s*classifiedSpatialFrame\.sampleAvailable !== false/,
@@ -104,45 +104,89 @@ function routeVideo() {
}; };
} }
function coarseRouteVideo() {
return {
...routeVideo(),
view_kind: "coarse-material-policy-review",
linked_tgs_result_id: `m49-tgs-full-shadow-${"2".repeat(64)}`,
taxonomy: {
schema_version: "missioncore.lab-v1-terrain-policy-taxonomy/v1",
classes: Array.from({ length: 9 }, (_, classId) => ({
class_id: classId,
label: `policy-${classId}`,
color_rgb: [classId, classId, classId],
disposition: classId === 0 ? "ambiguous" : "prediction",
material_class: classId === 0 ? null : "grass",
evidence_state: classId === 0 ? "UNOBSERVED" : "SUPPORTED_GROUND",
})),
},
aggregate_prediction_pixels: Array(9).fill(0),
mask_archive: {
path: "video/coarse-material-policy-masks.zip",
sha256: "8".repeat(64),
byte_length: 2048,
},
policy: {
presets: {
urban: { grass: "NO_GO" },
rural: { grass: "HIGH_COST" },
offroad: { grass: "HIGH_COST" },
},
},
fusion: {
mode: "synchronised-multilayer-review",
pixel_raster_fusion: false,
camera_semantic_temporal_filter: "none",
},
};
}
function labPayload(route = routeVideo()) {
return {
schema_version: "missioncore.lab-v1-vegetation-shadow/v1",
result_id: resultId,
created_at_utc: "2026-08-27T20:00:00Z",
status: "visual-shadow-ready-policy-not-authorized",
ground_truth: false,
identity: { selected_candidate: "ddrnet" },
metrics: {
candidates: {
ddrnet: candidate("ddrnet", 0.64),
ppliteseg: candidate("ppliteseg", 0.61),
},
},
decision: {
selected_candidate: "ddrnet",
visual_shadow_ready: true,
mission_policy_ready_for_configuration: true,
navigation_accepted: false,
production_accepted: false,
},
limitations: ["shadow only"],
authority: {
commands_enabled: false,
navigation_or_safety_accepted: false,
actuation_accepted: false,
camera_semantics_can_clear_rigid_geometry: false,
},
catalogs: {
goose: Array.from({ length: 12 }, (_, index) => visualCase("goose", index)),
ravnoves: [],
},
route_video: route,
access: "read-only",
};
}
test("vegetation LAB keeps autonomous assets and fail-closed authority", async () => { test("vegetation LAB keeps autonomous assets and fail-closed authority", async () => {
let requestedUrl = ""; let requestedUrl = "";
const result = await fetchVegetationShadowResult(resultId, { const result = await fetchVegetationShadowResult(resultId, {
fetcher: async (url) => { fetcher: async (url) => {
requestedUrl = String(url); requestedUrl = String(url);
return new Response(JSON.stringify({ return new Response(JSON.stringify(labPayload()), {
schema_version: "missioncore.lab-v1-vegetation-shadow/v1", status: 200,
result_id: resultId, headers: { "Content-Type": "application/json" },
created_at_utc: "2026-08-27T20:00:00Z", });
status: "visual-shadow-ready-policy-not-authorized",
ground_truth: false,
identity: { selected_candidate: "ddrnet" },
metrics: {
candidates: {
ddrnet: candidate("ddrnet", 0.64),
ppliteseg: candidate("ppliteseg", 0.61),
},
},
decision: {
selected_candidate: "ddrnet",
visual_shadow_ready: true,
mission_policy_ready_for_configuration: true,
navigation_accepted: false,
production_accepted: false,
},
limitations: ["shadow only"],
authority: {
commands_enabled: false,
navigation_or_safety_accepted: false,
actuation_accepted: false,
camera_semantics_can_clear_rigid_geometry: false,
},
catalogs: {
goose: Array.from({ length: 12 }, (_, index) => visualCase("goose", index)),
ravnoves: [],
},
route_video: routeVideo(),
access: "read-only",
}), { status: 200, headers: { "Content-Type": "application/json" } });
}, },
}); });
assert.equal( assert.equal(
@@ -154,6 +198,8 @@ test("vegetation LAB keeps autonomous assets and fail-closed authority", async (
assert.equal(result.routeCases.length, 0); assert.equal(result.routeCases.length, 0);
assert.equal(result.validationCases.length, 12); assert.equal(result.validationCases.length, 12);
assert.equal(result.routeVideo.frameCount, 4489); assert.equal(result.routeVideo.frameCount, 4489);
assert.equal(result.routeVideo.viewKind, "fine-semantic-prediction");
assert.equal(result.routeVideo.linkedTgsResultId, null);
assert.equal(result.routeVideo.taxonomy[0].disposition, "undefined"); assert.equal(result.routeVideo.taxonomy[0].disposition, "undefined");
assert.equal(result.validationCases[0].focus.className, "high_grass"); assert.equal(result.validationCases[0].focus.className, "high_grass");
assert.match(result.validationCases[0].assets.ddrnet_error, /\/assets\/visual\/goose\//); assert.match(result.validationCases[0].assets.ddrnet_error, /\/assets\/visual\/goose\//);
@@ -165,6 +211,21 @@ test("vegetation LAB keeps autonomous assets and fail-closed authority", async (
}); });
}); });
test("vegetation LAB parses coarse material policy and sealed TGS binding", async () => {
const result = await fetchVegetationShadowResult(resultId, {
fetcher: async () => new Response(JSON.stringify(labPayload(coarseRouteVideo())), {
status: 200,
headers: { "Content-Type": "application/json" },
}),
});
assert.equal(result.routeVideo.viewKind, "coarse-material-policy-review");
assert.match(result.routeVideo.linkedTgsResultId, /^m49-tgs-full-shadow-/);
assert.equal(result.routeVideo.taxonomy.length, 9);
assert.equal(result.routeVideo.taxonomy[0].evidenceState, "UNOBSERVED");
assert.equal(result.routeVideo.policyPresets.urban.grass, "NO_GO");
assert.equal(result.routeVideo.fusionMode, "synchronised-multilayer-review");
});
test("vegetation LAB reuses the admitted M4.8 and M4.7 instruments", async () => { test("vegetation LAB reuses the admitted M4.8 and M4.7 instruments", async () => {
const resultSource = await readFile( const resultSource = await readFile(
new URL("../src/workspaces/laboratory/VegetationShadowResult.tsx", import.meta.url), new URL("../src/workspaces/laboratory/VegetationShadowResult.tsx", import.meta.url),
@@ -172,8 +233,10 @@ test("vegetation LAB reuses the admitted M4.8 and M4.7 instruments", async () =>
); );
assert.match(resultSource, /M48MaskComparisonVisual/); assert.match(resultSource, /M48MaskComparisonVisual/);
assert.match(resultSource, /M4ReplayThreatVisual/); assert.match(resultSource, /M4ReplayThreatVisual/);
assert.match(resultSource, /M49TgsFullShadowEvidence/);
assert.match(resultSource, /semanticOverride/);
assert.equal(resultSource.match(/<LaboratoryEvidence\b/g)?.length, 2); assert.equal(resultSource.match(/<LaboratoryEvidence\b/g)?.length, 2);
assert.match(resultSource, /showReferenceMediaLayers=\{false\}/); assert.match(resultSource, /linkedTgsResultId/);
assert.doesNotMatch(resultSource, /VegetationRouteVisual|urban\/rural\/off-road presets/); assert.doesNotMatch(resultSource, /VegetationRouteVisual|urban\/rural\/off-road presets/);
await assert.rejects( await assert.rejects(
access(new URL("../src/workspaces/laboratory/VegetationShadowVisual.tsx", import.meta.url)), access(new URL("../src/workspaces/laboratory/VegetationShadowVisual.tsx", import.meta.url)),
@@ -0,0 +1,68 @@
{
"schema_version": "missioncore.lab-v1-vegetation-integrated-shadow-profile/v1",
"profile_id": "lab-v1-ravnoves00-ddrnet-m49-integrated-shadow/v1",
"source": {
"source_id": "RAVNOVES00",
"expected_timeline_frames": 4489,
"requested_source_rate_hz": 12.0,
"shared_start_barrier": true,
"ground_truth_available": false
},
"stages": {
"m49_graph_tgs": {
"profile": "m49-tgs-integrated-graph-shadow-v1.json",
"profile_sha256": "b61e018b2d04eec58802e2d4186ce7a3dd3a15b254db106b57b609e903eeef80",
"candidate": "frozen-native-rf-detr-plus-cpu-tgs",
"parameters_unchanged": true
},
"vegetation": {
"candidate_id": "ddrnet_39-goose-fine-64",
"candidate_key": "ddrnet",
"checkpoint_sha256": "b99c2838051bcd7b092fd3970aa62a77d5c0bbb809c9b9afb2ff4b0ebdaa4ee6",
"config_sha256": "96a427a8baae387b827ec9c0bf7ca42e3fb9114b8fa9a8671bbc9d10877670b9",
"policy_sha256": "b75c4ac841d7b4bcc57f7a9c8417ca2317d8ecfa499e72a9af8a8591a2ec0d35",
"provider_map_sha256": "f2b69046b6a740fd9532d2d88e7fabae7c20fb662f783c9502adc9026406f352",
"container_image": "ndc/mission-core-lab-v1-goose:sg3.2.0-cu117-v1",
"container_image_id": "sha256:591cb382c099eeb05e7ec16e2371e0b2da54d2bb5c49ec0f4ac88dbf72b0f0cd",
"semantic_output_persisted": false,
"one_heavy_vegetation_candidate_at_a_time": true
}
},
"acceptance": {
"minimum_graph_world_state_fps": 11.209069,
"minimum_vegetation_fps": 11.209069,
"maximum_vegetation_completion_p95_ms": 125.0,
"maximum_combined_output_age_p99_ms": 125.0,
"capacity_drop_count_max": 0,
"unaccounted_frame_count_max": 0
},
"telemetry": {
"sample_interval_seconds": 1.0,
"required_roles": [
"graph",
"triton",
"tgs",
"vegetation"
]
},
"invariants": {
"raw_fisheye_immutable": true,
"reference_graph_parameters_unchanged": true,
"tgs_parameters_unchanged": true,
"ddrnet_parameters_unchanged": true,
"ppliteseg_concurrent_run_allowed": false,
"camera_semantics_can_clear_rigid_geometry": false,
"canonical_triton_mutation_allowed": false,
"gauss_or_playcanvas_in_scope": false
},
"authority": {
"visual_quality_accepted": false,
"route_truth_available": false,
"traversability_accepted": false,
"physical_free_space_accepted": false,
"commands_enabled": false,
"actuation_allowed": false,
"navigation_or_safety_accepted": false,
"production_accepted": false
}
}
@@ -12,6 +12,10 @@ param(
[string]$RunId, [string]$RunId,
[ValidateRange(1.0, 120.0)] [ValidateRange(1.0, 120.0)]
[double]$SourceRateHz = 12.0, [double]$SourceRateHz = 12.0,
[switch]$VegetationLoadGate,
[string]$VegetationAssetRoot = (
"D:\NDC_MISSIONCORE\datasets\vegetation-v1\observed-2026-08-27"
),
[string]$OutputRoot = ( [string]$OutputRoot = (
"D:\NDC_MISSIONCORE\runtime\results\m49-tgs-integrated-graph-shadow" "D:\NDC_MISSIONCORE\runtime\results\m49-tgs-integrated-graph-shadow"
) )
@@ -23,6 +27,8 @@ $TravelImageTag = "ndc/mission-core-m49-t3-travel:20260826"
$TravelImageId = "sha256:7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f" $TravelImageId = "sha256:7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f"
$ParityImageTag = "ndc-mission-core-m48t-upstream-parity:1.9.4-cu130" $ParityImageTag = "ndc-mission-core-m48t-upstream-parity:1.9.4-cu130"
$ParityImageId = "sha256:ceb13548617e4bd3f619766bfdff00af3fa5160946b367828da6d2233dcdcba0" $ParityImageId = "sha256:ceb13548617e4bd3f619766bfdff00af3fa5160946b367828da6d2233dcdcba0"
$VegetationImageTag = "ndc/mission-core-lab-v1-goose:sg3.2.0-cu117-v1"
$VegetationImageId = "sha256:591cb382c099eeb05e7ec16e2371e0b2da54d2bb5c49ec0f4ac88dbf72b0f0cd"
$RuntimeImage = ( $RuntimeImage = (
"nvcr.io/nvidia/tritonserver:26.06-py3@" + "nvcr.io/nvidia/tritonserver:26.06-py3@" +
"sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794" "sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
@@ -98,12 +104,20 @@ function Wait-Healthy([string]$Name) {
function Wait-SharedReady( function Wait-SharedReady(
[string]$GraphReady, [string]$GraphReady,
[string]$TgsReady, [string]$TgsReady,
[string]$VegetationReady,
[string]$GraphName, [string]$GraphName,
[string]$TgsName [string]$TgsName,
[string]$VegetationName
) { ) {
$deadline = [DateTimeOffset]::UtcNow.AddMinutes(10) $deadline = [DateTimeOffset]::UtcNow.AddMinutes(10)
while (-not ((Test-Path -LiteralPath $GraphReady) -and (Test-Path -LiteralPath $TgsReady))) { $requiredFiles = @($GraphReady, $TgsReady)
foreach ($name in @($GraphName, $TgsName)) { $requiredContainers = @($GraphName, $TgsName)
if (-not [string]::IsNullOrWhiteSpace($VegetationReady)) {
$requiredFiles += $VegetationReady
$requiredContainers += $VegetationName
}
while ($requiredFiles.Where({ -not (Test-Path -LiteralPath $_) }).Count -gt 0) {
foreach ($name in $requiredContainers) {
$container = Get-Container $name $container = Get-Container $name
if (-not $container.State.Running) { if (-not $container.State.Running) {
& docker logs $name & docker logs $name
@@ -128,15 +142,25 @@ $runCandidate = Join-Path $output $RunId
if (Test-Path -LiteralPath $runCandidate) { throw "M49 integrated output already exists" } if (Test-Path -LiteralPath $runCandidate) { throw "M49 integrated output already exists" }
$null = New-Item -ItemType Directory -Path $runCandidate $null = New-Item -ItemType Directory -Path $runCandidate
$runOutput = Resolve-DDirectory $runCandidate "M49 integrated run output" $false $runOutput = Resolve-DDirectory $runCandidate "M49 integrated run output" $false
foreach ($directory in @("bin", "control", "graph", "tgs")) { foreach ($directory in @("bin", "control", "graph", "tgs", "vegetation")) {
$null = New-Item -ItemType Directory -Path (Join-Path $runOutput $directory) $null = New-Item -ItemType Directory -Path (Join-Path $runOutput $directory)
} }
$releaseDocument = Get-Content -LiteralPath (Join-Path $payload "release.json") -Raw | ConvertFrom-Json $releaseDocument = Get-Content -LiteralPath (Join-Path $payload "release.json") -Raw | ConvertFrom-Json
$expectedReleaseSchema = if ($VegetationLoadGate) {
"missioncore.lab-v1-vegetation-integrated-worker-release/v1"
} else {
"missioncore.m49-tgs-integrated-graph-worker-release/v1"
}
$expectedTransition = if ($VegetationLoadGate) {
"lab-v1-vegetation-m49-integrated-shadow/v1"
} else {
"m49-tgs-native-risk-integrated-shadow/v1"
}
if ( if (
$releaseDocument.schema_version -cne "missioncore.m49-tgs-integrated-graph-worker-release/v1" -or $releaseDocument.schema_version -cne $expectedReleaseSchema -or
$releaseDocument.worker_id -cne "worker-006" -or $releaseDocument.worker_id -cne "worker-006" -or
$releaseDocument.transition -cne "m49-tgs-native-risk-integrated-shadow/v1" $releaseDocument.transition -cne $expectedTransition
) { throw "M49 integrated release contract changed" } ) { throw "M49 integrated release contract changed" }
foreach ($property in $releaseDocument.files.PSObject.Properties) { foreach ($property in $releaseDocument.files.PSObject.Properties) {
$path = Join-Path $payload $property.Name $path = Join-Path $payload $property.Name
@@ -146,6 +170,9 @@ foreach ($property in $releaseDocument.files.PSObject.Properties) {
} }
$wheelSha256 = [string]$releaseDocument.files."nodedc_mission_core-0.1.0-py3-none-any.whl".sha256 $wheelSha256 = [string]$releaseDocument.files."nodedc_mission_core-0.1.0-py3-none-any.whl".sha256
$runnerSha256 = [string]$releaseDocument.files."run_m48s_reference_graph_shadow_worker.py".sha256 $runnerSha256 = [string]$releaseDocument.files."run_m48s_reference_graph_shadow_worker.py".sha256
$vegetationRunnerSha256 = if ($VegetationLoadGate) {
[string]$releaseDocument.files."run_vegetation_integrated_load.py".sha256
} else { "" }
$source = [ordered]@{ $source = [ordered]@{
CameraIndex = ( CameraIndex = (
@@ -179,6 +206,23 @@ if ((Get-Sha256 $source.SourcePack) -cne [string]$releaseDocument.source_pack_sh
throw "RAVNOVES00 source pack digest changed" throw "RAVNOVES00 source pack digest changed"
} }
$vegetation = $null
if ($VegetationLoadGate) {
$vegetationRoot = Resolve-DDirectory $VegetationAssetRoot "vegetation asset root" $false
$vegetation = [ordered]@{
Dataset = Resolve-DDirectory (
(Join-Path $vegetationRoot "goose-2d\validation")
) "GOOSE validation root" $false
Checkpoint = Resolve-DFile (
(Join-Path $vegetationRoot "models\goose\ddrnet_class_512.pth")
) "DDRNet checkpoint"
}
if (
(Get-Sha256 $vegetation.Checkpoint) -cne
"b99c2838051bcd7b092fd3970aa62a77d5c0bbb809c9b9afb2ff4b0ebdaa4ee6"
) { throw "DDRNet checkpoint SHA-256 changed" }
}
$nativeConfig = Resolve-DFile ( $nativeConfig = Resolve-DFile (
(Join-Path $payload "rf_detr_large_native_kb4_config.pbtxt") (Join-Path $payload "rf_detr_large_native_kb4_config.pbtxt")
) "native RF-DETR config" ) "native RF-DETR config"
@@ -207,12 +251,17 @@ $pillow = Resolve-DDirectory (
Assert-Image $TravelImageTag $TravelImageId Assert-Image $TravelImageTag $TravelImageId
Assert-Image $ParityImageTag $ParityImageId Assert-Image $ParityImageTag $ParityImageId
if ($VegetationLoadGate) { Assert-Image $VegetationImageTag $VegetationImageId }
& docker image inspect $RuntimeImage *> $null & docker image inspect $RuntimeImage *> $null
Assert-LastExitCode "pinned runtime image inspection" Assert-LastExitCode "pinned runtime image inspection"
$os = Get-CimInstance Win32_OperatingSystem $os = Get-CimInstance Win32_OperatingSystem
$freeMemoryGiB = [double]$os.FreePhysicalMemory / 1MB $freeMemoryGiB = [double]$os.FreePhysicalMemory / 1MB
if ($freeMemoryGiB -lt 24.0) { $requiredMemoryGiB = if ($VegetationLoadGate) { 32.0 } else { 24.0 }
throw ("M49 integrated shadow requires 24 GiB free memory; observed {0:N2} GiB" -f $freeMemoryGiB) if ($freeMemoryGiB -lt $requiredMemoryGiB) {
throw (
"M49 integrated shadow requires {0:N0} GiB free memory; observed {1:N2} GiB" -f
$requiredMemoryGiB, $freeMemoryGiB
)
} }
$canonicalBefore = Get-Container "ndc-mission-core-triton" $canonicalBefore = Get-Container "ndc-mission-core-triton"
if (-not $canonicalBefore.State.Running -or $canonicalBefore.State.Health.Status -cne "healthy") { if (-not $canonicalBefore.State.Running -or $canonicalBefore.State.Health.Status -cne "healthy") {
@@ -225,9 +274,12 @@ $compileName = "ndc-mission-core-m49-integrated-compile-$RunId"
$tritonName = "ndc-mission-core-m49-integrated-triton-$RunId" $tritonName = "ndc-mission-core-m49-integrated-triton-$RunId"
$graphName = "ndc-mission-core-m49-integrated-graph-$RunId" $graphName = "ndc-mission-core-m49-integrated-graph-$RunId"
$tgsName = "ndc-mission-core-m49-integrated-tgs-$RunId" $tgsName = "ndc-mission-core-m49-integrated-tgs-$RunId"
$vegetationName = "ndc-mission-core-m49-integrated-vegetation-$RunId"
$analyzeName = "ndc-mission-core-m49-integrated-analyze-$RunId" $analyzeName = "ndc-mission-core-m49-integrated-analyze-$RunId"
$evidenceName = "ndc-mission-core-m49-integrated-evidence-$RunId" $evidenceName = "ndc-mission-core-m49-integrated-evidence-$RunId"
$vegetationEvidenceName = "ndc-mission-core-m49-integrated-vegetation-evidence-$RunId"
$containers = @($prepareName, $compileName, $tritonName, $graphName, $tgsName, $analyzeName, $evidenceName) $containers = @($prepareName, $compileName, $tritonName, $graphName, $tgsName, $analyzeName, $evidenceName)
if ($VegetationLoadGate) { $containers += @($vegetationName, $vegetationEvidenceName) }
foreach ($name in $containers) { foreach ($name in $containers) {
if (& docker ps -a --format "{{.Names}}" --filter "name=^/$name$") { if (& docker ps -a --format "{{.Names}}" --filter "name=^/$name$") {
throw "M49 integrated container name already exists: $name" throw "M49 integrated container name already exists: $name"
@@ -236,6 +288,24 @@ foreach ($name in $containers) {
$started = [DateTimeOffset]::UtcNow $started = [DateTimeOffset]::UtcNow
try { try {
if ($VegetationLoadGate) {
$vegetationFrames = Join-Path $runOutput "vegetation\input-frames"
$null = New-Item -ItemType Directory -Path $vegetationFrames
& ffmpeg -hide_banner -loglevel error -i $source.Video -map 0:v:0 -fps_mode passthrough (
Join-Path $vegetationFrames "frame-%06d.png"
)
Assert-LastExitCode "RAVNOVES full-video frame extraction"
$extractedFrames = @(
Get-ChildItem -LiteralPath $vegetationFrames -File -Filter "frame-*.png" |
Sort-Object Name
)
if (
$extractedFrames.Count -ne 4489 -or
$extractedFrames[0].Name -cne "frame-000001.png" -or
$extractedFrames[-1].Name -cne "frame-004489.png"
) { throw "RAVNOVES full-video frame sequence changed" }
}
& docker run --rm --name $prepareName --network none --cpus 8 --memory 16g ` & docker run --rm --name $prepareName --network none --cpus 8 --memory 16g `
--entrypoint python3 ` --entrypoint python3 `
--volume ((Convert-ToDockerPath $source.SourcePack) + ":/source/lidar-pack.npz:ro") ` --volume ((Convert-ToDockerPath $source.SourcePack) + ":/source/lidar-pack.npz:ro") `
@@ -332,24 +402,71 @@ try {
$TravelImageTag /release/run_tgs_integrated_shadow.sh *> $null $TravelImageTag /release/run_tgs_integrated_shadow.sh *> $null
Assert-LastExitCode "M49 integrated TGS creation" Assert-LastExitCode "M49 integrated TGS creation"
if ($VegetationLoadGate) {
$dockerVegetationDataset = Convert-ToDockerPath $vegetation.Dataset
$dockerVegetationCheckpoint = Convert-ToDockerPath $vegetation.Checkpoint
& docker create --name $vegetationName --network none --cpus 8 --memory 10g `
--gpus all --read-only --security-opt "no-new-privileges:true" --cap-drop ALL `
--pids-limit 512 --tmpfs "/tmp:rw,noexec,nosuid,size=2g" `
-e "HOME=/tmp" `
--entrypoint conda `
--volume ($dockerRelease + ":/release:ro") `
--volume ($dockerRun + ":/shared:rw") `
--volume ($dockerVegetationDataset + ":/data/goose:ro") `
--volume ($dockerVegetationCheckpoint + ":/models/candidate.pth:ro") `
$VegetationImageTag run --no-capture-output --name goose python `
/release/run_vegetation_integrated_load.py `
--config /release/lab-v1-goose-vegetation-benchmark-v1.json `
--policy /release/lab-v1-vegetation-mission-policy-v1.json `
--provider-map /release/lab-v1-vegetation-provider-label-map-v1.json `
--checkpoint /models/candidate.pth `
--dataset-root /data/goose `
--frames-root /shared/vegetation/input-frames `
--source-rate-hz $rate `
--minimum-effective-fps 11.209069 `
--maximum-completion-p95-ms 125.0 `
--shared-start-ready-file /shared/control/vegetation.ready `
--shared-start-file /shared/control/start.signal `
--frame-ledger /shared/vegetation/frames.jsonl `
--output /shared/vegetation/result.json `
--release-sha256 $ExpectedArtifactSha256 *> $null
Assert-LastExitCode "M49 integrated vegetation creation"
}
& docker start $graphName *> $null & docker start $graphName *> $null
Assert-LastExitCode "M49 integrated graph start" Assert-LastExitCode "M49 integrated graph start"
& docker start $tgsName *> $null & docker start $tgsName *> $null
Assert-LastExitCode "M49 integrated TGS start" Assert-LastExitCode "M49 integrated TGS start"
if ($VegetationLoadGate) {
& docker start $vegetationName *> $null
Assert-LastExitCode "M49 integrated vegetation start"
}
$graphReady = Join-Path $runOutput "control\graph.ready" $graphReady = Join-Path $runOutput "control\graph.ready"
$tgsReady = Join-Path $runOutput "control\tgs.ready" $tgsReady = Join-Path $runOutput "control\tgs.ready"
Wait-SharedReady $graphReady $tgsReady $graphName $tgsName $vegetationReady = if ($VegetationLoadGate) {
Join-Path $runOutput "control\vegetation.ready"
} else { "" }
Wait-SharedReady $graphReady $tgsReady $vegetationReady $graphName $tgsName $vegetationName
[DateTimeOffset]::UtcNow.ToString("o") | Set-Content -LiteralPath ( [DateTimeOffset]::UtcNow.ToString("o") | Set-Content -LiteralPath (
Join-Path $runOutput "control\start.signal" Join-Path $runOutput "control\start.signal"
) -Encoding utf8 ) -Encoding utf8
$telemetryPath = Join-Path $runOutput "container-telemetry.jsonl" $telemetryPath = Join-Path $runOutput "container-telemetry.jsonl"
$m49TelemetryPath = if ($VegetationLoadGate) {
Join-Path $runOutput "m49-container-telemetry.jsonl"
} else { $telemetryPath }
while ($true) { while ($true) {
$graphState = Get-Container $graphName $graphState = Get-Container $graphName
$tgsState = Get-Container $tgsName $tgsState = Get-Container $tgsName
$vegetationState = if ($VegetationLoadGate) {
Get-Container $vegetationName
} else { $null }
$running = @() $running = @()
if ($graphState.State.Running) { $running += $graphName } if ($graphState.State.Running) { $running += $graphName }
if ($tgsState.State.Running) { $running += $tgsName } if ($tgsState.State.Running) { $running += $tgsName }
if ($VegetationLoadGate -and $vegetationState.State.Running) {
$running += $vegetationName
}
if ((Get-Container $tritonName).State.Running) { $running += $tritonName } if ((Get-Container $tritonName).State.Running) { $running += $tritonName }
if ($running.Count -gt 0) { if ($running.Count -gt 0) {
$stats = @((& docker stats --no-stream --format "{{json .}}" @running)) $stats = @((& docker stats --no-stream --format "{{json .}}" @running))
@@ -362,10 +479,12 @@ try {
"tgs" "tgs"
} elseif ($value.Name -ceq $tritonName) { } elseif ($value.Name -ceq $tritonName) {
"triton" "triton"
} elseif ($VegetationLoadGate -and $value.Name -ceq $vegetationName) {
"vegetation"
} else { } else {
throw "Unknown M49 telemetry container" throw "Unknown M49 telemetry container"
} }
[ordered]@{ $telemetryRow = [ordered]@{
observed_utc = [DateTimeOffset]::UtcNow.ToString("o") observed_utc = [DateTimeOffset]::UtcNow.ToString("o")
role = $role role = $role
name = [string]$value.Name name = [string]$value.Name
@@ -373,23 +492,46 @@ try {
memory_usage = [string]$value.MemUsage memory_usage = [string]$value.MemUsage
memory_percent = [string]$value.MemPerc memory_percent = [string]$value.MemPerc
pids = [string]$value.PIDs pids = [string]$value.PIDs
} | ConvertTo-Json -Compress | Out-File -LiteralPath $telemetryPath -Encoding utf8 -Append } | ConvertTo-Json -Compress
$telemetryRow | Out-File -LiteralPath $telemetryPath -Encoding utf8 -Append
if ($VegetationLoadGate -and $role -cne "vegetation") {
$telemetryRow | Out-File -LiteralPath $m49TelemetryPath -Encoding utf8 -Append
}
} }
} }
if (-not $graphState.State.Running -and -not $tgsState.State.Running) { break } $vegetationStopped = -not $VegetationLoadGate -or -not $vegetationState.State.Running
if (
-not $graphState.State.Running -and
-not $tgsState.State.Running -and
$vegetationStopped
) { break }
Start-Sleep -Seconds 1 Start-Sleep -Seconds 1
} }
$graphExit = [int](Get-Container $graphName).State.ExitCode $graphExit = [int](Get-Container $graphName).State.ExitCode
$tgsExit = [int](Get-Container $tgsName).State.ExitCode $tgsExit = [int](Get-Container $tgsName).State.ExitCode
$vegetationExit = if ($VegetationLoadGate) {
[int](Get-Container $vegetationName).State.ExitCode
} else { 0 }
$previousErrorAction = $ErrorActionPreference $previousErrorAction = $ErrorActionPreference
$ErrorActionPreference = "Continue" $ErrorActionPreference = "Continue"
$graphLogs = & docker logs $graphName 2>&1 $graphLogs = & docker logs $graphName 2>&1
$tgsLogs = & docker logs $tgsName 2>&1 $tgsLogs = & docker logs $tgsName 2>&1
$vegetationLogs = if ($VegetationLoadGate) {
& docker logs $vegetationName 2>&1
} else { @() }
$ErrorActionPreference = $previousErrorAction $ErrorActionPreference = $previousErrorAction
$graphLogs | Set-Content -LiteralPath (Join-Path $runOutput "graph.log") -Encoding utf8 $graphLogs | Set-Content -LiteralPath (Join-Path $runOutput "graph.log") -Encoding utf8
$tgsLogs | Set-Content -LiteralPath (Join-Path $runOutput "tgs.log") -Encoding utf8 $tgsLogs | Set-Content -LiteralPath (Join-Path $runOutput "tgs.log") -Encoding utf8
if ($VegetationLoadGate) {
$vegetationLogs | Set-Content -LiteralPath (
Join-Path $runOutput "vegetation.log"
) -Encoding utf8
}
if ($graphExit -ne 0) { throw "M49 integrated graph failed with exit code $graphExit" } if ($graphExit -ne 0) { throw "M49 integrated graph failed with exit code $graphExit" }
if ($tgsExit -ne 0) { throw "M49 integrated TGS failed with exit code $tgsExit" } if ($tgsExit -ne 0) { throw "M49 integrated TGS failed with exit code $tgsExit" }
if ($vegetationExit -ne 0) {
throw "M49 integrated vegetation failed with exit code $vegetationExit"
}
& docker run --rm --name $analyzeName --network none --cpus 8 --memory 16g ` & docker run --rm --name $analyzeName --network none --cpus 8 --memory 16g `
--entrypoint python3 ` --entrypoint python3 `
@@ -401,6 +543,12 @@ try {
--output-root /shared/tgs/evidence --output-root /shared/tgs/evidence
Assert-LastExitCode "M49 integrated TGS evidence analysis" Assert-LastExitCode "M49 integrated TGS evidence analysis"
$m49ResultPath = if ($VegetationLoadGate) {
"/shared/m49-result.json"
} else { "/shared/result.json" }
$dockerM49TelemetryPath = if ($VegetationLoadGate) {
"/shared/m49-container-telemetry.jsonl"
} else { "/shared/container-telemetry.jsonl" }
& docker run --rm --name $evidenceName --network none --cpus 4 --memory 8g ` & docker run --rm --name $evidenceName --network none --cpus 4 --memory 8g `
--entrypoint python3 ` --entrypoint python3 `
--volume ($dockerRelease + ":/release:ro") ` --volume ($dockerRelease + ":/release:ro") `
@@ -411,11 +559,33 @@ try {
--graph-frames /shared/graph/frames.jsonl ` --graph-frames /shared/graph/frames.jsonl `
--tgs-result /shared/tgs/evidence/result.json ` --tgs-result /shared/tgs/evidence/result.json `
--tgs-timing /shared/tgs/tgs-full-timing.tsv ` --tgs-timing /shared/tgs/tgs-full-timing.tsv `
--telemetry /shared/container-telemetry.jsonl ` --telemetry $dockerM49TelemetryPath `
--output /shared/result.json ` --output $m49ResultPath `
--release-sha256 $ExpectedArtifactSha256 --release-sha256 $ExpectedArtifactSha256
Assert-LastExitCode "M49 integrated evidence gate" Assert-LastExitCode "M49 integrated evidence gate"
if ($VegetationLoadGate) {
& docker run --rm --name $vegetationEvidenceName --network none --cpus 4 --memory 8g `
--entrypoint python3 `
--volume ($dockerRelease + ":/release:ro") `
--volume ($dockerRun + ":/shared:rw") `
$ParityImageTag /release/build_vegetation_integrated_graph_evidence.py `
--profile /release/lab-v1-vegetation-integrated-shadow-v1.json `
--m49-result /shared/m49-result.json `
--graph-frames /shared/graph/frames.jsonl `
--tgs-timing /shared/tgs/tgs-full-timing.tsv `
--vegetation-result /shared/vegetation/result.json `
--vegetation-frames /shared/vegetation/frames.jsonl `
--telemetry /shared/container-telemetry.jsonl `
--output /shared/result.json `
--release-sha256 $ExpectedArtifactSha256
Assert-LastExitCode "M49 integrated vegetation evidence gate"
}
} finally { } finally {
$vegetationFrames = Join-Path $runOutput "vegetation\input-frames"
if (Test-Path -LiteralPath $vegetationFrames -PathType Container) {
Remove-Item -LiteralPath $vegetationFrames -Recurse -Force
}
foreach ($name in $containers) { Remove-ExactContainer $name } foreach ($name in $containers) { Remove-ExactContainer $name }
$canonicalAfter = Get-Container "ndc-mission-core-triton" $canonicalAfter = Get-Container "ndc-mission-core-triton"
if ( if (
@@ -432,7 +602,11 @@ if (-not (Test-Path -LiteralPath $resultPath -PathType Leaf)) {
} }
$result = Get-Content -LiteralPath $resultPath -Raw | ConvertFrom-Json $result = Get-Content -LiteralPath $resultPath -Raw | ConvertFrom-Json
$summary = [ordered]@{ $summary = [ordered]@{
schema_version = "missioncore.m49-tgs-integrated-graph-worker-summary/v1" schema_version = if ($VegetationLoadGate) {
"missioncore.lab-v1-vegetation-integrated-worker-summary/v1"
} else {
"missioncore.m49-tgs-integrated-graph-worker-summary/v1"
}
worker_id = "worker-006" worker_id = "worker-006"
run_id = $RunId run_id = $RunId
code_revision = [string]$releaseDocument.code_revision code_revision = [string]$releaseDocument.code_revision
@@ -443,6 +617,7 @@ $summary = [ordered]@{
free_memory_gib_before = [math]::Round($freeMemoryGiB, 6) free_memory_gib_before = [math]::Round($freeMemoryGiB, 6)
result_id = [string]$result.result_id result_id = [string]$result.result_id
result_status = [string]$result.status result_status = [string]$result.status
vegetation_load_gate = [bool]$VegetationLoadGate
canonical_triton_id = $canonicalId canonical_triton_id = $canonicalId
canonical_triton_health = "healthy" canonical_triton_health = "healthy"
gauss_or_playcanvas_action = "none" gauss_or_playcanvas_action = "none"
@@ -0,0 +1,280 @@
#!/usr/bin/env python3
"""Run source-paced DDRNet beside the frozen M4 graph and TGS shadow."""
from __future__ import annotations
import argparse
import json
import math
import platform
import statistics
import time
from pathlib import Path
from typing import Any
import torch
from PIL import Image
from run_goose_vegetation_benchmark import (
infer,
load_mapping,
load_model,
percentile,
preprocess,
read_json,
sha256,
stable_digest,
validate_contracts,
)
SCHEMA = "missioncore.lab-v1-vegetation-integrated-load/v1"
FRAME_SCHEMA = "missioncore.lab-v1-vegetation-integrated-frame/v1"
FRAME_COUNT = 4_489
AUTHORITY = {
"ground_truth": False,
"candidate_accepted": False,
"camera_semantics_can_clear_rigid_geometry": False,
"commands_enabled": False,
"actuation_allowed": False,
"navigation_or_safety_accepted": False,
"production_accepted": False,
}
class IntegratedLoadError(RuntimeError):
"""The bounded integrated-load contract is incomplete or changed."""
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--config", type=Path, required=True)
parser.add_argument("--policy", type=Path, required=True)
parser.add_argument("--provider-map", type=Path, required=True)
parser.add_argument("--checkpoint", type=Path, required=True)
parser.add_argument("--dataset-root", type=Path, required=True)
parser.add_argument("--frames-root", type=Path, required=True)
parser.add_argument("--source-rate-hz", type=float, required=True)
parser.add_argument("--minimum-effective-fps", type=float, required=True)
parser.add_argument("--maximum-completion-p95-ms", type=float, required=True)
parser.add_argument("--shared-start-ready-file", type=Path, required=True)
parser.add_argument("--shared-start-file", type=Path, required=True)
parser.add_argument("--shared-start-timeout-seconds", type=float, default=600.0)
parser.add_argument("--frame-ledger", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--release-sha256", required=True)
return parser.parse_args()
def wait_for_shared_start(ready_file: Path, start_file: Path, timeout_seconds: float) -> None:
if ready_file.exists():
raise IntegratedLoadError("shared-start ready file already exists")
ready_file.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
ready_file.write_text("ready\n", encoding="utf-8")
deadline = time.monotonic() + timeout_seconds
while not start_file.is_file():
if time.monotonic() >= deadline:
raise IntegratedLoadError("shared-start barrier timed out")
time.sleep(0.01)
def distribution(values: list[float]) -> dict[str, float]:
return {
"mean": round(statistics.fmean(values), 6),
"p50": round(percentile(values, 0.50), 6),
"p95": round(percentile(values, 0.95), 6),
"p99": round(percentile(values, 0.99), 6),
"maximum": round(max(values), 6),
}
def exact_frames(root: Path) -> list[Path]:
if root.is_symlink() or not root.is_dir():
raise IntegratedLoadError("RAVNOVES frame root is unavailable")
frames = sorted(root.glob("frame-*.png"))
expected = [f"frame-{sequence + 1:06d}.png" for sequence in range(FRAME_COUNT)]
if len(frames) != FRAME_COUNT or [frame.name for frame in frames] != expected:
raise IntegratedLoadError("RAVNOVES full-video frame sequence changed")
return frames
def validate_sha256(value: str, label: str) -> None:
if len(value) != 64 or any(character not in "0123456789abcdef" for character in value):
raise IntegratedLoadError(f"{label} SHA-256 is invalid")
def run() -> int:
args = parse_args()
if not torch.cuda.is_available():
raise IntegratedLoadError("CUDA is required for Worker 006 qualification")
if (
not math.isfinite(args.source_rate_hz)
or args.source_rate_hz <= 0
or args.minimum_effective_fps <= 0
or args.maximum_completion_p95_ms <= 0
or args.shared_start_timeout_seconds <= 0
):
raise IntegratedLoadError("integrated-load thresholds must be positive and finite")
validate_sha256(args.release_sha256, "release")
if args.output.exists() or args.frame_ledger.exists():
raise IntegratedLoadError("integrated-load output already exists")
config = read_json(args.config, "benchmark config")
policy = read_json(args.policy, "mission policy")
provider_map = read_json(args.provider_map, "provider map")
candidate = validate_contracts(config, policy, provider_map, "ddrnet")
if args.checkpoint.is_symlink() or not args.checkpoint.is_file():
raise IntegratedLoadError("DDRNet checkpoint is unavailable")
if args.checkpoint.stat().st_size != candidate["checkpoint_size_bytes"]:
raise IntegratedLoadError("DDRNet checkpoint size changed")
checkpoint_sha256 = sha256(args.checkpoint)
if checkpoint_sha256 != candidate["checkpoint_sha256"]:
raise IntegratedLoadError("DDRNet checkpoint digest changed")
mapping_path = args.dataset_root / config["dataset"]["mapping_relative_path"]
load_mapping(mapping_path, config["dataset"]["mapping_sha256"])
frames = exact_frames(args.frames_root)
torch.cuda.empty_cache()
model, model_name, architecture_failures = load_model("ddrnet", args.checkpoint)
with Image.open(frames[0]) as image:
warmup_tensor, _ = preprocess(image.convert("RGB"))
warmup_latencies_ms = [infer(model, warmup_tensor)[1] for _ in range(3)]
torch.cuda.reset_peak_memory_stats()
wait_for_shared_start(
args.shared_start_ready_file,
args.shared_start_file,
args.shared_start_timeout_seconds,
)
interval_ns = 1_000_000_000.0 / args.source_rate_hz
start_ns = time.monotonic_ns()
started_utc_ns = time.time_ns()
completion_ages_ms: list[float] = []
stage_latencies_ms: list[float] = []
inference_latencies_ms: list[float] = []
late_deadline_count = 0
args.frame_ledger.parent.mkdir(parents=True, exist_ok=True)
with args.frame_ledger.open("x", encoding="utf-8") as ledger:
for sequence, frame in enumerate(frames):
scheduled_ns = start_ns + round(sequence * interval_ns)
remaining_ns = scheduled_ns - time.monotonic_ns()
if remaining_ns > 0:
time.sleep(remaining_ns / 1_000_000_000.0)
admitted_ns = time.monotonic_ns()
with Image.open(frame) as image:
source = image.convert("RGB")
if source.size != (
config["ravnoves"]["expected_width"],
config["ravnoves"]["expected_height"],
):
raise IntegratedLoadError("RAVNOVES video frame dimensions changed")
tensor, _ = preprocess(source)
_, inference_ms = infer(model, tensor)
completed_ns = time.monotonic_ns()
completion_age_ms = (completed_ns - scheduled_ns) / 1_000_000.0
stage_ms = (completed_ns - admitted_ns) / 1_000_000.0
completion_ages_ms.append(completion_age_ms)
stage_latencies_ms.append(stage_ms)
inference_latencies_ms.append(inference_ms)
if sequence + 1 < FRAME_COUNT and completed_ns > start_ns + round(
(sequence + 1) * interval_ns
):
late_deadline_count += 1
row = {
"schema_version": FRAME_SCHEMA,
"sequence": sequence,
"frame_name": frame.name,
"scheduled_monotonic_ns": scheduled_ns,
"admitted_monotonic_ns": admitted_ns,
"completed_monotonic_ns": completed_ns,
"completion_age_ms": round(completion_age_ms, 6),
"stage_ms": round(stage_ms, 6),
"inference_ms": round(inference_ms, 6),
}
ledger.write(json.dumps(row, sort_keys=True, separators=(",", ":")) + "\n")
if sequence % 64 == 0:
ledger.flush()
completed_ns = time.monotonic_ns()
wall_seconds = (completed_ns - start_ns) / 1_000_000_000.0
effective_fps = FRAME_COUNT / wall_seconds
completion = distribution(completion_ages_ms)
checks = {
"all_frames_accounted": len(completion_ages_ms) == FRAME_COUNT,
"minimum_effective_fps": effective_fps >= args.minimum_effective_fps,
"maximum_completion_p95_ms": completion["p95"]
<= args.maximum_completion_p95_ms,
"zero_capacity_drops": len(completion_ages_ms) == FRAME_COUNT,
"authority_remains_false": all(value is False for value in AUTHORITY.values()),
}
result: dict[str, Any] = {
"schema_version": SCHEMA,
"worker_id": "worker-006",
"source": {
"source_id": config["ravnoves"]["source_id"],
"frame_count": FRAME_COUNT,
"requested_source_rate_hz": args.source_rate_hz,
"raw_fisheye_immutable": True,
"ground_truth_available": False,
},
"candidate": {
"candidate_id": candidate["candidate_id"],
"candidate_key": "ddrnet",
"loaded_model_name": model_name,
"architecture_probe_failures": architecture_failures,
"checkpoint_size_bytes": args.checkpoint.stat().st_size,
"checkpoint_sha256": checkpoint_sha256,
},
"execution": {
"run_mode": "source-paced-integrated-shadow/v1",
"started_utc_ns": started_utc_ns,
"wall_seconds": round(wall_seconds, 6),
"effective_fps": round(effective_fps, 6),
"frame_count": FRAME_COUNT,
"capacity_drop_count": 0,
"deadline_miss_count": late_deadline_count,
"frame_ledger": {
"path": args.frame_ledger.name,
"rows": FRAME_COUNT,
"sha256": sha256(args.frame_ledger),
},
},
"timing": {
"prewarm_inference_count": len(warmup_latencies_ms),
"prewarm_latency_ms_first": round(warmup_latencies_ms[0], 6),
"prewarm_latency_ms_last": round(warmup_latencies_ms[-1], 6),
"completion_age_ms": completion,
"stage_ms": distribution(stage_latencies_ms),
"inference_ms": distribution(inference_latencies_ms),
},
"resource": {
"gpu_name": torch.cuda.get_device_name(0),
"peak_allocated_vram_bytes": int(torch.cuda.max_memory_allocated()),
"peak_reserved_vram_bytes": int(torch.cuda.max_memory_reserved()),
"torch_version": torch.__version__,
"cuda_runtime_version": torch.version.cuda,
"python_version": platform.python_version(),
},
"identity": {
"release_sha256": args.release_sha256,
"config_sha256": sha256(args.config),
"policy_sha256": sha256(args.policy),
"provider_map_sha256": sha256(args.provider_map),
"runner_sha256": sha256(Path(__file__)),
},
"predeclared_thresholds": {
"minimum_effective_fps": args.minimum_effective_fps,
"maximum_completion_p95_ms": args.maximum_completion_p95_ms,
"capacity_drop_count_max": 0,
},
"checks": checks,
"integrated_load_gate_passed": all(checks.values()),
"authority": AUTHORITY,
}
result["result_id"] = f"lab-v1-vegetation-integrated-{stable_digest(result)}"
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8")
print(json.dumps({"result_id": result["result_id"], "passed": all(checks.values())}))
return 0 if all(checks.values()) else 2
if __name__ == "__main__":
raise SystemExit(run())
@@ -0,0 +1,366 @@
#!/usr/bin/env python3
"""Seal the synchronized RF-DETR, TGS and DDRNet Worker 006 load gate."""
from __future__ import annotations
import argparse
import csv
import hashlib
import json
import math
import re
from collections import defaultdict
from pathlib import Path
from typing import Any
import numpy as np
PROFILE_SCHEMA = "missioncore.lab-v1-vegetation-integrated-shadow-profile/v1"
M49_SCHEMA = "missioncore.m49-tgs-integrated-graph-shadow-result/v1"
VEGETATION_SCHEMA = "missioncore.lab-v1-vegetation-integrated-load/v1"
RESULT_SCHEMA = "missioncore.lab-v1-vegetation-integrated-shadow-result/v1"
FRAME_COUNT = 4_489
class VegetationIntegratedError(RuntimeError):
"""The synchronized three-layer load evidence is incomplete."""
def canonical_json(value: object) -> bytes:
return json.dumps(value, sort_keys=True, separators=(",", ":")).encode("utf-8")
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def load_json(path: Path, label: str) -> dict[str, Any]:
try:
value = json.loads(path.read_text(encoding="utf-8-sig"))
except (OSError, json.JSONDecodeError) as exc:
raise VegetationIntegratedError(f"{label} is unreadable") from exc
if not isinstance(value, dict):
raise VegetationIntegratedError(f"{label} is not an object")
return value
def distribution(values: list[float]) -> dict[str, float]:
if not values:
raise VegetationIntegratedError("timing distribution is empty")
array = np.asarray(values, dtype=np.float64)
return {
"mean": round(float(array.mean()), 6),
"p50": round(float(np.percentile(array, 50)), 6),
"p95": round(float(np.percentile(array, 95)), 6),
"p99": round(float(np.percentile(array, 99)), 6),
"maximum": round(float(array.max()), 6),
}
def graph_completion_ages(path: Path) -> list[float]:
values: list[float] = []
with path.open("r", encoding="utf-8") as stream:
for expected, line in enumerate(stream):
row = json.loads(line)
if row.get("source_envelope", {}).get("sequence") != expected:
raise VegetationIntegratedError("graph frame sequence changed")
age = row.get("completion_age_ns")
if not isinstance(age, int) or age < 0:
raise VegetationIntegratedError("graph completion age is invalid")
values.append(age / 1_000_000.0)
if len(values) != FRAME_COUNT:
raise VegetationIntegratedError("graph frame ledger is incomplete")
return values
def tgs_completion_ages(path: Path) -> list[float]:
values: list[float] = []
with path.open("r", encoding="utf-8", newline="") as stream:
for expected, row in enumerate(csv.DictReader(stream, delimiter="\t")):
if int(row["timeline_frame_index"]) != expected:
raise VegetationIntegratedError("TGS timing sequence changed")
age = float(row["completion_age_ms"])
if not math.isfinite(age) or age < 0:
raise VegetationIntegratedError("TGS completion age is invalid")
values.append(age)
if len(values) != FRAME_COUNT:
raise VegetationIntegratedError("TGS timing ledger is incomplete")
return values
def vegetation_completion_ages(path: Path) -> list[float]:
values: list[float] = []
with path.open("r", encoding="utf-8") as stream:
for expected, line in enumerate(stream):
row = json.loads(line)
if row.get("schema_version") != "missioncore.lab-v1-vegetation-integrated-frame/v1":
raise VegetationIntegratedError("vegetation frame schema changed")
if row.get("sequence") != expected:
raise VegetationIntegratedError("vegetation frame sequence changed")
age = row.get("completion_age_ms")
if not isinstance(age, (int, float)) or not math.isfinite(age) or age < 0:
raise VegetationIntegratedError("vegetation completion age is invalid")
values.append(float(age))
if len(values) != FRAME_COUNT:
raise VegetationIntegratedError("vegetation frame ledger is incomplete")
return values
_SIZE = re.compile(r"^\s*([0-9.]+)\s*([kmgt]?i?b)\s*$", re.IGNORECASE)
def size_mib(value: str) -> float:
match = _SIZE.fullmatch(value)
if match is None:
raise VegetationIntegratedError("container memory telemetry is invalid")
number = float(match.group(1))
scale = {
"b": 1.0 / (1024.0 * 1024.0),
"kb": 1.0 / 1024.0,
"kib": 1.0 / 1024.0,
"mb": 1.0,
"mib": 1.0,
"gb": 1024.0,
"gib": 1024.0,
"tb": 1024.0 * 1024.0,
"tib": 1024.0 * 1024.0,
}[match.group(2).lower()]
return number * scale
def host_telemetry(path: Path) -> dict[str, object]:
roles = ("graph", "tgs", "triton", "vegetation")
samples: dict[str, list[dict[str, float]]] = defaultdict(list)
with path.open("r", encoding="utf-8-sig") as stream:
for line in stream:
row = json.loads(line)
role = row.get("role")
if role not in roles:
raise VegetationIntegratedError("container telemetry role changed")
cpu = row.get("cpu_percent")
memory = row.get("memory_usage")
memory_percent = row.get("memory_percent")
if not all(isinstance(value, str) for value in (cpu, memory, memory_percent)):
raise VegetationIntegratedError("container telemetry row is incomplete")
assert isinstance(cpu, str) and isinstance(memory, str)
assert isinstance(memory_percent, str)
samples[role].append(
{
"cpu_percent": float(cpu.rstrip("%")),
"memory_used_mib": size_mib(memory.split("/", 1)[0].strip()),
"memory_percent": float(memory_percent.rstrip("%")),
}
)
if any(not samples[role] for role in roles):
raise VegetationIntegratedError("container telemetry does not cover every runtime role")
return {
role: {
"sample_count": len(samples[role]),
"cpu_percent": distribution([row["cpu_percent"] for row in samples[role]]),
"memory_used_mib": distribution(
[row["memory_used_mib"] for row in samples[role]]
),
"memory_percent": distribution(
[row["memory_percent"] for row in samples[role]]
),
}
for role in roles
}
def build(
*,
profile_path: Path,
m49_result_path: Path,
graph_frames_path: Path,
tgs_timing_path: Path,
vegetation_result_path: Path,
vegetation_frames_path: Path,
telemetry_path: Path,
output_path: Path,
release_sha256: str,
) -> dict[str, object]:
if output_path.exists():
raise VegetationIntegratedError("integrated vegetation result already exists")
if len(release_sha256) != 64 or any(
character not in "0123456789abcdef" for character in release_sha256
):
raise VegetationIntegratedError("release SHA-256 is invalid")
profile = load_json(profile_path, "integrated vegetation profile")
m49 = load_json(m49_result_path, "M49 integrated result")
vegetation = load_json(vegetation_result_path, "vegetation load result")
if profile.get("schema_version") != PROFILE_SCHEMA:
raise VegetationIntegratedError("integrated vegetation profile schema changed")
if m49.get("schema_version") != M49_SCHEMA:
raise VegetationIntegratedError("M49 integrated result schema changed")
if vegetation.get("schema_version") != VEGETATION_SCHEMA:
raise VegetationIntegratedError("vegetation load result schema changed")
graph_ages = graph_completion_ages(graph_frames_path)
tgs_ages = tgs_completion_ages(tgs_timing_path)
vegetation_ages = vegetation_completion_ages(vegetation_frames_path)
combined_ages = [
max(graph, tgs, semantic)
for graph, tgs, semantic in zip(
graph_ages, tgs_ages, vegetation_ages, strict=True
)
]
combined = distribution(combined_ages)
telemetry = host_telemetry(telemetry_path)
acceptance = profile["acceptance"]
vegetation_execution = vegetation.get("execution", {})
vegetation_timing = vegetation.get("timing", {})
vegetation_identity = vegetation.get("identity", {})
vegetation_candidate = vegetation.get("candidate", {})
m49_performance = m49.get("performance", {})
m49_accounting = m49.get("accounting", {})
checks = {
"base_m49_runtime_passed": (
m49.get("status") == "passed"
and m49.get("integrated_runtime_gate_passed") is True
and m49.get("identity", {}).get("profile_sha256")
== profile["stages"]["m49_graph_tgs"]["profile_sha256"]
),
"vegetation_identity_frozen": (
vegetation_candidate.get("candidate_key") == "ddrnet"
and vegetation_candidate.get("checkpoint_sha256")
== profile["stages"]["vegetation"]["checkpoint_sha256"]
and vegetation_identity.get("config_sha256")
== profile["stages"]["vegetation"]["config_sha256"]
and vegetation_identity.get("policy_sha256")
== profile["stages"]["vegetation"]["policy_sha256"]
and vegetation_identity.get("provider_map_sha256")
== profile["stages"]["vegetation"]["provider_map_sha256"]
),
"requested_source_rate_preserved": (
vegetation.get("source", {}).get("requested_source_rate_hz")
== profile["source"]["requested_source_rate_hz"]
),
"exact_three_layer_sequence_join": len(combined_ages) == FRAME_COUNT,
"all_graph_frames_delivered": (
m49_accounting.get("graph_admitted") == FRAME_COUNT
and m49_accounting.get("graph_delivered") == FRAME_COUNT
),
"all_tgs_frames_accounted": m49_accounting.get("tgs_timeline_frames")
== FRAME_COUNT,
"all_vegetation_frames_accounted": vegetation_execution.get("frame_count")
== FRAME_COUNT,
"minimum_graph_world_state_fps": float(
m49_performance.get("effective_world_state_fps", 0.0)
)
>= float(acceptance["minimum_graph_world_state_fps"]),
"minimum_vegetation_fps": float(vegetation_execution.get("effective_fps", 0.0))
>= float(acceptance["minimum_vegetation_fps"]),
"maximum_vegetation_completion_p95_ms": float(
vegetation_timing.get("completion_age_ms", {}).get("p95", math.inf)
)
<= float(acceptance["maximum_vegetation_completion_p95_ms"]),
"maximum_combined_output_age_p99_ms": combined["p99"]
<= float(acceptance["maximum_combined_output_age_p99_ms"]),
"zero_capacity_drops": (
int(m49_accounting.get("tgs_capacity_drops", -1)) == 0
and int(vegetation_execution.get("capacity_drop_count", -1)) == 0
),
"host_resource_telemetry_complete": all(
telemetry[role]["sample_count"] > 0
for role in ("graph", "tgs", "triton", "vegetation")
),
"authority_remains_false": (
all(value is False for value in profile["authority"].values())
and all(value is False for value in vegetation.get("authority", {}).values())
),
}
files = {
label: {"bytes": path.stat().st_size, "sha256": sha256_file(path)}
for label, path in (
("m49-result.json", m49_result_path),
("graph-frames.jsonl", graph_frames_path),
("tgs-timing.tsv", tgs_timing_path),
("vegetation-result.json", vegetation_result_path),
("vegetation-frames.jsonl", vegetation_frames_path),
("container-telemetry.jsonl", telemetry_path),
)
}
document: dict[str, object] = {
"schema_version": RESULT_SCHEMA,
"profile_id": profile["profile_id"],
"status": "passed" if all(checks.values()) else "failed",
"source": {
"source_id": profile["source"]["source_id"],
"requested_source_rate_hz": profile["source"]["requested_source_rate_hz"],
"joined_frame_count": len(combined_ages),
"ground_truth_available": False,
},
"identity": {
"release_sha256": release_sha256,
"profile_sha256": sha256_file(profile_path),
"m49_result_id": m49.get("result_id"),
"vegetation_result_id": vegetation.get("result_id"),
},
"performance": {
"graph_tgs": m49_performance,
"vegetation": {
"effective_fps": vegetation_execution.get("effective_fps"),
"completion_age_ms": vegetation_timing.get("completion_age_ms"),
"stage_ms": vegetation_timing.get("stage_ms"),
"inference_ms": vegetation_timing.get("inference_ms"),
"resource": vegetation.get("resource"),
},
"three_layer_output_age_ms": combined,
"host_containers": telemetry,
},
"accounting": {
"graph_frames": m49_accounting.get("graph_delivered"),
"tgs_frames": m49_accounting.get("tgs_timeline_frames"),
"vegetation_frames": vegetation_execution.get("frame_count"),
"capacity_drop_count": int(m49_accounting.get("tgs_capacity_drops", 0))
+ int(vegetation_execution.get("capacity_drop_count", 0)),
},
"checks": checks,
"integrated_runtime_gate_passed": all(checks.values()),
"visual_quality_accepted": False,
"route_truth_available": False,
"production_accepted": False,
"authority": profile["authority"],
"files": files,
}
identity = hashlib.sha256(canonical_json(document)).hexdigest()
document["result_id"] = f"lab-v1-vegetation-integrated-shadow-{identity}"
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_text(json.dumps(document, indent=2, sort_keys=True) + "\n", encoding="utf-8")
return document
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--profile", type=Path, required=True)
parser.add_argument("--m49-result", type=Path, required=True)
parser.add_argument("--graph-frames", type=Path, required=True)
parser.add_argument("--tgs-timing", type=Path, required=True)
parser.add_argument("--vegetation-result", type=Path, required=True)
parser.add_argument("--vegetation-frames", type=Path, required=True)
parser.add_argument("--telemetry", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--release-sha256", required=True)
arguments = parser.parse_args()
result = build(
profile_path=arguments.profile,
m49_result_path=arguments.m49_result,
graph_frames_path=arguments.graph_frames,
tgs_timing_path=arguments.tgs_timing,
vegetation_result_path=arguments.vegetation_result,
vegetation_frames_path=arguments.vegetation_frames,
telemetry_path=arguments.telemetry,
output_path=arguments.output,
release_sha256=arguments.release_sha256,
)
print(json.dumps({"result_id": result["result_id"], "status": result["status"]}))
return 0 if result["status"] == "passed" else 2
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,183 @@
#!/usr/bin/env python3
"""Build a clean-revision Worker 006 release for the DDRNet + M49 load gate."""
from __future__ import annotations
import argparse
import json
import re
import subprocess
import sys
import tempfile
from pathlib import Path
SCRIPT_ROOT = Path(__file__).resolve().parent
if str(SCRIPT_ROOT) not in sys.path:
sys.path.insert(0, str(SCRIPT_ROOT))
from build_m49_tgs_integrated_graph_worker_artifact import ( # noqa: E402
PATCH_ID,
REPOSITORY_ROOT,
WHEEL_NAME,
ArtifactBuildError,
build_wheel,
git_revision,
materialize_revision,
sha256_file,
write_archive,
)
from build_m49_tgs_integrated_graph_worker_artifact import ( # noqa: E402
SOURCES as M49_SOURCES,
)
SOURCES = M49_SOURCES + (
Path(
"experiments/perception/worker/lab_v1_vegetation_goose/"
"run_goose_vegetation_benchmark.py"
),
Path(
"experiments/perception/worker/lab_v1_vegetation_goose/"
"run_vegetation_integrated_load.py"
),
Path(
"experiments/perception/worker/m49_t3_travel/"
"build_vegetation_integrated_graph_evidence.py"
),
Path("config/perception/lab-v1-goose-vegetation-benchmark-v1.json"),
Path("config/perception/lab-v1-vegetation-mission-policy-v1.json"),
Path("config/perception/lab-v1-vegetation-provider-label-map-v1.json"),
Path("config/perception/lab-v1-vegetation-integrated-shadow-v1.json"),
)
def build_artifact(
patch_id: str,
output_directory: Path,
*,
revision: str | None = None,
source_root: Path | None = None,
) -> dict[str, object]:
if PATCH_ID.fullmatch(patch_id) is None:
raise ArtifactBuildError("patch id is invalid")
selected_revision = revision or git_revision()
if re.fullmatch(r"[a-f0-9]{40}", selected_revision) is None:
raise ArtifactBuildError("artifact revision is invalid")
with tempfile.TemporaryDirectory(prefix="mission-core-vegetation-integrated-") as directory:
stage = Path(directory)
snapshot = source_root
if snapshot is None:
snapshot = stage / "source"
materialize_revision(selected_revision, snapshot)
sources = tuple(snapshot / relative for relative in SOURCES)
if any(path.is_symlink() or not path.is_file() for path in sources):
raise ArtifactBuildError("release input is not a regular file")
payload = stage / "payload"
payload.mkdir()
wheel = build_wheel(snapshot, stage / "wheel")
copied: list[Path] = []
for source in sources:
destination = payload / source.name
if destination.exists():
raise ArtifactBuildError("release payload file names are not unique")
destination.write_bytes(source.read_bytes())
copied.append(destination)
wheel_destination = payload / WHEEL_NAME
wheel_destination.write_bytes(wheel.read_bytes())
copied.append(wheel_destination)
release = {
"schema_version": "missioncore.lab-v1-vegetation-integrated-worker-release/v1",
"patch_id": patch_id,
"transition": "lab-v1-vegetation-m49-integrated-shadow/v1",
"code_revision": selected_revision,
"worker_id": "worker-006",
"source_pack_sha256": (
"0685d24219d8236caf8b7f1685e93f6d6b59e7fd015a768d88a92bbe8b154944"
),
"expected_frames": 4489,
"requested_source_rate_hz": 12.0,
"native_engine_sha256": (
"b8a40b3580edff001ec9680de68707242294ff590ab296000fae371f1083f695"
),
"ddrnet_checkpoint_sha256": (
"b99c2838051bcd7b092fd3970aa62a77d5c0bbb809c9b9afb2ff4b0ebdaa4ee6"
),
"images": {
"travel": (
"sha256:7b412020f4d8392d1d1ed1b33beadc44140f0ea8f781e62dd69796042334300f"
),
"parity": (
"sha256:ceb13548617e4bd3f619766bfdff00af3fa5160946b367828da6d2233dcdcba0"
),
"runtime": (
"sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
),
"vegetation": (
"sha256:591cb382c099eeb05e7ec16e2371e0b2da54d2bb5c49ec0f4ac88dbf72b0f0cd"
),
},
"authority": {
"visual_quality_accepted": False,
"route_truth_available": False,
"traversability_accepted": False,
"physical_free_space_accepted": False,
"commands_enabled": False,
"actuation_allowed": False,
"navigation_or_safety_accepted": False,
"production_accepted": False,
},
"scope": {
"gauss_or_playcanvas_action": "none",
"durable_worker_action": "none",
"canonical_triton_action": "none",
"heavy_vegetation_candidates": ["ddrnet"],
},
"files": {
path.name: {"sha256": sha256_file(path), "bytes": path.stat().st_size}
for path in sorted(copied)
},
}
release_path = payload / "release.json"
release_path.write_text(
json.dumps(release, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
payload_files = sorted((*release["files"], release_path.name))
(stage / "manifest.env").write_text(
f"id={patch_id}\ncomponent=mission-core-worker\ntype=shadow-release\n",
encoding="utf-8",
)
(stage / "files.txt").write_text(
"\n".join(payload_files) + "\n", encoding="utf-8"
)
target = output_directory.resolve() / f"nodedc-{patch_id}.tgz"
write_archive(stage, target)
return {
"ok": True,
"patch_id": patch_id,
"artifact": str(target),
"sha256": sha256_file(target),
"code_revision": selected_revision,
"wheel_sha256": release["files"][WHEEL_NAME]["sha256"],
"payload_files": payload_files,
"transition": release["transition"],
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("patch_id")
parser.add_argument(
"--output-directory",
type=Path,
default=REPOSITORY_ROOT / ".runtime/worker-artifacts",
)
arguments = parser.parse_args()
try:
result = build_artifact(arguments.patch_id, arguments.output_directory)
except (ArtifactBuildError, OSError, subprocess.SubprocessError) as exc:
parser.error(str(exc))
print(json.dumps(result, indent=2, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,281 @@
"""Seal a coarse material + YOLOX + TGS review from an immutable vegetation LAB."""
from __future__ import annotations
import argparse
import copy
import hashlib
import json
import shutil
import tempfile
from datetime import UTC, datetime
from pathlib import Path, PurePosixPath
from typing import Any, Final
from k1link.laboratory.evidence_registry import LaboratoryEvidenceDefinition
from k1link.laboratory.evidence_report import verify_laboratory_evidence_result
from k1link.laboratory.m49_tgs_full_shadow import read_m49_tgs_full_shadow
from k1link.laboratory.vegetation_mission_policy import (
load_vegetation_mission_policy,
load_vegetation_provider_label_map,
)
from k1link.laboratory.vegetation_policy_video import build_policy_mask_archive, policy_taxonomy
from k1link.laboratory.vegetation_shadow_lab import (
LAB_SCHEMA,
RESULT_PREFIX,
canonical_json,
sha256_path,
)
_DEFINITION: Final = LaboratoryEvidenceDefinition(
work_id="lab-v1-vegetation-shadow",
runtime_relative_root=PurePosixPath("lab-v1-vegetation/results"),
result_id_prefix="lab-v1-vegetation-shadow",
document_name="result.json",
result_schema_version=LAB_SCHEMA,
)
_FRAME_COUNT: Final = 4489
_MAX_RESULT_BYTES: Final = 1024 * 1024
class VegetationPolicyReviewError(ValueError):
"""The sealed inputs cannot form an honest synchronized policy review."""
def _object(value: object, label: str) -> dict[str, Any]:
if not isinstance(value, dict) or not all(isinstance(key, str) for key in value):
raise VegetationPolicyReviewError(f"{label} must be an object")
return value
def _read_base(root: Path) -> dict[str, Any]:
candidate = root.resolve(strict=True)
verify_laboratory_evidence_result(_DEFINITION, candidate)
path = candidate / "result.json"
if path.stat().st_size > _MAX_RESULT_BYTES:
raise VegetationPolicyReviewError("base vegetation LAB document is too large")
payload = _object(json.loads(path.read_text("utf-8")), "base vegetation LAB")
route = _object(payload.get("route_video"), "base route video")
authority = _object(payload.get("authority"), "base authority")
if (
payload.get("schema_version") != LAB_SCHEMA
or payload.get("result_id") != candidate.name
or route.get("frame_count") != _FRAME_COUNT
or route.get("view_kind", "fine-semantic-prediction")
!= "fine-semantic-prediction"
or route.get("base_m4_result_id") is None
or authority.get("commands_enabled") is not False
or authority.get("navigation_or_safety_accepted") is not False
or authority.get("actuation_accepted") is not False
or authority.get("camera_semantics_can_clear_rigid_geometry") is not False
):
raise VegetationPolicyReviewError("base vegetation LAB contract changed")
return payload
def _copy_verified_artifacts(
*,
source_root: Path,
destination_root: Path,
artifacts: object,
) -> list[dict[str, object]]:
if not isinstance(artifacts, list):
raise VegetationPolicyReviewError("base artifact catalog changed")
copied: list[dict[str, object]] = []
for raw in artifacts:
descriptor = _object(raw, "base artifact")
relative_text = descriptor.get("path")
expected_sha256 = descriptor.get("sha256")
if not isinstance(relative_text, str) or not isinstance(expected_sha256, str):
raise VegetationPolicyReviewError("base artifact proof changed")
relative = PurePosixPath(relative_text)
source = source_root.joinpath(*relative.parts)
destination = destination_root.joinpath(*relative.parts)
if (
relative.is_absolute()
or str(relative) != relative_text
or any(part in {"", ".", ".."} for part in relative.parts)
or source.is_symlink()
or not source.is_file()
or sha256_path(source) != expected_sha256
):
raise VegetationPolicyReviewError("base artifact changed")
destination.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
shutil.copyfile(source, destination)
copied.append(copy.deepcopy(descriptor))
return copied
def seal_vegetation_policy_review(
*,
base_lab_root: Path,
mission_policy_path: Path,
provider_label_map_path: Path,
m49_tgs_full_shadow_root: Path,
output_root: Path,
created_at_utc: str | None = None,
) -> Path:
base_root = base_lab_root.resolve(strict=True)
base = _read_base(base_root)
base_route = _object(base["route_video"], "base route video")
repository_root = mission_policy_path.resolve().parents[2]
mission_policy = load_vegetation_mission_policy(
mission_policy_path.resolve(strict=True),
repository_root=repository_root,
)
provider_map = load_vegetation_provider_label_map(
provider_label_map_path.resolve(strict=True),
policy=mission_policy,
)
tgs = read_m49_tgs_full_shadow(m49_tgs_full_shadow_root)
tgs_source = _object(tgs.report.get("source"), "full TGS source")
tgs_timeline = _object(tgs.report.get("timeline"), "full TGS timeline")
if (
tgs_source.get("source_id") != "RAVNOVES00"
or tgs_source.get("linked_visual_result_id") != base_route.get("base_m4_result_id")
or tgs_timeline.get("frame_count") != _FRAME_COUNT
):
raise VegetationPolicyReviewError("TGS and vegetation timelines differ")
raw_archive = _object(base_route.get("mask_archive"), "fine mask archive")
if raw_archive.get("path") != "video/ddrnet-semantic-masks.zip":
raise VegetationPolicyReviewError("fine mask archive identity changed")
raw_archive_path = base_root / "video" / "ddrnet-semantic-masks.zip"
fine_taxonomy = _object(base_route.get("taxonomy"), "fine taxonomy")
output_root.mkdir(mode=0o700, parents=True, exist_ok=True)
temporary = Path(tempfile.mkdtemp(prefix=".lab-v1-policy-", dir=output_root))
try:
artifacts = _copy_verified_artifacts(
source_root=base_root,
destination_root=temporary,
artifacts=base.get("artifacts"),
)
policy_archive = temporary / "video" / "coarse-material-policy-masks.zip"
policy_counts = build_policy_mask_archive(
source_archive=raw_archive_path,
destination_archive=policy_archive,
fine_taxonomy=fine_taxonomy,
provider_label_map=provider_map,
)
policy_archive_proof = {
"role": "route-coarse-material-mask-archive",
"path": "video/coarse-material-policy-masks.zip",
"byte_length": policy_archive.stat().st_size,
"sha256": sha256_path(policy_archive),
"media_type": "application/zip",
}
artifacts.append(policy_archive_proof)
route = copy.deepcopy(base_route)
route.update(
{
"view_kind": "coarse-material-policy-review",
"source_mask_archive": copy.deepcopy(raw_archive),
"mask_archive": {
"path": policy_archive_proof["path"],
"sha256": policy_archive_proof["sha256"],
"byte_length": policy_archive_proof["byte_length"],
},
"taxonomy": policy_taxonomy(),
"aggregate_prediction_pixels": policy_counts,
"linked_tgs_result_id": tgs.result_id,
"policy": {
"profile_id": mission_policy["profile_id"],
"profile_sha256": sha256_path(mission_policy_path),
"provider_label_map_id": provider_map["profile_id"],
"provider_label_map_sha256": sha256_path(provider_label_map_path),
"presets": mission_policy["presets"],
"precedence": mission_policy["precedence"],
},
"fusion": {
"mode": "synchronised-multilayer-review",
"pixel_raster_fusion": False,
"camera_material_layer": "DDRNet fine-64 to coarse material evidence",
"camera_safety_veto_layer": "frozen M4 YOLOX camera proposals",
"spatial_safety_veto_layer": "M4.9 full TGS gravity-local costmap",
"temporal_consensus_owner": "TGS causal rolling 1 s and metric obstacle tracks",
"camera_semantic_temporal_filter": "none",
"reason": "No admitted TGS-to-camera pixel projection exists.",
},
}
)
identity = copy.deepcopy(_object(base.get("identity"), "base identity"))
identity.update(
{
"base_result_id": base_root.name,
"route_video": route,
}
)
identity_sha256 = hashlib.sha256(canonical_json(identity)).hexdigest()
result_id = f"{RESULT_PREFIX}{identity_sha256}"
manifest = copy.deepcopy(base)
manifest.update(
{
"result_id": result_id,
"identity_sha256": identity_sha256,
"created_at_utc": created_at_utc or datetime.now(UTC).isoformat(),
"identity": identity,
"route_video": route,
"method": {
"completeness": "complete",
"execution_class": "ai-inference-plus-deterministic-adapter",
"pipeline_id": "goose-fine64-to-coarse-material-plus-yolox-tgs-review/v1",
},
"decision": {
**_object(base.get("decision"), "base decision"),
"multilayer_policy_review_ready": True,
"navigation_accepted": False,
"production_accepted": False,
},
"limitations": [
"GOOSE validation is external-domain qualification, not RAVNOVES ground truth.",
(
"The coarse material playback is derived from per-frame DDRNet "
"predictions and has no RAVNOVES truth."
),
(
"Vegetation semantics never clears YOLOX, LiDAR, metric obstacle "
"or TGS vetoes."
),
"Undefined pixels outside the 600x600 center crop remain fail-closed.",
(
"TGS remains in gravity-local space; no uncalibrated pixel "
"projection is fabricated."
),
(
"Temporal consensus comes from causal TGS and metric tracks; "
"the camera material mask is not temporally filtered."
),
],
"artifacts": artifacts,
}
)
(temporary / "result.json").write_bytes(canonical_json(manifest) + b"\n")
destination = output_root / result_id
if destination.exists():
raise VegetationPolicyReviewError("immutable vegetation policy result already exists")
temporary.replace(destination)
verify_laboratory_evidence_result(_DEFINITION, destination)
return destination
except Exception:
shutil.rmtree(temporary, ignore_errors=True)
raise
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--base-lab-root", type=Path, required=True)
parser.add_argument("--mission-policy-path", type=Path, required=True)
parser.add_argument("--provider-label-map-path", type=Path, required=True)
parser.add_argument("--m49-tgs-full-shadow-root", type=Path, required=True)
parser.add_argument("--output-root", type=Path, required=True)
args = parser.parse_args()
print(seal_vegetation_policy_review(**vars(args)))
if __name__ == "__main__":
main()
__all__ = ["VegetationPolicyReviewError", "seal_vegetation_policy_review"]
@@ -0,0 +1,206 @@
"""Build a deterministic coarse material-evidence video from fine GOOSE masks."""
from __future__ import annotations
import io
import zipfile
from pathlib import Path
from typing import Any, Final
import numpy as np
from PIL import Image
from k1link.laboratory.vegetation_mission_policy import map_provider_material
TAXONOMY_SCHEMA: Final = "missioncore.lab-v1-terrain-policy-taxonomy/v1"
FRAME_COUNT: Final = 4489
WIDTH: Final = 800
HEIGHT: Final = 600
POLICY_CLASSES: Final = (
{
"class_id": 0,
"label": "UNOBSERVED / NO MATERIAL CLAIM · NO_GO",
"color_rgb": [147, 151, 159],
"disposition": "ambiguous",
"material_class": None,
"evidence_state": "UNOBSERVED",
},
{
"class_id": 1,
"label": "SAFETY DETECTOR VETO · NO_GO",
"color_rgb": [255, 104, 112],
"disposition": "labeled",
"material_class": None,
"evidence_state": "RIGID_OR_UNKNOWN_OBSTACLE",
},
{
"class_id": 2,
"label": "WOODY SHRUB / TREE · NO_GO",
"color_rgb": [232, 56, 126],
"disposition": "labeled",
"material_class": "woody_or_tree",
"evidence_state": "VEGETATION_WITH_RIGID_GEOMETRY",
},
{
"class_id": 3,
"label": "CULTIVATED VEGETATION · POLICY NO_GO",
"color_rgb": [183, 112, 255],
"disposition": "labeled",
"material_class": "cultivated_vegetation",
"evidence_state": "VEGETATION_POTENTIALLY_TRAVERSABLE",
},
{
"class_id": 4,
"label": "LOW GRASS · MISSION CANDIDATE",
"color_rgb": [181, 255, 90],
"disposition": "prediction",
"material_class": "grass",
"evidence_state": "VEGETATION_POTENTIALLY_TRAVERSABLE",
},
{
"class_id": 5,
"label": "HIGH / HERBACEOUS · MISSION CANDIDATE",
"color_rgb": [113, 211, 111],
"disposition": "prediction",
"material_class": "herbaceous_vegetation",
"evidence_state": "VEGETATION_POTENTIALLY_TRAVERSABLE",
},
{
"class_id": 6,
"label": "BARE SOIL · MISSION CANDIDATE",
"color_rgb": [255, 197, 92],
"disposition": "prediction",
"material_class": "bare_soil",
"evidence_state": "SUPPORTED_GROUND",
},
{
"class_id": 7,
"label": "HARD SURFACE · MISSION CANDIDATE",
"color_rgb": [84, 169, 255],
"disposition": "prediction",
"material_class": "hard_surface",
"evidence_state": "SUPPORTED_GROUND",
},
{
"class_id": 8,
"label": "VEGETATION UNKNOWN · NO_GO",
"color_rgb": [207, 124, 255],
"disposition": "labeled",
"material_class": "vegetation_unknown",
"evidence_state": "VEGETATION_UNKNOWN",
},
)
_MATERIAL_TO_CLASS: Final = {
"hard_surface": 7,
"bare_soil": 6,
"grass": 4,
"fern": 5,
"herbaceous_vegetation": 5,
"cultivated_vegetation": 3,
"woody_shrub": 2,
"tree_or_trunk": 2,
"vegetation_unknown": 8,
}
class VegetationPolicyVideoError(ValueError):
"""The fine-mask input cannot be transformed without inventing evidence."""
def policy_taxonomy() -> dict[str, object]:
return {
"schema_version": TAXONOMY_SCHEMA,
"classes": [dict(row) for row in POLICY_CLASSES],
}
def fine_to_policy_lut(
fine_taxonomy: dict[str, object],
provider_label_map: dict[str, Any],
) -> np.ndarray:
classes = fine_taxonomy.get("classes")
if not isinstance(classes, list) or len(classes) != 64:
raise VegetationPolicyVideoError("fine taxonomy must contain 64 classes")
lut = np.zeros(256, dtype=np.uint8)
for expected_id, raw in enumerate(classes):
if not isinstance(raw, dict) or raw.get("class_id") != expected_id:
raise VegetationPolicyVideoError("fine taxonomy ordering changed")
label = raw.get("label")
if not isinstance(label, str) or not label:
raise VegetationPolicyVideoError("fine taxonomy label is invalid")
if expected_id == 0:
continue
material = map_provider_material(
provider_label_map,
provider_id="goose-fine-64",
provider_label=label,
)
lut[expected_id] = _MATERIAL_TO_CLASS.get(material, 0)
return lut
def _zip_info(name: str) -> zipfile.ZipInfo:
info = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0))
info.compress_type = zipfile.ZIP_STORED
info.create_system = 3
info.external_attr = 0o600 << 16
return info
def build_policy_mask_archive(
*,
source_archive: Path,
destination_archive: Path,
fine_taxonomy: dict[str, object],
provider_label_map: dict[str, Any],
) -> list[int]:
"""Map every fine mask to coarse evidence; safety vetoes remain separate layers."""
lut = fine_to_policy_lut(fine_taxonomy, provider_label_map)
counts = np.zeros(len(POLICY_CLASSES), dtype=np.int64)
destination_archive.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
try:
with zipfile.ZipFile(source_archive) as source, zipfile.ZipFile(
destination_archive,
"x",
) as destination:
for sequence in range(FRAME_COUNT):
member = f"masks/frame-{sequence + 1:06d}.png"
with source.open(member) as stream, Image.open(stream) as image:
fine = np.asarray(image.convert("L"), dtype=np.uint8)
if fine.shape != (HEIGHT, WIDTH):
raise VegetationPolicyVideoError(
f"fine mask {member} has shape {fine.shape}, expected {(HEIGHT, WIDTH)}"
)
coarse = lut[fine]
counts += np.bincount(
coarse.reshape(-1),
minlength=len(POLICY_CLASSES),
)
buffer = io.BytesIO()
Image.fromarray(coarse, mode="L").save(
buffer,
format="PNG",
compress_level=1,
optimize=False,
)
destination.writestr(_zip_info(member), buffer.getvalue())
except (KeyError, OSError, ValueError, zipfile.BadZipFile) as exc:
destination_archive.unlink(missing_ok=True)
raise VegetationPolicyVideoError("fine mask archive is invalid") from exc
return [int(value) for value in counts]
__all__ = [
"FRAME_COUNT",
"HEIGHT",
"POLICY_CLASSES",
"TAXONOMY_SCHEMA",
"VegetationPolicyVideoError",
"WIDTH",
"build_policy_mask_archive",
"fine_to_policy_lut",
"policy_taxonomy",
]
+153 -4
View File
@@ -14,6 +14,15 @@ from pathlib import Path, PurePosixPath
from typing import Any, Final from typing import Any, Final
from k1link.laboratory.m47_reference_graph import read_m47_reference_graph_lab from k1link.laboratory.m47_reference_graph import read_m47_reference_graph_lab
from k1link.laboratory.m49_tgs_full_shadow import read_m49_tgs_full_shadow
from k1link.laboratory.vegetation_mission_policy import (
load_vegetation_mission_policy,
load_vegetation_provider_label_map,
)
from k1link.laboratory.vegetation_policy_video import (
build_policy_mask_archive,
policy_taxonomy,
)
LAB_SCHEMA: Final = "missioncore.lab-v1-vegetation-shadow/v1" LAB_SCHEMA: Final = "missioncore.lab-v1-vegetation-shadow/v1"
WORKER_SCHEMA: Final = "missioncore.lab-v1-goose-vegetation-run/v1" WORKER_SCHEMA: Final = "missioncore.lab-v1-goose-vegetation-run/v1"
@@ -315,6 +324,9 @@ def seal_vegetation_shadow_lab(
output_root: Path, output_root: Path,
ddrnet_ravnoves_video_root: Path | None = None, ddrnet_ravnoves_video_root: Path | None = None,
m47_reference_graph_lab_root: Path | None = None, m47_reference_graph_lab_root: Path | None = None,
mission_policy_path: Path | None = None,
provider_label_map_path: Path | None = None,
m49_tgs_full_shadow_root: Path | None = None,
) -> Path: ) -> Path:
roots = { roots = {
("ddrnet", "goose"): ddrnet_goose_root.resolve(), ("ddrnet", "goose"): ddrnet_goose_root.resolve(),
@@ -333,6 +345,17 @@ def seal_vegetation_shadow_lab(
selected = _selected_candidate(results) selected = _selected_candidate(results)
if (ddrnet_ravnoves_video_root is None) != (m47_reference_graph_lab_root is None): if (ddrnet_ravnoves_video_root is None) != (m47_reference_graph_lab_root is None):
raise VegetationShadowLabError("full-video Worker and M4.7 roots must be paired") raise VegetationShadowLabError("full-video Worker and M4.7 roots must be paired")
policy_inputs = (
mission_policy_path,
provider_label_map_path,
m49_tgs_full_shadow_root,
)
if any(value is not None for value in policy_inputs) and not all(
value is not None for value in policy_inputs
):
raise VegetationShadowLabError("policy, provider map and full TGS roots must be paired")
if all(value is not None for value in policy_inputs) and ddrnet_ravnoves_video_root is None:
raise VegetationShadowLabError("policy review requires the full-video DDRNet result")
route_video: dict[str, object] | None = None route_video: dict[str, object] | None = None
route_video_archive: Path | None = None route_video_archive: Path | None = None
video_result: dict[str, Any] | None = None video_result: dict[str, Any] | None = None
@@ -355,6 +378,35 @@ def seal_vegetation_shadow_lab(
raise VegetationShadowLabError("M4.7 video binding differs from DDRNet source") raise VegetationShadowLabError("M4.7 video binding differs from DDRNet source")
route_video["m47_reference_graph_result_id"] = m47.result_id route_video["m47_reference_graph_result_id"] = m47.result_id
mission_policy: dict[str, Any] | None = None
provider_label_map: dict[str, Any] | None = None
linked_tgs_result_id: str | None = None
if (
mission_policy_path is not None
and provider_label_map_path is not None
and m49_tgs_full_shadow_root is not None
and route_video is not None
):
repository_root = mission_policy_path.resolve().parents[2]
mission_policy = load_vegetation_mission_policy(
mission_policy_path.resolve(),
repository_root=repository_root,
)
provider_label_map = load_vegetation_provider_label_map(
provider_label_map_path.resolve(),
policy=mission_policy,
)
tgs = read_m49_tgs_full_shadow(m49_tgs_full_shadow_root)
tgs_source = _object(tgs.report.get("source"), "M4.9 full TGS source")
tgs_timeline = _object(tgs.report.get("timeline"), "M4.9 full TGS timeline")
if (
tgs_source.get("source_id") != "RAVNOVES00"
or tgs_source.get("linked_visual_result_id") != route_video["base_m4_result_id"]
or tgs_timeline.get("frame_count") != _VIDEO_FRAME_COUNT
):
raise VegetationShadowLabError("full TGS timeline differs from vegetation video")
linked_tgs_result_id = tgs.result_id
output_root.mkdir(mode=0o700, parents=True, exist_ok=True) output_root.mkdir(mode=0o700, parents=True, exist_ok=True)
temporary = Path(tempfile.mkdtemp(prefix=".lab-v1-vegetation-", dir=output_root)) temporary = Path(tempfile.mkdtemp(prefix=".lab-v1-vegetation-", dir=output_root))
artifacts: list[dict[str, object]] = [] artifacts: list[dict[str, object]] = []
@@ -471,14 +523,78 @@ def seal_vegetation_shadow_lab(
temporary, temporary,
"video/ddrnet-semantic-masks.zip", "video/ddrnet-semantic-masks.zip",
artifacts, artifacts,
role="route-semantic-mask-archive", role=(
"route-fine-semantic-source-archive"
if mission_policy is not None
else "route-semantic-mask-archive"
),
media_type="application/zip", media_type="application/zip",
) )
route_video["mask_archive"] = { raw_archive_proof = {
"path": archive_descriptor["path"], "path": archive_descriptor["path"],
"sha256": archive_descriptor["sha256"], "sha256": archive_descriptor["sha256"],
"byte_length": archive_descriptor["byte_length"], "byte_length": archive_descriptor["byte_length"],
} }
route_video["mask_archive"] = raw_archive_proof
route_video["view_kind"] = "fine-semantic-prediction"
if (
mission_policy is not None
and provider_label_map is not None
and linked_tgs_result_id is not None
and mission_policy_path is not None
and provider_label_map_path is not None
):
policy_archive = temporary / "video" / "coarse-material-policy-masks.zip"
policy_counts = build_policy_mask_archive(
source_archive=route_video_archive,
destination_archive=policy_archive,
fine_taxonomy=_object(route_video["taxonomy"], "fine video taxonomy"),
provider_label_map=provider_label_map,
)
policy_descriptor = {
"role": "route-coarse-material-mask-archive",
"path": "video/coarse-material-policy-masks.zip",
"byte_length": policy_archive.stat().st_size,
"sha256": sha256_path(policy_archive),
"media_type": "application/zip",
}
artifacts.append(policy_descriptor)
route_video.update(
{
"view_kind": "coarse-material-policy-review",
"source_mask_archive": raw_archive_proof,
"mask_archive": {
"path": policy_descriptor["path"],
"sha256": policy_descriptor["sha256"],
"byte_length": policy_descriptor["byte_length"],
},
"taxonomy": policy_taxonomy(),
"aggregate_prediction_pixels": policy_counts,
"linked_tgs_result_id": linked_tgs_result_id,
"policy": {
"profile_id": mission_policy["profile_id"],
"profile_sha256": sha256_path(mission_policy_path),
"provider_label_map_id": provider_label_map["profile_id"],
"provider_label_map_sha256": sha256_path(
provider_label_map_path
),
"presets": mission_policy["presets"],
"precedence": mission_policy["precedence"],
},
"fusion": {
"mode": "synchronised-multilayer-review",
"pixel_raster_fusion": False,
"camera_material_layer": "DDRNet fine-64 to coarse material evidence",
"camera_safety_veto_layer": "frozen M4 YOLOX camera proposals",
"spatial_safety_veto_layer": "M4.9 full TGS gravity-local costmap",
"temporal_consensus_owner": (
"TGS causal rolling 1 s and metric obstacle tracks"
),
"camera_semantic_temporal_filter": "none",
"reason": "No admitted TGS-to-camera pixel projection exists.",
},
}
)
candidate_metrics: dict[str, object] = {} candidate_metrics: dict[str, object] = {}
for candidate in _CANDIDATES: for candidate in _CANDIDATES:
@@ -536,7 +652,11 @@ def seal_vegetation_shadow_lab(
"method": { "method": {
"completeness": "complete", "completeness": "complete",
"execution_class": "ai-inference", "execution_class": "ai-inference",
"pipeline_id": "goose-fine64-ready-weights-to-ravnoves-policy-shadow/v1", "pipeline_id": (
"goose-fine64-to-coarse-material-plus-yolox-tgs-review/v1"
if mission_policy is not None
else "goose-fine64-ready-weights-to-ravnoves-policy-shadow/v1"
),
}, },
"metrics": {"candidates": candidate_metrics}, "metrics": {"candidates": candidate_metrics},
"decision": { "decision": {
@@ -544,14 +664,37 @@ def seal_vegetation_shadow_lab(
"visual_shadow_ready": True, "visual_shadow_ready": True,
"full_video_shadow_ready": route_video is not None, "full_video_shadow_ready": route_video is not None,
"mission_policy_ready_for_configuration": True, "mission_policy_ready_for_configuration": True,
"multilayer_policy_review_ready": mission_policy is not None,
"navigation_accepted": False, "navigation_accepted": False,
"production_accepted": False, "production_accepted": False,
}, },
"limitations": [ "limitations": [
"GOOSE validation is external-domain qualification, not RAVNOVES ground truth.", "GOOSE validation is external-domain qualification, not RAVNOVES ground truth.",
"The full RAVNOVES DDRNet playback is prediction-only and has no independent labels.", (
"The coarse material playback is derived from per-frame DDRNet predictions "
"and has no RAVNOVES truth."
if mission_policy is not None
else (
"The full RAVNOVES DDRNet playback is prediction-only and has "
"no independent labels."
)
),
"Vegetation semantics never clears rigid LiDAR/TGS occupancy.", "Vegetation semantics never clears rigid LiDAR/TGS occupancy.",
"Undefined pixels outside the 600x600 center crop remain fail-closed.", "Undefined pixels outside the 600x600 center crop remain fail-closed.",
*(
[
(
"TGS remains in gravity-local space; no uncalibrated pixel "
"projection is fabricated."
),
(
"Temporal consensus comes from causal TGS and metric tracks; "
"the camera material mask is not temporally filtered."
),
]
if mission_policy is not None
else []
),
], ],
"authority": authority, "authority": authority,
"catalogs": catalogs, "catalogs": catalogs,
@@ -577,6 +720,9 @@ def _parse_args() -> argparse.Namespace:
parser.add_argument("--output-root", type=Path, required=True) parser.add_argument("--output-root", type=Path, required=True)
parser.add_argument("--ddrnet-ravnoves-video-root", type=Path) parser.add_argument("--ddrnet-ravnoves-video-root", type=Path)
parser.add_argument("--m47-reference-graph-lab-root", type=Path) parser.add_argument("--m47-reference-graph-lab-root", type=Path)
parser.add_argument("--mission-policy-path", type=Path)
parser.add_argument("--provider-label-map-path", type=Path)
parser.add_argument("--m49-tgs-full-shadow-root", type=Path)
return parser.parse_args() return parser.parse_args()
@@ -590,6 +736,9 @@ def main() -> None:
output_root=args.output_root, output_root=args.output_root,
ddrnet_ravnoves_video_root=args.ddrnet_ravnoves_video_root, ddrnet_ravnoves_video_root=args.ddrnet_ravnoves_video_root,
m47_reference_graph_lab_root=args.m47_reference_graph_lab_root, m47_reference_graph_lab_root=args.m47_reference_graph_lab_root,
mission_policy_path=args.mission_policy_path,
provider_label_map_path=args.provider_label_map_path,
m49_tgs_full_shadow_root=args.m49_tgs_full_shadow_root,
) )
print(destination) print(destination)
+24 -3
View File
@@ -93,12 +93,33 @@ def build_vegetation_shadow_lab_router(
candidate = _resolve_candidate(root_provider, result_id) candidate = _resolve_candidate(root_provider, result_id)
manifest = _read_verified(candidate) manifest = _read_verified(candidate)
route_video = manifest.get("route_video") route_video = manifest.get("route_video")
if not isinstance(route_video, dict) or not 0 <= sequence < 4489: if (
not isinstance(route_video, dict)
or route_video.get("frame_count") != 4489
or not 0 <= sequence < 4489
):
raise HTTPException(status_code=404, detail="Vegetation video mask not found") raise HTTPException(status_code=404, detail="Vegetation video mask not found")
archive = route_video.get("mask_archive") archive = route_video.get("mask_archive")
if not isinstance(archive, dict) or archive.get("path") != "video/ddrnet-semantic-masks.zip": archive_relative = archive.get("path") if isinstance(archive, dict) else None
if not isinstance(archive_relative, str):
raise HTTPException(status_code=404, detail="Vegetation video mask not found") raise HTTPException(status_code=404, detail="Vegetation video mask not found")
archive_path = candidate / "video" / "ddrnet-semantic-masks.zip" relative = PurePosixPath(archive_relative)
if (
relative.is_absolute()
or str(relative) != archive_relative
or any(part in {"", ".", ".."} for part in relative.parts)
or relative.suffix != ".zip"
):
raise HTTPException(status_code=404, detail="Vegetation video mask not found")
artifacts = manifest.get("artifacts")
if not isinstance(artifacts, list) or not any(
isinstance(item, dict)
and item.get("path") == archive_relative
and item.get("media_type") == "application/zip"
for item in artifacts
):
raise HTTPException(status_code=404, detail="Vegetation video mask not found")
archive_path = candidate.joinpath(*relative.parts)
member = f"masks/frame-{sequence + 1:06d}.png" member = f"masks/frame-{sequence + 1:06d}.png"
try: try:
before = archive_path.stat() before = archive_path.stat()
@@ -0,0 +1,243 @@
from __future__ import annotations
import importlib.util
import json
import tarfile
from pathlib import Path
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
EVIDENCE_PATH = (
REPOSITORY_ROOT
/ "experiments/perception/worker/m49_t3_travel/"
"build_vegetation_integrated_graph_evidence.py"
)
ARTIFACT_PATH = (
REPOSITORY_ROOT / "scripts/build_lab_v1_vegetation_integrated_worker_artifact.py"
)
RUNNER_PATH = (
REPOSITORY_ROOT
/ "experiments/perception/worker/lab_v1_vegetation_goose/"
"run_vegetation_integrated_load.py"
)
POWERSHELL_PATH = (
REPOSITORY_ROOT
/ "experiments/perception/worker/Invoke-M49TgsIntegratedGraphShadow.ps1"
)
def load_module(name: str, path: Path):
spec = importlib.util.spec_from_file_location(name, path)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
EVIDENCE = load_module("vegetation_integrated_evidence", EVIDENCE_PATH)
ARTIFACT = load_module("vegetation_integrated_artifact", ARTIFACT_PATH)
def test_three_layer_gate_joins_exact_frames_and_preserves_false_authority(
tmp_path: Path,
) -> None:
profile = tmp_path / "profile.json"
profile.write_text(
json.dumps(
{
"schema_version": EVIDENCE.PROFILE_SCHEMA,
"profile_id": "test",
"source": {"source_id": "RAVNOVES00", "requested_source_rate_hz": 12.0},
"stages": {
"m49_graph_tgs": {"profile_sha256": "a" * 64},
"vegetation": {
"checkpoint_sha256": "b" * 64,
"config_sha256": "c" * 64,
"policy_sha256": "d" * 64,
"provider_map_sha256": "e" * 64,
},
},
"acceptance": {
"minimum_graph_world_state_fps": 11.2,
"minimum_vegetation_fps": 11.2,
"maximum_vegetation_completion_p95_ms": 125.0,
"maximum_combined_output_age_p99_ms": 125.0,
},
"authority": {
"commands_enabled": False,
"actuation_allowed": False,
"navigation_or_safety_accepted": False,
"production_accepted": False,
},
}
),
encoding="utf-8",
)
m49 = tmp_path / "m49.json"
m49.write_text(
json.dumps(
{
"schema_version": EVIDENCE.M49_SCHEMA,
"status": "passed",
"integrated_runtime_gate_passed": True,
"result_id": "m49-test",
"identity": {"profile_sha256": "a" * 64},
"performance": {"effective_world_state_fps": 11.8},
"accounting": {
"graph_admitted": EVIDENCE.FRAME_COUNT,
"graph_delivered": EVIDENCE.FRAME_COUNT,
"tgs_timeline_frames": EVIDENCE.FRAME_COUNT,
"tgs_capacity_drops": 0,
},
}
),
encoding="utf-8",
)
vegetation = tmp_path / "vegetation.json"
vegetation.write_text(
json.dumps(
{
"schema_version": EVIDENCE.VEGETATION_SCHEMA,
"result_id": "vegetation-test",
"source": {"requested_source_rate_hz": 12.0},
"candidate": {"candidate_key": "ddrnet", "checkpoint_sha256": "b" * 64},
"identity": {
"config_sha256": "c" * 64,
"policy_sha256": "d" * 64,
"provider_map_sha256": "e" * 64,
},
"execution": {
"frame_count": EVIDENCE.FRAME_COUNT,
"effective_fps": 11.75,
"capacity_drop_count": 0,
},
"timing": {
"completion_age_ms": {"p95": 25.0},
"stage_ms": {"p95": 20.0},
"inference_ms": {"p95": 18.0},
},
"resource": {"gpu_name": "test"},
"authority": {
"commands_enabled": False,
"actuation_allowed": False,
"navigation_or_safety_accepted": False,
"production_accepted": False,
},
}
),
encoding="utf-8",
)
graph_frames = tmp_path / "graph.jsonl"
graph_frames.write_text(
"".join(
json.dumps(
{"source_envelope": {"sequence": index}, "completion_age_ns": 40_000_000}
)
+ "\n"
for index in range(EVIDENCE.FRAME_COUNT)
),
encoding="utf-8",
)
tgs_frames = tmp_path / "tgs.tsv"
tgs_frames.write_text(
"timeline_frame_index\tcompletion_age_ms\n"
+ "".join(f"{index}\t5.0\n" for index in range(EVIDENCE.FRAME_COUNT)),
encoding="utf-8",
)
vegetation_frames = tmp_path / "vegetation.jsonl"
vegetation_frames.write_text(
"".join(
json.dumps(
{
"schema_version": "missioncore.lab-v1-vegetation-integrated-frame/v1",
"sequence": index,
"completion_age_ms": 20.0,
}
)
+ "\n"
for index in range(EVIDENCE.FRAME_COUNT)
),
encoding="utf-8",
)
telemetry = tmp_path / "telemetry.jsonl"
telemetry.write_text(
"".join(
json.dumps(
{
"role": role,
"cpu_percent": "10.0%",
"memory_usage": "1GiB / 64GiB",
"memory_percent": "1.56%",
}
)
+ "\n"
for role in ("graph", "tgs", "triton", "vegetation")
),
encoding="utf-8",
)
output = tmp_path / "result.json"
result = EVIDENCE.build(
profile_path=profile,
m49_result_path=m49,
graph_frames_path=graph_frames,
tgs_timing_path=tgs_frames,
vegetation_result_path=vegetation,
vegetation_frames_path=vegetation_frames,
telemetry_path=telemetry,
output_path=output,
release_sha256="f" * 64,
)
assert result["status"] == "passed"
assert result["source"]["joined_frame_count"] == EVIDENCE.FRAME_COUNT
assert result["performance"]["three_layer_output_age_ms"]["p99"] == 40.0
assert result["checks"]["authority_remains_false"] is True
assert result["production_accepted"] is False
def test_integrated_release_is_deterministic_and_contains_one_vegetation_candidate(
monkeypatch, tmp_path: Path
) -> None:
def fake_wheel(_source_root: Path, output: Path) -> Path:
output.mkdir(parents=True, exist_ok=True)
wheel = output / ARTIFACT.WHEEL_NAME
wheel.write_bytes(b"clean committed wheel\n")
return wheel
monkeypatch.setattr(ARTIFACT, "build_wheel", fake_wheel)
revision = "f" * 40
first = ARTIFACT.build_artifact(
"mission-core-vegetation-integrated-unit-001",
tmp_path / "first",
revision=revision,
source_root=REPOSITORY_ROOT,
)
second = ARTIFACT.build_artifact(
"mission-core-vegetation-integrated-unit-001",
tmp_path / "second",
revision=revision,
source_root=REPOSITORY_ROOT,
)
assert Path(first["artifact"]).read_bytes() == Path(second["artifact"]).read_bytes()
with tarfile.open(first["artifact"], "r:gz") as archive:
names = set(archive.getnames())
release_stream = archive.extractfile("payload/release.json")
assert release_stream is not None
release = json.loads(release_stream.read())
assert "payload/run_vegetation_integrated_load.py" in names
assert "payload/build_vegetation_integrated_graph_evidence.py" in names
assert release["scope"]["heavy_vegetation_candidates"] == ["ddrnet"]
assert all(value is False for value in release["authority"].values())
def test_worker_gate_reuses_shared_barrier_and_keeps_canonical_triton_unchanged() -> None:
runner = RUNNER_PATH.read_text(encoding="utf-8")
wrapper = POWERSHELL_PATH.read_text(encoding="utf-8")
assert '"source-paced-integrated-shadow/v1"' in runner
assert "wait_for_shared_start(" in runner
assert '"camera_semantics_can_clear_rigid_geometry": False' in runner
assert "$VegetationLoadGate" in wrapper
assert '"vegetation"' in wrapper
assert "if ($canonicalAfter.Id -cne $canonicalId" not in wrapper
assert "$canonicalAfter.Id -cne $canonicalId" in wrapper
+96 -1
View File
@@ -2,6 +2,7 @@ from __future__ import annotations
import hashlib import hashlib
import json import json
import shutil
import zipfile import zipfile
from pathlib import Path from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
@@ -9,9 +10,11 @@ from types import SimpleNamespace
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from k1link.laboratory import LaboratoryEvidenceRegistry import k1link.laboratory.vegetation_policy_review as policy_review_module
import k1link.laboratory.vegetation_shadow_lab as vegetation_lab_module import k1link.laboratory.vegetation_shadow_lab as vegetation_lab_module
from k1link.laboratory import LaboratoryEvidenceRegistry
from k1link.laboratory.evidence_report import verify_laboratory_evidence_result from k1link.laboratory.evidence_report import verify_laboratory_evidence_result
from k1link.laboratory.vegetation_policy_review import seal_vegetation_policy_review
from k1link.laboratory.vegetation_shadow_lab import seal_vegetation_shadow_lab from k1link.laboratory.vegetation_shadow_lab import seal_vegetation_shadow_lab
from k1link.web.vegetation_shadow_lab_api import build_vegetation_shadow_lab_router from k1link.web.vegetation_shadow_lab_api import build_vegetation_shadow_lab_router
@@ -229,3 +232,95 @@ def test_vegetation_shadow_lab_seals_autonomous_visual_evidence(
client.get(f"/api/v1/laboratory/vegetation-shadow/{result_root.name}").status_code client.get(f"/api/v1/laboratory/vegetation-shadow/{result_root.name}").status_code
== 503 == 503
) )
def test_policy_review_reuses_sealed_video_and_links_yolox_tgs(
tmp_path: Path,
monkeypatch,
) -> None:
roots = {}
for candidate, vegetation_iou in (("ddrnet", 0.64), ("ppliteseg", 0.61)):
for mode in ("goose", "ravnoves"):
root = tmp_path / "worker" / f"{candidate}-{mode}"
_worker_result(root, candidate=candidate, mode=mode, vegetation_iou=vegetation_iou)
roots[(candidate, mode)] = root
video_root = tmp_path / "worker" / "ddrnet-ravnoves-video"
_video_worker_result(video_root)
m47_root = tmp_path / f"m47-reference-graph-lab-{'a' * 64}"
m47_root.mkdir()
base_m4_result_id = f"m4-threat-replay-{'f' * 64}"
monkeypatch.setattr(
vegetation_lab_module,
"read_m47_reference_graph_lab",
lambda _root: SimpleNamespace(
result_id=m47_root.name,
report={
"source": {"source_id": "RAVNOVES00"},
"visual_evidence": {
"linked_result_id": base_m4_result_id,
"timeline_frames": 4489,
},
},
),
)
base_root = seal_vegetation_shadow_lab(
ddrnet_goose_root=roots[("ddrnet", "goose")],
ppliteseg_goose_root=roots[("ppliteseg", "goose")],
ddrnet_ravnoves_root=roots[("ddrnet", "ravnoves")],
ppliteseg_ravnoves_root=roots[("ppliteseg", "ravnoves")],
output_root=tmp_path / "results",
ddrnet_ravnoves_video_root=video_root,
m47_reference_graph_lab_root=m47_root,
)
tgs_result_id = f"m49-tgs-full-shadow-{'9' * 64}"
monkeypatch.setattr(
policy_review_module,
"read_m49_tgs_full_shadow",
lambda _root: SimpleNamespace(
result_id=tgs_result_id,
report={
"source": {
"source_id": "RAVNOVES00",
"linked_visual_result_id": base_m4_result_id,
},
"timeline": {"frame_count": 4489},
},
),
)
def fake_policy_archive(**kwargs) -> list[int]:
shutil.copyfile(kwargs["source_archive"], kwargs["destination_archive"])
return [4489 * 800 * 600, *([0] * 8)]
monkeypatch.setattr(policy_review_module, "build_policy_mask_archive", fake_policy_archive)
result_root = seal_vegetation_policy_review(
base_lab_root=base_root,
mission_policy_path=REPOSITORY_ROOT
/ "config/perception/lab-v1-vegetation-mission-policy-v1.json",
provider_label_map_path=REPOSITORY_ROOT
/ "config/perception/lab-v1-vegetation-provider-label-map-v1.json",
m49_tgs_full_shadow_root=tmp_path / "sealed-tgs",
output_root=tmp_path / "results",
created_at_utc="2026-08-28T08:00:00+00:00",
)
manifest = json.loads((result_root / "result.json").read_text("utf-8"))
route = manifest["route_video"]
assert route["view_kind"] == "coarse-material-policy-review"
assert route["linked_tgs_result_id"] == tgs_result_id
assert route["fusion"]["pixel_raster_fusion"] is False
assert route["fusion"]["camera_semantic_temporal_filter"] == "none"
assert route["taxonomy"]["schema_version"] == (
"missioncore.lab-v1-terrain-policy-taxonomy/v1"
)
assert len(route["taxonomy"]["classes"]) == 9
assert len(manifest["artifacts"]) == 79
assert manifest["authority"]["commands_enabled"] is False
assert manifest["decision"]["multilayer_policy_review_ready"] is True
app = FastAPI()
app.include_router(build_vegetation_shadow_lab_router(root_provider=lambda: result_root.parent))
response = TestClient(app).get(
f"/api/v1/laboratory/vegetation-shadow/{result_root.name}/masks/0"
)
assert response.status_code == 200
assert response.content == b"\x89PNG\r\n\x1a\n"