feat(lab): canonize versioned report template
This commit is contained in:
@@ -96,15 +96,22 @@ function e33() {
|
||||
},
|
||||
metrics: {
|
||||
source_frames: 4489,
|
||||
source_available_frames: 3928,
|
||||
source_unavailable_frames: 561,
|
||||
delivered_frames: 4489,
|
||||
input_superseded: 0,
|
||||
result_superseded: 0,
|
||||
effective_delivery_fps: 10.006,
|
||||
source_span_seconds: 448.623,
|
||||
deadline_miss_fraction: 0,
|
||||
processing_p95_ms: 0.749,
|
||||
release_lag_p95_ms: 0.461,
|
||||
result_age_p95_ms: 2.668,
|
||||
result_age_max_ms: 13.638,
|
||||
result_deadline_ms: 100,
|
||||
process_rss_p95_mib: 90.32,
|
||||
process_rss_max_mib: 92.34,
|
||||
process_rss_limit_mib: 1024,
|
||||
gpu_utilization_p95_percent: 52,
|
||||
gpu_visible: true,
|
||||
work_queue_capacity: 2,
|
||||
@@ -147,6 +154,8 @@ test("decodes E31, E32 and E33 from separate read-only catalogs", async () => {
|
||||
assert.equal(decoded.e31.metrics.availableBindingCount, 3928);
|
||||
assert.equal(decoded.e32.metrics.qualifiedPointsPublished, 2119302);
|
||||
assert.equal(decoded.e33.metrics.deliveredFrames, 4489);
|
||||
assert.equal(decoded.e33.metrics.sourceAvailableFrames, 3928);
|
||||
assert.equal(decoded.e33.metrics.resultAgeMaxMs, 13.638);
|
||||
assert.deepEqual(requests, [
|
||||
{ input: "/api/v1/laboratory/e31/results?limit=1", method: "GET" },
|
||||
{ input: "/api/v1/laboratory/e32/results?limit=1", method: "GET" },
|
||||
|
||||
@@ -75,6 +75,7 @@ test("laboratory UI is a bounded feature slice, not a central workspace branch",
|
||||
);
|
||||
const workspaceCss = await read("styles/workspaces.css");
|
||||
const laboratoryCss = await read("styles/laboratory.css");
|
||||
const laboratoryReportingCss = await read("styles/laboratory-reporting.css");
|
||||
const e30Review = await read("workspaces/E30ReviewWorkspace.tsx");
|
||||
const e30HumanReview = await read(
|
||||
"workspaces/E30HumanReviewPanel.tsx",
|
||||
@@ -94,6 +95,8 @@ test("laboratory UI is a bounded feature slice, not a central workspace branch",
|
||||
assert.doesNotMatch(workspaceCss, /\.(?:lab-|laboratory-|e30-)/);
|
||||
assert.match(laboratoryCss, /\.laboratory-work-template/);
|
||||
assert.match(laboratoryCss, /\.e30-review-workspace/);
|
||||
assert.match(laboratoryReportingCss, /\.laboratory-summary__brief/);
|
||||
assert.match(laboratoryReportingCss, /\.laboratory-result-conclusion/);
|
||||
assert.doesNotMatch(laboratory, /E30HumanReviewPanel/);
|
||||
assert.match(e30Review, /<E30HumanReviewPanel/);
|
||||
assert.doesNotMatch(e30Review, /E30EngineeringAuditPanel/);
|
||||
@@ -109,6 +112,7 @@ test("central composition files cannot silently become monoliths again", async (
|
||||
["workspaces/laboratory/LaboratoryArchiveWorkspace.tsx", 1_000],
|
||||
["styles/workspaces.css", 4_350],
|
||||
["styles/laboratory.css", 900],
|
||||
["styles/laboratory-reporting.css", 100],
|
||||
];
|
||||
|
||||
for (const [relativePath, maximumLines] of ratchets) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { readdir, readFile } from "node:fs/promises";
|
||||
import { test } from "node:test";
|
||||
|
||||
const workspaceSourceUrl = new URL(
|
||||
@@ -18,6 +18,18 @@ const laboratoryStylesUrl = new URL(
|
||||
"../src/styles/laboratory.css",
|
||||
import.meta.url,
|
||||
);
|
||||
const e33ResultUrl = new URL(
|
||||
"../src/workspaces/laboratory/E33Result.tsx",
|
||||
import.meta.url,
|
||||
);
|
||||
const workspacesUrl = new URL(
|
||||
"../src/workspaces/Workspaces.tsx",
|
||||
import.meta.url,
|
||||
);
|
||||
const laboratoryResultsUrl = new URL(
|
||||
"../src/workspaces/laboratory/",
|
||||
import.meta.url,
|
||||
);
|
||||
|
||||
test("E30 uses one reusable evidence viewer with camera, 3D and expand controls", async () => {
|
||||
const [workspaceSource, viewerSource, laboratoryStyles] = await Promise.all([
|
||||
@@ -75,6 +87,60 @@ test("LAB product surface has a compact canonical summary and no roadmap footer"
|
||||
|
||||
assert.match(presentationSource, /export function LaboratorySummary/);
|
||||
assert.match(presentationSource, /export function LaboratoryWorkTemplate/);
|
||||
assert.match(
|
||||
presentationSource,
|
||||
/LABORATORY_REPORT_TEMPLATE_VERSION\s*=\s*\n?\s*"missioncore\.laboratory-report\/v1"/,
|
||||
);
|
||||
assert.match(presentationSource, /brief: LaboratoryBrief;/);
|
||||
assert.doesNotMatch(presentationSource, /brief\?: LaboratoryBrief/);
|
||||
assert.match(presentationSource, /data-template-contract=\{LABORATORY_REPORT_TEMPLATE_VERSION\}/);
|
||||
assert.doesNotMatch(workspaceSource, /СЛЕДУЮЩИЙ GATE/);
|
||||
assert.doesNotMatch(workspaceSource, /e30-review-workspace__taxonomy/);
|
||||
});
|
||||
|
||||
test("bounded LAB result modules use the versioned shared report anatomy", async () => {
|
||||
const resultNames = (await readdir(laboratoryResultsUrl))
|
||||
.filter((name) => /^E\d+Result\.tsx$/.test(name))
|
||||
.sort();
|
||||
|
||||
assert.ok(resultNames.length >= 3);
|
||||
|
||||
for (const resultName of resultNames) {
|
||||
const source = await readFile(new URL(resultName, laboratoryResultsUrl), "utf8");
|
||||
assert.match(source, /<LaboratoryWorkTemplate/, `${resultName} bypasses the LAB template`);
|
||||
assert.match(source, /brief=\{\{/, `${resultName} omits the canonical four-part brief`);
|
||||
assert.match(source, /<LaboratoryResultSummary/, `${resultName} invents a result layout`);
|
||||
assert.doesNotMatch(
|
||||
source,
|
||||
/className="laboratory-(?:summary|result-summary)"/,
|
||||
`${resultName} owns canonical report geometry`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("E33 explains the experiment, its method and its retained limits", async () => {
|
||||
const [presentationSource, e33Source] = await Promise.all([
|
||||
readFile(presentationSourceUrl, "utf8"),
|
||||
readFile(e33ResultUrl, "utf8"),
|
||||
]);
|
||||
|
||||
assert.match(presentationSource, /export interface LaboratoryBrief/);
|
||||
assert.match(presentationSource, /export function LaboratoryConclusion/);
|
||||
assert.match(presentationSource, /export function LaboratoryResultSummary/);
|
||||
assert.match(e33Source, /Проверяли не качество распознавания объектов/);
|
||||
assert.match(e33Source, /Recorded pacing \+ bounded latest-wins queues/);
|
||||
assert.match(e33Source, /Детектор, semantic-модели и качество геометрии здесь не пересчитывались/);
|
||||
assert.match(e33Source, /sourceUnavailableFrames/);
|
||||
assert.match(e33Source, /не включает команды, навигацию или safety/);
|
||||
assert.doesNotMatch(e33Source, /GPU \{metrics\.gpuUtilizationP95Percent/);
|
||||
assert.doesNotMatch(e33Source, /name: result\.e32ResultId/);
|
||||
});
|
||||
|
||||
test("the primary point-cloud viewer restores from fullscreen on Escape", async () => {
|
||||
const workspacesSource = await readFile(workspacesUrl, "utf8");
|
||||
|
||||
assert.match(workspacesSource, /if \(!pointCloudFocused\) return;/);
|
||||
assert.match(workspacesSource, /event\.key !== "Escape"/);
|
||||
assert.match(workspacesSource, /observationLayout\.setFocusedSourceId\(null\)/);
|
||||
assert.match(workspacesSource, /window\.addEventListener\("keydown", onKeyDown\)/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user