fix(lab): restore semantic overlay in M4.7

This commit is contained in:
DCCONSTRUCTIONS
2026-08-23 22:40:07 +03:00
parent 34ed8a0f5f
commit a55ef475d9
11 changed files with 289 additions and 32 deletions
@@ -360,27 +360,65 @@ function parseResult(value: unknown): E47SemanticSlamResult {
}
export async function fetchE47SemanticSlamResult({
resultId: requestedResultId,
fetcher = fetch,
signal,
}: {
resultId?: string;
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
} = {}): Promise<E47SemanticSlamResult | null> {
const response = await fetcher("/api/v1/laboratory/e47-semantic-slam/results?limit=1", {
headers: { Accept: "application/json" },
signal,
});
if (requestedResultId !== undefined) resultId(requestedResultId);
let response = await fetcher(
requestedResultId === undefined
? "/api/v1/laboratory/e47-semantic-slam/results?limit=1"
: `/api/v1/laboratory/e47-semantic-slam/results/${requestedResultId}`,
{ headers: { Accept: "application/json" }, signal },
);
let catalogFallback = false;
if (requestedResultId !== undefined && response.status === 404) {
response = await fetcher("/api/v1/laboratory/e47-semantic-slam/results?limit=10", {
headers: { Accept: "application/json" },
signal,
});
catalogFallback = true;
}
if (!response.ok) {
throw new E47SemanticSlamContractError(`E47 LAB недоступен: HTTP ${response.status}.`);
}
const payload = object(await response.json(), "E47 catalog");
exact(
payload.schema_version,
"missioncore.e47-semantic-slam-catalog/v1",
"E47 catalog schema",
);
const items = array(payload.items, "E47 catalog items");
return items.length ? parseResult(items[0]) : null;
const payload = await response.json();
if (requestedResultId === undefined || catalogFallback) {
const catalog = object(payload, "E47 catalog");
exact(
catalog.schema_version,
"missioncore.e47-semantic-slam-catalog/v1",
"E47 catalog schema",
);
const items = array(catalog.items, "E47 catalog items");
if (!items.length) return null;
const selected = requestedResultId === undefined
? items[0]
: items.find((candidate) => (
typeof candidate === "object"
&& candidate !== null
&& (candidate as Record<string, unknown>).result_id === requestedResultId
));
if (selected === undefined) {
throw new E47SemanticSlamContractError(
"E47 requested result: точный semantic-result отсутствует в каталоге.",
);
}
const parsed = parseResult(selected);
if (requestedResultId !== undefined && parsed.resultId !== requestedResultId) {
throw new E47SemanticSlamContractError("E47 requested result: нарушена идентичность.");
}
return parsed;
}
const parsed = parseResult(payload);
if (parsed.resultId !== requestedResultId) {
throw new E47SemanticSlamContractError("E47 requested result: нарушена идентичность.");
}
return parsed;
}
function parseFrame(
@@ -6,6 +6,10 @@ import {
fetchM4ThreatReplayResult,
type M4ThreatReplayResult,
} from "./m4ReplayThreat";
import {
fetchE47SemanticSlamResult,
type E47SemanticSlamResult,
} from "./e47SemanticSlam";
export interface M47ReferenceGraphLabResult {
resultId: string;
@@ -41,6 +45,7 @@ export interface M47ReferenceGraphLabResult {
>>;
limitations: readonly string[];
visual: M4ThreatReplayResult;
semantic: E47SemanticSlamResult;
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
@@ -154,7 +159,7 @@ export async function fetchM47ReferenceGraphLab({
const report = evidence.rawReport;
exact(
report.schema_version,
"missioncore.reference-perception-graph-lab-report/v1",
"missioncore.reference-perception-graph-lab-report/v2",
"M4.7 report schema",
);
exact(report.result_id, resultId, "M4.7 report result");
@@ -176,6 +181,16 @@ export async function fetchM47ReferenceGraphLab({
true,
"M4.7 visual evidence",
);
exact(
visualEvidence.camera_semantic_overlay_available,
true,
"M4.7 camera semantic overlay",
);
exact(
visualEvidence.semantic_binding,
"exact-sequence-and-session-time",
"M4.7 semantic binding",
);
const linkedVisualResultId = text(
visualEvidence.linked_result_id,
"M4.7 linked visual result",
@@ -193,6 +208,31 @@ export async function fetchM47ReferenceGraphLab({
"M4.7 visual binding: сервер вернул другой replay result.",
);
}
const semanticResultId = text(
visualEvidence.semantic_result_id,
"M4.7 linked semantic result",
);
if (!/^e47-semantic-slam-[a-f0-9]{64}$/.test(semanticResultId)) {
throw new M47ReferenceGraphContractError(
"M4.7 semantic binding: нарушена идентичность.",
);
}
const semantic = await fetchE47SemanticSlamResult({
resultId: semanticResultId,
fetcher,
signal,
});
if (
!semantic
|| semantic.resultId !== semanticResultId
|| semantic.baseM4ResultId !== linkedVisualResultId
|| semantic.metrics.frames.total !== 4489
|| semantic.metrics.frames.maskAvailable !== 4489
) {
throw new M47ReferenceGraphContractError(
"M4.7 semantic binding: сервер вернул несвязанный semantic-result.",
);
}
const graphResultId = text(source.graph_result_id, "M4.7 graph result");
if (!/^m47-reference-graph-[a-f0-9]{64}$/.test(graphResultId)) {
throw new M47ReferenceGraphContractError("M4.7 graph result: нарушена идентичность.");
@@ -219,5 +259,6 @@ export async function fetchM47ReferenceGraphLab({
queueHighWatermarks: queueWatermarks(metrics.queue_high_watermarks),
limitations: stringArray(report.limitations, "M4.7 limitations"),
visual,
semantic,
};
}
@@ -44,7 +44,7 @@ export function M47ReferenceGraphResultView({
},
{
label: "Визуал",
value: "VIDEO/CAMERA/3D/PLAN · единый recorded clock · exact M4.6 ledger binding",
value: "VIDEO/CAMERA/3D/PLAN · единый recorded clock · exact M4.6 + E47 semantic binding",
},
]}
brief={{
@@ -72,6 +72,13 @@ export function M47ReferenceGraphResultView({
role: "synchronized VIDEO/CAMERA/3D/PLAN evidence",
identitySha256: result.linkedVisualResultId.split("-").at(-1) ?? null,
},
{
kind: "source",
name: result.semantic.resultId,
version: "4489 exact camera masks",
role: "synchronized diagnostic semantic overlay",
identitySha256: result.semantic.resultId.split("-").at(-1) ?? null,
},
{
kind: "algorithm",
name: "canonical reference perception graph",
@@ -90,7 +97,13 @@ export function M47ReferenceGraphResultView({
kind="diagnostic-model"
resizable
>
<M4ReplayThreatVisual resultId={result.visual.resultId} />
<M4ReplayThreatVisual
resultId={result.visual.resultId}
semantic={{
resultId: result.semantic.resultId,
taxonomy: result.semantic.taxonomy,
}}
/>
</LaboratoryEvidence>
)}
result={(
@@ -127,6 +127,21 @@ test("E47 accepts only a fully accounted diagnostic semantic/SLAM view", async (
);
});
test("E47 fetches one exact content-addressed semantic result", async () => {
const requests = [];
const result = await fetchE47SemanticSlamResult({
resultId,
fetcher: async (input) => {
requests.push(String(input));
return new Response(JSON.stringify(resultView()));
},
});
assert.equal(result.resultId, resultId);
assert.deepEqual(requests, [
`/api/v1/laboratory/e47-semantic-slam/results/${resultId}`,
]);
});
test("E47 rejects result-level point accounting drift", async () => {
await assert.rejects(
fetchE47SemanticSlamResult({
@@ -9,6 +9,7 @@ let fetchM47ReferenceGraphLab;
const resultId = `m47-reference-graph-lab-${"a".repeat(64)}`;
const graphResultId = `m47-reference-graph-${"b".repeat(64)}`;
const visualResultId = `m4-threat-replay-${"c".repeat(64)}`;
const semanticResultId = `e47-semantic-slam-${"d".repeat(64)}`;
before(async () => {
server = await createServer({
@@ -81,6 +82,62 @@ function m4Result() {
};
}
function semanticResult() {
return {
schema_version: "missioncore.e47-semantic-slam-view/v1",
result_id: semanticResultId,
created_at_utc: "2026-08-06T08:13:48.601Z",
status: "diagnostic-semantic-slam-shadow",
profile_id: "ravnoves00-eomt-kb4-slam-shadow/v1",
base_m4_result_id: visualResultId,
semantic_result_id: `result-${"e".repeat(64)}`,
geometry_result_id: `m4-geometry-replay-${"f".repeat(64)}`,
source_pack_id: `e10-lidar-pack-${"1".repeat(64)}`,
calibration_content_sha256: "2".repeat(64),
provider: {
provider_id: "eomt-cityscapes-semantic-control/v1",
model_id: "cityscapes-semantic-eomt",
model_revision: "3".repeat(40),
model_weights_sha256: "4".repeat(64),
preprocess_id: "raw-kb4-valid-fov-semantic/v1",
},
temporal_binding: {
semantic_to_camera: "exact-sequence-and-session-time",
camera_to_lidar: "accepted-e6-nearest-host-arrival-best-effort",
clock_basis: "recorded-host-monotonic-arrival",
maximum_lidar_camera_delta_ms: 100,
maximum_pose_point_delta_ms: 100,
physical_synchronization_proven: false,
},
taxonomy: [{
class_id: 1,
label: "road",
disposition: "labeled",
color_rgb: [128, 64, 128],
}],
metrics: {
frames: { total: 4489, mask_available: 4489, source_available: 3928 },
points: { total: 1, projected: 1, labeled: 1, ambiguous: 0, unprojected: 0, absent: 0 },
observations: { total: 1, labeled: 1, ambiguous: 0, unprojected: 0, absent: 0 },
runtime: { elapsed_ms: 1000, frames_per_second: 4.489 },
},
acceptance: {
artifact_contract_passed: true,
frame_accounting_passed: true,
point_accounting_passed: true,
observation_binding_passed: true,
temporal_binding_passed: true,
independent_semantic_truth_passed: false,
provider_promoted: false,
},
limitations: ["diagnostic only"],
ground_truth: false,
semantic_authority: "diagnostic-only",
navigation_or_safety_accepted: false,
actuation_allowed: false,
};
}
function evidenceReport() {
const mismatch = {
source_binding: 0,
@@ -92,7 +149,7 @@ function evidenceReport() {
threat_assessments: 0,
};
const raw = {
schema_version: "missioncore.reference-perception-graph-lab-report/v1",
schema_version: "missioncore.reference-perception-graph-lab-report/v2",
result_id: resultId,
source: { graph_result_id: graphResultId },
method: { graph_id: "reference-perception-graph/v2" },
@@ -122,8 +179,11 @@ function evidenceReport() {
},
visual_evidence: {
linked_result_id: visualResultId,
semantic_result_id: semanticResultId,
shared_recorded_clock: true,
video_camera_3d_plan_available: true,
camera_semantic_overlay_available: true,
semantic_binding: "exact-sequence-and-session-time",
},
limitations: ["recorded replay only"],
};
@@ -134,13 +194,13 @@ function evidenceReport() {
created_at_utc: "2026-08-23T18:00:16.061Z",
access: "read-only",
proof: {
document_schema_version: "missioncore.reference-perception-graph-lab/v1",
document_schema_version: "missioncore.reference-perception-graph-lab/v2",
document_sha256: "3".repeat(64),
identity_sha256: "a".repeat(64),
report_schema_version: raw.schema_version,
report_sha256: "4".repeat(64),
artifact_count: 6,
verified_artifact_count: 6,
artifact_count: 9,
verified_artifact_count: 9,
},
completeness: { identity: "recorded" },
identity: { authority: raw.authority },
@@ -167,14 +227,16 @@ test("M4.7 binds exact Worker graph proof to the synchronized M4.6 visual", asyn
fetcher: async (input) => {
const path = String(input);
requests.push(path);
return new Response(JSON.stringify(
path.includes("/evidence-reports/") ? evidenceReport() : m4Result(),
), { status: 200 });
const payload = path.includes("/evidence-reports/")
? evidenceReport()
: path.includes("/e47-semantic-slam/") ? semanticResult() : m4Result();
return new Response(JSON.stringify(payload), { status: 200 });
},
});
assert.equal(result.graphResultId, graphResultId);
assert.equal(result.visual.resultId, visualResultId);
assert.equal(result.semantic.resultId, semanticResultId);
assert.equal(result.worker.id, "worker-006");
assert.equal(result.frames.delivered, 4489);
assert.deepEqual(Object.values(result.parityMismatchCounts), Array(7).fill(0));
@@ -182,6 +244,7 @@ test("M4.7 binds exact Worker graph proof to the synchronized M4.6 visual", asyn
assert.deepEqual(requests, [
`/api/v1/laboratory/evidence-reports/m47-reference-graph-shadow/${resultId}`,
`/api/v1/laboratory/m4-threat/results/${visualResultId}`,
`/api/v1/laboratory/e47-semantic-slam/results/${semanticResultId}`,
]);
});
@@ -198,6 +261,9 @@ test("M4.7 keeps exact visual binding during a rolling API deployment", async ()
if (path.endsWith(`/${visualResultId}`)) {
return new Response(null, { status: 404 });
}
if (path.includes("/e47-semantic-slam/")) {
return new Response(JSON.stringify(semanticResult()), { status: 200 });
}
return new Response(JSON.stringify({
schema_version: "missioncore.m4-threat-replay-catalog/v1",
items: [m4Result()],
@@ -210,5 +276,6 @@ test("M4.7 keeps exact visual binding during a rolling API deployment", async ()
`/api/v1/laboratory/evidence-reports/m47-reference-graph-shadow/${resultId}`,
`/api/v1/laboratory/m4-threat/results/${visualResultId}`,
"/api/v1/laboratory/m4-threat/results?limit=10",
`/api/v1/laboratory/e47-semantic-slam/results/${semanticResultId}`,
]);
});
@@ -5,6 +5,6 @@
"runtime_relative_root": "m47/reference-graph-labs",
"result_id_prefix": "m47-reference-graph-lab",
"document_name": "manifest.json",
"schema_version": "missioncore.reference-perception-graph-lab/v1"
"schema_version": "missioncore.reference-perception-graph-lab/v2"
}
}
@@ -14,11 +14,13 @@ def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--graph-result-root", type=Path, required=True)
parser.add_argument("--visual-result-root", type=Path, required=True)
parser.add_argument("--semantic-result-root", type=Path, required=True)
parser.add_argument("--output-root", type=Path, required=True)
args = parser.parse_args()
result = publish_m47_reference_graph_lab(
graph_result_root=args.graph_result_root,
visual_result_root=args.visual_result_root,
semantic_result_root=args.semantic_result_root,
output_root=args.output_root,
)
print(
+40 -4
View File
@@ -12,11 +12,17 @@ from pathlib import Path
from typing import Final
from k1link.perception.reference_graph_result import read_reference_graph_result
from k1link.perception.semantic_slam_replay import (
SEMANTIC_SLAM_MANIFEST_NAME,
SEMANTIC_SLAM_REPORT_NAME,
SEMANTIC_SLAM_TAXONOMY_NAME,
read_semantic_slam_replay_result,
)
from k1link.perception.threat_replay import read_threat_replay_result
M47_REFERENCE_GRAPH_LAB_SCHEMA: Final = "missioncore.reference-perception-graph-lab/v1"
M47_REFERENCE_GRAPH_LAB_SCHEMA: Final = "missioncore.reference-perception-graph-lab/v2"
M47_REFERENCE_GRAPH_LAB_REPORT_SCHEMA: Final = (
"missioncore.reference-perception-graph-lab-report/v1"
"missioncore.reference-perception-graph-lab-report/v2"
)
M47_REFERENCE_GRAPH_LAB_PREFIX: Final = "m47-reference-graph-lab-"
@@ -37,10 +43,12 @@ def publish_m47_reference_graph_lab(
*,
graph_result_root: Path,
visual_result_root: Path,
semantic_result_root: Path,
output_root: Path,
) -> M47ReferenceGraphLab:
graph = read_reference_graph_result(graph_result_root)
visual = read_threat_replay_result(visual_result_root)
semantic = read_semantic_slam_replay_result(semantic_result_root)
if not graph.accepted or not visual.accepted:
raise M47ReferenceGraphLabError("both graph and visual replay must be accepted")
graph_report = graph.report
@@ -49,6 +57,9 @@ def publish_m47_reference_graph_lab(
parity = _object(graph_report.get("accepted_parity"), "graph parity")
mismatches = _object(parity.get("mismatch_counts"), "graph parity mismatches")
visual_identity = _object(visual.manifest.get("identity"), "visual identity")
semantic_identity = _object(semantic.manifest.get("identity"), "semantic identity")
semantic_frames = _object(semantic_identity.get("counts"), "semantic counts")
semantic_frame_counts = _object(semantic_frames.get("frames"), "semantic frame counts")
if (
parity.get("accepted") is not True
or parity.get("expected_frames") != 4489
@@ -68,6 +79,13 @@ def publish_m47_reference_graph_lab(
or parity.get("temporal_frames_sha256") != visual_identity.get("temporal_frames_sha256")
):
raise M47ReferenceGraphLabError("graph-to-visual parity proof changed")
if (
semantic_identity.get("base_m4_result_id") != visual.result_id
or semantic_identity.get("source_session_id") != visual_identity.get("source_session_id")
or semantic_frame_counts.get("total") != 4489
or semantic_frame_counts.get("mask_available") != 4489
):
raise M47ReferenceGraphLabError("semantic-to-visual binding proof changed")
terminal = _object(graph_report.get("terminal_outcomes"), "terminal outcomes")
queues = _object(graph_report.get("queue_high_watermarks"), "queue high watermarks")
execution = _object(graph_report.get("execution"), "graph execution")
@@ -81,23 +99,30 @@ def publish_m47_reference_graph_lab(
}
visual_evidence = {
"linked_result_id": visual.result_id,
"semantic_result_id": semantic.result_id,
"binding": "exact-threat-and-temporal-ledger-parity",
"semantic_binding": "exact-sequence-and-session-time",
"timeline_frames": 4489,
"shared_recorded_clock": True,
"video_camera_3d_plan_available": True,
"camera_semantic_overlay_available": True,
"regression_sequences": [138, 274, 1880, 2584],
"independent_ground_truth": False,
}
identity: dict[str, object] = {
"schema_version": M47_REFERENCE_GRAPH_LAB_SCHEMA,
"binding_id": "m47-reference-graph-visual-binding/v1",
"binding_id": "m47-reference-graph-visual-binding/v2",
"source": {
"source_id": "RAVNOVES00",
"source_session_id": visual_identity.get("source_session_id"),
"graph_result_id": graph.result_id,
"visual_result_id": visual.result_id,
"semantic_result_id": semantic.result_id,
"temporal_frames_sha256": parity.get("temporal_frames_sha256"),
"threat_frames_sha256": parity.get("threat_frames_sha256"),
"semantic_frames_sha256": semantic_identity.get("semantic_frames_sha256"),
"semantic_masks_sha256": semantic_identity.get("semantic_masks_sha256"),
"semantic_taxonomy_sha256": semantic_identity.get("taxonomy_sha256"),
},
"method": {
"graph_id": graph_manifest.get("graph_id"),
@@ -179,6 +204,9 @@ def publish_m47_reference_graph_lab(
"graph-runtime.json": graph.result_root / "runtime.json",
"visual-manifest.json": visual.result_root / "manifest.json",
"visual-report.json": visual.result_root / "report.json",
"semantic-manifest.json": semantic.result_root / SEMANTIC_SLAM_MANIFEST_NAME,
"semantic-report.json": semantic.result_root / SEMANTIC_SLAM_REPORT_NAME,
"semantic-taxonomy.json": semantic.result_root / SEMANTIC_SLAM_TAXONOMY_NAME,
}
for name, source in sources.items():
shutil.copyfile(source, staging / name)
@@ -190,6 +218,9 @@ def publish_m47_reference_graph_lab(
"graph-runtime.json": "m47-runtime",
"visual-manifest.json": "linked-visual-manifest",
"visual-report.json": "linked-visual-report",
"semantic-manifest.json": "linked-semantic-manifest",
"semantic-report.json": "linked-semantic-report",
"semantic-taxonomy.json": "linked-semantic-taxonomy",
}
schemas = {
"graph-manifest.json": graph_manifest.get("schema_version"),
@@ -197,6 +228,11 @@ def publish_m47_reference_graph_lab(
"graph-runtime.json": graph_runtime.get("schema_version"),
"visual-manifest.json": visual.manifest.get("schema_version"),
"visual-report.json": visual.report.get("schema_version"),
"semantic-manifest.json": semantic.manifest.get("schema_version"),
"semantic-report.json": semantic.report.get("schema_version"),
"semantic-taxonomy.json": _read_json(
semantic.result_root / SEMANTIC_SLAM_TAXONOMY_NAME
).get("schema_version"),
"report.json": M47_REFERENCE_GRAPH_LAB_REPORT_SCHEMA,
}
artifacts = [_artifact(staging / name, role, schemas[name]) for name, role in roles.items()]
@@ -247,7 +283,7 @@ def read_m47_reference_graph_lab(result_root: Path) -> M47ReferenceGraphLab:
):
raise M47ReferenceGraphLabError("M4.7 LAB identity changed")
artifacts = manifest.get("artifacts")
if not isinstance(artifacts, list) or len(artifacts) != 6:
if not isinstance(artifacts, list) or len(artifacts) != 9:
raise M47ReferenceGraphLabError("M4.7 LAB artifact inventory changed")
for value in artifacts:
descriptor = _object(value, "LAB artifact")
+4
View File
@@ -137,6 +137,10 @@ def build_e47_semantic_slam_router(
"access": "read-only-diagnostic-shadow",
}
@router.get("/results/{result_id}")
def get_result(result_id: str) -> dict[str, object]:
return _project_result(result(result_id))
@router.get("/results/{result_id}/timeline/chunk")
def get_timeline_chunk(
result_id: str,
+8 -3
View File
@@ -173,9 +173,7 @@ def test_catalog_projects_exact_diagnostic_only_view(
assert item["status"] == "diagnostic-semantic-slam-shadow"
assert item["base_m4_result_id"] == M4_RESULT_ID
assert item["provider"]["provider_id"] == "eomt-cityscapes-semantic-control/v1"
assert item["temporal_binding"]["semantic_to_camera"] == (
"exact-sequence-and-session-time"
)
assert item["temporal_binding"]["semantic_to_camera"] == ("exact-sequence-and-session-time")
assert item["temporal_binding"]["physical_synchronization_proven"] is False
assert [entry["label"] for entry in item["taxonomy"]] == ["ambiguous", "road"]
assert item["acceptance"] == {
@@ -191,6 +189,13 @@ def test_catalog_projects_exact_diagnostic_only_view(
assert item["navigation_or_safety_accepted"] is False
assert item["actuation_allowed"] is False
get_result = _endpoint(
"/api/v1/laboratory/e47-semantic-slam/results/{result_id}",
root,
)
exact = get_result(RESULT_ID)
assert exact == item
def test_timeline_chunk_preserves_point_index_space_and_unavailable_sentinel(
publication: tuple[Path, Path],
+38 -2
View File
@@ -25,8 +25,10 @@ def test_m47_lab_binds_worker_graph_to_exact_visual_replay(
) -> None:
graph_root = tmp_path / "graph"
visual_root = tmp_path / "visual"
semantic_root = tmp_path / "semantic"
graph_root.mkdir()
visual_root.mkdir()
semantic_root.mkdir()
runtime = {
"schema_version": "missioncore.reference-graph-runtime-identity/v3",
"worker_id": "worker-006",
@@ -99,6 +101,20 @@ def test_m47_lab_binds_worker_graph_to_exact_visual_replay(
},
}
visual_report = {"schema_version": "missioncore.perception-threat-replay-report/v2"}
semantic_identity = {
"base_m4_result_id": "m4-threat-replay-" + "6" * 64,
"source_session_id": "20260720T065719Z_viewer_live",
"semantic_frames_sha256": "7" * 64,
"semantic_masks_sha256": "8" * 64,
"taxonomy_sha256": "9" * 64,
"counts": {"frames": {"total": 4489, "mask_available": 4489}},
}
semantic_manifest = {
"schema_version": "missioncore.e47-semantic-slam-result/v1",
"identity": semantic_identity,
}
semantic_report = {"schema_version": "missioncore.e47-semantic-slam-report/v1"}
semantic_taxonomy = {"schema_version": "missioncore.e47-semantic-taxonomy/v1"}
for root, documents in (
(
graph_root,
@@ -112,6 +128,14 @@ def test_m47_lab_binds_worker_graph_to_exact_visual_replay(
visual_root,
{"manifest.json": visual_manifest, "report.json": visual_report},
),
(
semantic_root,
{
"manifest.json": semantic_manifest,
"report.json": semantic_report,
"taxonomy.json": semantic_taxonomy,
},
),
):
for name, document in documents.items():
_write_json(root / name, document)
@@ -129,6 +153,12 @@ def test_m47_lab_binds_worker_graph_to_exact_visual_replay(
manifest=visual_manifest,
report=visual_report,
)
semantic = SimpleNamespace(
result_id="e47-semantic-slam-" + "a" * 64,
result_root=semantic_root,
manifest=semantic_manifest,
report=semantic_report,
)
monkeypatch.setattr(
"k1link.laboratory.m47_reference_graph.read_reference_graph_result",
lambda _: graph,
@@ -137,16 +167,22 @@ def test_m47_lab_binds_worker_graph_to_exact_visual_replay(
"k1link.laboratory.m47_reference_graph.read_threat_replay_result",
lambda _: visual,
)
monkeypatch.setattr(
"k1link.laboratory.m47_reference_graph.read_semantic_slam_replay_result",
lambda _: semantic,
)
runtime_root = tmp_path / "runtime"
result = publish_m47_reference_graph_lab(
graph_result_root=graph_root,
visual_result_root=visual_root,
semantic_result_root=semantic_root,
output_root=runtime_root / "m47" / "reference-graph-labs",
)
assert read_m47_reference_graph_lab(result.result_root) == result
assert result.report["visual_evidence"]["linked_result_id"] == visual.result_id
assert result.report["visual_evidence"]["semantic_result_id"] == semantic.result_id
assert result.report["execution"]["worker_id"] == "worker-006"
assert result.report["metrics"]["parity_mismatch_counts"] == mismatch_counts
repository_root = Path(__file__).resolve().parents[1]
@@ -157,11 +193,11 @@ def test_m47_lab_binds_worker_graph_to_exact_visual_replay(
item for item in registry.definitions if item.work_id == "m47-reference-graph-shadow"
)
proof = verify_laboratory_evidence_result(definition, result.result_root)
assert proof["artifact_count"] == 6
assert proof["artifact_count"] == 9
projected = LaboratoryEvidenceReportService(registry, lambda: runtime_root).read(
definition.work_id,
result.result_id,
)
assert projected["raw_report"]["schema_version"] == (
"missioncore.reference-perception-graph-lab-report/v1"
"missioncore.reference-perception-graph-lab-report/v2"
)