feat(lab): publish E39 refinement result
This commit is contained in:
@@ -179,6 +179,48 @@ export interface E38PerceptionBaselineResult {
|
|||||||
access: "read-only";
|
access: "read-only";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface E39DevelopmentDimensionMetric {
|
||||||
|
correct: number;
|
||||||
|
incorrect: number;
|
||||||
|
total: number;
|
||||||
|
accuracy: number;
|
||||||
|
target: number;
|
||||||
|
passed: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface E39PerceptionRefinementResult {
|
||||||
|
resultId: string;
|
||||||
|
createdAtUtc: string | null;
|
||||||
|
sourceSessionId: string;
|
||||||
|
sourceDisplayName: string;
|
||||||
|
status: "measured-r1-source-scoped-refinement";
|
||||||
|
profileId: string;
|
||||||
|
workerNode: string;
|
||||||
|
qualityGatePassed: boolean;
|
||||||
|
developmentCrossValidation: {
|
||||||
|
strategy: string;
|
||||||
|
seed: string;
|
||||||
|
folds: number;
|
||||||
|
items: number;
|
||||||
|
validationLabelsUsed: false;
|
||||||
|
passed: boolean;
|
||||||
|
dimensions: {
|
||||||
|
presence: E39DevelopmentDimensionMetric;
|
||||||
|
geometryAssociation: E39DevelopmentDimensionMetric;
|
||||||
|
freshness: E39DevelopmentDimensionMetric;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
metrics: E38PerceptionBaselineResult["metrics"];
|
||||||
|
blockingChecks: readonly string[];
|
||||||
|
method: {
|
||||||
|
summary: string;
|
||||||
|
selection: string;
|
||||||
|
dimensionProjection: string;
|
||||||
|
};
|
||||||
|
limitations: readonly string[];
|
||||||
|
access: "read-only";
|
||||||
|
}
|
||||||
|
|
||||||
export interface AdvancedLaboratoryResults {
|
export interface AdvancedLaboratoryResults {
|
||||||
e31: E31LaboratoryResult | null;
|
e31: E31LaboratoryResult | null;
|
||||||
e32: E32LaboratoryResult | null;
|
e32: E32LaboratoryResult | null;
|
||||||
@@ -187,6 +229,7 @@ export interface AdvancedLaboratoryResults {
|
|||||||
e35: E35DegradationRecoveryResult | null;
|
e35: E35DegradationRecoveryResult | null;
|
||||||
e37: E37AcceptanceContractResult | null;
|
e37: E37AcceptanceContractResult | null;
|
||||||
e38: E38PerceptionBaselineResult | null;
|
e38: E38PerceptionBaselineResult | null;
|
||||||
|
e39: E39PerceptionRefinementResult | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AdvancedLaboratoryContractError extends Error {
|
export class AdvancedLaboratoryContractError extends Error {
|
||||||
@@ -248,6 +291,13 @@ function trueValue(value: unknown, label: string): true {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function falseValue(value: unknown, label: string): false {
|
||||||
|
if (value !== false) {
|
||||||
|
throw new AdvancedLaboratoryContractError(`${label}: ожидалось false.`);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function finiteNumber(value: unknown, label: string): number {
|
function finiteNumber(value: unknown, label: string): number {
|
||||||
if (typeof value !== "number" || !Number.isFinite(value)) {
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
||||||
throw new AdvancedLaboratoryContractError(`${label}: ожидалось число.`);
|
throw new AdvancedLaboratoryContractError(`${label}: ожидалось число.`);
|
||||||
@@ -728,6 +778,155 @@ function parseE38(value: unknown): E38PerceptionBaselineResult {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseE39DevelopmentDimension(
|
||||||
|
value: unknown,
|
||||||
|
label: string,
|
||||||
|
): E39DevelopmentDimensionMetric {
|
||||||
|
const source = record(value, label);
|
||||||
|
return {
|
||||||
|
correct: integerValue(source.correct, `${label}.correct`),
|
||||||
|
incorrect: integerValue(source.incorrect, `${label}.incorrect`),
|
||||||
|
total: integerValue(source.total, `${label}.total`),
|
||||||
|
accuracy: numberValue(source.accuracy, `${label}.accuracy`),
|
||||||
|
target: numberValue(source.target, `${label}.target`),
|
||||||
|
passed: booleanValue(source.passed, `${label}.passed`),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseE39(value: unknown): E39PerceptionRefinementResult {
|
||||||
|
const item = record(value, "E39");
|
||||||
|
const metrics = record(item.metrics, "E39.metrics");
|
||||||
|
const dimensions = record(metrics.dimensions, "E39.metrics.dimensions");
|
||||||
|
const developmentCrossValidation = record(
|
||||||
|
item.development_cross_validation,
|
||||||
|
"E39.development_cross_validation",
|
||||||
|
);
|
||||||
|
const developmentDimensions = record(
|
||||||
|
developmentCrossValidation.dimensions,
|
||||||
|
"E39.development_cross_validation.dimensions",
|
||||||
|
);
|
||||||
|
const method = record(item.method, "E39.method");
|
||||||
|
diagnosticAuthority(item.authority, "E39.authority");
|
||||||
|
return {
|
||||||
|
resultId: contentId(
|
||||||
|
item.result_id,
|
||||||
|
"e39-perception-refinement",
|
||||||
|
"E39.result_id",
|
||||||
|
),
|
||||||
|
createdAtUtc: optionalString(item.created_at_utc, "E39.created_at_utc"),
|
||||||
|
sourceSessionId: stringValue(
|
||||||
|
item.source_session_id,
|
||||||
|
"E39.source_session_id",
|
||||||
|
),
|
||||||
|
sourceDisplayName: stringValue(
|
||||||
|
item.source_display_name,
|
||||||
|
"E39.source_display_name",
|
||||||
|
),
|
||||||
|
status: exactString(
|
||||||
|
item.status,
|
||||||
|
"measured-r1-source-scoped-refinement",
|
||||||
|
"E39.status",
|
||||||
|
),
|
||||||
|
profileId: stringValue(item.profile_id, "E39.profile_id"),
|
||||||
|
workerNode: stringValue(item.worker_node, "E39.worker_node"),
|
||||||
|
qualityGatePassed: booleanValue(
|
||||||
|
item.quality_gate_passed,
|
||||||
|
"E39.quality_gate_passed",
|
||||||
|
),
|
||||||
|
developmentCrossValidation: {
|
||||||
|
strategy: stringValue(
|
||||||
|
developmentCrossValidation.strategy,
|
||||||
|
"E39.development_cross_validation.strategy",
|
||||||
|
),
|
||||||
|
seed: stringValue(
|
||||||
|
developmentCrossValidation.seed,
|
||||||
|
"E39.development_cross_validation.seed",
|
||||||
|
),
|
||||||
|
folds: integerValue(
|
||||||
|
developmentCrossValidation.folds,
|
||||||
|
"E39.development_cross_validation.folds",
|
||||||
|
),
|
||||||
|
items: integerValue(
|
||||||
|
developmentCrossValidation.items,
|
||||||
|
"E39.development_cross_validation.items",
|
||||||
|
),
|
||||||
|
validationLabelsUsed: falseValue(
|
||||||
|
developmentCrossValidation.validation_labels_used,
|
||||||
|
"E39.development_cross_validation.validation_labels_used",
|
||||||
|
),
|
||||||
|
passed: booleanValue(
|
||||||
|
developmentCrossValidation.passed,
|
||||||
|
"E39.development_cross_validation.passed",
|
||||||
|
),
|
||||||
|
dimensions: {
|
||||||
|
presence: parseE39DevelopmentDimension(
|
||||||
|
developmentDimensions.presence,
|
||||||
|
"E39.development_cross_validation.dimensions.presence",
|
||||||
|
),
|
||||||
|
geometryAssociation: parseE39DevelopmentDimension(
|
||||||
|
developmentDimensions.geometry_association,
|
||||||
|
"E39.development_cross_validation.dimensions.geometry_association",
|
||||||
|
),
|
||||||
|
freshness: parseE39DevelopmentDimension(
|
||||||
|
developmentDimensions.freshness,
|
||||||
|
"E39.development_cross_validation.dimensions.freshness",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metrics: {
|
||||||
|
developmentItems: integerValue(
|
||||||
|
metrics.development_items,
|
||||||
|
"E39.metrics.development_items",
|
||||||
|
),
|
||||||
|
validationItems: integerValue(
|
||||||
|
metrics.validation_items,
|
||||||
|
"E39.metrics.validation_items",
|
||||||
|
),
|
||||||
|
terminalOutcomes: integerValue(
|
||||||
|
metrics.terminal_outcomes,
|
||||||
|
"E39.metrics.terminal_outcomes",
|
||||||
|
),
|
||||||
|
accountingFraction: numberValue(
|
||||||
|
metrics.accounting_fraction,
|
||||||
|
"E39.metrics.accounting_fraction",
|
||||||
|
),
|
||||||
|
falseFreeClaims: integerValue(
|
||||||
|
metrics.false_free_claims,
|
||||||
|
"E39.metrics.false_free_claims",
|
||||||
|
),
|
||||||
|
highSeverityFailures: integerValue(
|
||||||
|
metrics.high_severity_failures,
|
||||||
|
"E39.metrics.high_severity_failures",
|
||||||
|
),
|
||||||
|
dimensions: {
|
||||||
|
presence: parseE38Dimension(
|
||||||
|
dimensions.presence,
|
||||||
|
"E39.metrics.dimensions.presence",
|
||||||
|
),
|
||||||
|
geometryAssociation: parseE38Dimension(
|
||||||
|
dimensions.geometry_association,
|
||||||
|
"E39.metrics.dimensions.geometry_association",
|
||||||
|
),
|
||||||
|
freshness: parseE38Dimension(
|
||||||
|
dimensions.freshness,
|
||||||
|
"E39.metrics.dimensions.freshness",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
blockingChecks: strings(item.blocking_checks, "E39.blocking_checks"),
|
||||||
|
method: {
|
||||||
|
summary: stringValue(method.summary, "E39.method.summary"),
|
||||||
|
selection: stringValue(method.selection, "E39.method.selection"),
|
||||||
|
dimensionProjection: stringValue(
|
||||||
|
method.dimension_projection,
|
||||||
|
"E39.method.dimension_projection",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
limitations: strings(item.limitations, "E39.limitations"),
|
||||||
|
access: exactString(item.access, "read-only", "E39.access"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchOne<T>(
|
async function fetchOne<T>(
|
||||||
path: string,
|
path: string,
|
||||||
parser: (value: unknown) => T,
|
parser: (value: unknown) => T,
|
||||||
@@ -752,7 +951,7 @@ export async function fetchAdvancedLaboratoryResults({
|
|||||||
fetcher?: LaboratoryFetch;
|
fetcher?: LaboratoryFetch;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
} = {}): Promise<AdvancedLaboratoryResults> {
|
} = {}): Promise<AdvancedLaboratoryResults> {
|
||||||
const [e31, e32, e33, e34, e35, e37, e38] = await Promise.all([
|
const [e31, e32, e33, e34, e35, e37, e38, e39] = await Promise.all([
|
||||||
fetchOne("/api/v1/laboratory/e31/results?limit=1", parseE31, fetcher, signal),
|
fetchOne("/api/v1/laboratory/e31/results?limit=1", parseE31, fetcher, signal),
|
||||||
fetchOne("/api/v1/laboratory/e32/results?limit=1", parseE32, fetcher, signal),
|
fetchOne("/api/v1/laboratory/e32/results?limit=1", parseE32, fetcher, signal),
|
||||||
fetchOne("/api/v1/laboratory/e33/results?limit=1", parseE33, fetcher, signal),
|
fetchOne("/api/v1/laboratory/e33/results?limit=1", parseE33, fetcher, signal),
|
||||||
@@ -760,8 +959,9 @@ export async function fetchAdvancedLaboratoryResults({
|
|||||||
fetchE35DegradationRecoveryResult({ fetcher, signal }),
|
fetchE35DegradationRecoveryResult({ fetcher, signal }),
|
||||||
fetchOne("/api/v1/laboratory/e37/results?limit=1", parseE37, fetcher, signal),
|
fetchOne("/api/v1/laboratory/e37/results?limit=1", parseE37, fetcher, signal),
|
||||||
fetchOne("/api/v1/laboratory/e38/results?limit=1", parseE38, fetcher, signal),
|
fetchOne("/api/v1/laboratory/e38/results?limit=1", parseE38, fetcher, signal),
|
||||||
|
fetchOne("/api/v1/laboratory/e39/results?limit=1", parseE39, fetcher, signal),
|
||||||
]);
|
]);
|
||||||
return { e31, e32, e33, e34, e35, e37, e38 };
|
return { e31, e32, e33, e34, e35, e37, e38, e39 };
|
||||||
}
|
}
|
||||||
import {
|
import {
|
||||||
fetchE34TemporalLayerResult,
|
fetchE34TemporalLayerResult,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { E34Result } from "./E34Result";
|
|||||||
import { E35Result } from "./E35Result";
|
import { E35Result } from "./E35Result";
|
||||||
import { E37Result } from "./E37Result";
|
import { E37Result } from "./E37Result";
|
||||||
import { E38Result } from "./E38Result";
|
import { E38Result } from "./E38Result";
|
||||||
|
import { E39Result } from "./E39Result";
|
||||||
import { RecordedReplayEvidence } from "./RecordedReplayEvidence";
|
import { RecordedReplayEvidence } from "./RecordedReplayEvidence";
|
||||||
|
|
||||||
export type AdvancedLaboratoryWorkId =
|
export type AdvancedLaboratoryWorkId =
|
||||||
@@ -20,7 +21,8 @@ export type AdvancedLaboratoryWorkId =
|
|||||||
| "e34-temporal-layer"
|
| "e34-temporal-layer"
|
||||||
| "e35-degradation-recovery"
|
| "e35-degradation-recovery"
|
||||||
| "e37-ravnoves-acceptance"
|
| "e37-ravnoves-acceptance"
|
||||||
| "e38-perception-baseline";
|
| "e38-perception-baseline"
|
||||||
|
| "e39-perception-refinement";
|
||||||
|
|
||||||
type LaboratoryWorkspaceProps = WorkspaceRendererProps & {
|
type LaboratoryWorkspaceProps = WorkspaceRendererProps & {
|
||||||
SpatialView: ComponentType<WorkspaceRendererProps>;
|
SpatialView: ComponentType<WorkspaceRendererProps>;
|
||||||
@@ -37,6 +39,7 @@ export function isAdvancedLaboratoryWorkId(
|
|||||||
|| value === "e35-degradation-recovery"
|
|| value === "e35-degradation-recovery"
|
||||||
|| value === "e37-ravnoves-acceptance"
|
|| value === "e37-ravnoves-acceptance"
|
||||||
|| value === "e38-perception-baseline"
|
|| value === "e38-perception-baseline"
|
||||||
|
|| value === "e39-perception-refinement"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +90,12 @@ export function advancedLaboratoryWorkOptions(
|
|||||||
label: "LAB E38 · perception quality R1",
|
label: "LAB E38 · perception quality R1",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (results.e39) {
|
||||||
|
options.push({
|
||||||
|
id: "e39-perception-refinement",
|
||||||
|
label: "LAB E39 · perception refinement R1",
|
||||||
|
});
|
||||||
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +133,9 @@ export function AdvancedLaboratoryResult({
|
|||||||
failedSessionId: string | null;
|
failedSessionId: string | null;
|
||||||
replayError: string | null;
|
replayError: string | null;
|
||||||
}) {
|
}) {
|
||||||
|
if (workId === "e39-perception-refinement" && results.e39) {
|
||||||
|
return <E39Result rigLabel={rigLabel} result={results.e39} />;
|
||||||
|
}
|
||||||
if (workId === "e38-perception-baseline" && results.e38) {
|
if (workId === "e38-perception-baseline" && results.e38) {
|
||||||
return <E38Result rigLabel={rigLabel} result={results.e38} />;
|
return <E38Result rigLabel={rigLabel} result={results.e38} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
import {
|
||||||
|
LaboratoryEvidence,
|
||||||
|
LaboratoryResultSummary,
|
||||||
|
LaboratorySummary,
|
||||||
|
LaboratoryWorkTemplate,
|
||||||
|
} from "../../components/laboratory/LaboratoryPresentation";
|
||||||
|
import type {
|
||||||
|
E39PerceptionRefinementResult,
|
||||||
|
} from "../../core/laboratory/advancedResults";
|
||||||
|
import { formatNumber } from "../../presentation";
|
||||||
|
|
||||||
|
function percent(value: number): string {
|
||||||
|
return `${(value * 100).toLocaleString("ru-RU", {
|
||||||
|
maximumFractionDigits: 1,
|
||||||
|
})}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function E39Result({
|
||||||
|
rigLabel,
|
||||||
|
result,
|
||||||
|
}: {
|
||||||
|
rigLabel: string;
|
||||||
|
result: E39PerceptionRefinementResult;
|
||||||
|
}) {
|
||||||
|
const metrics = result.metrics;
|
||||||
|
const dimensions = metrics.dimensions;
|
||||||
|
const development = result.developmentCrossValidation.dimensions;
|
||||||
|
const gateLabel = result.qualityGatePassed
|
||||||
|
? "R1 gate пройден"
|
||||||
|
: "R1 gate не пройден";
|
||||||
|
return (
|
||||||
|
<LaboratoryWorkTemplate
|
||||||
|
summary={(
|
||||||
|
<LaboratorySummary
|
||||||
|
title="LAB E39 · refinement качества R1"
|
||||||
|
description="Поверх baseline E38 проверена более богатая source-scoped модель camera + LiDAR. Метод был выбран только по development-кейсам, исполнен на Worker 006 и один раз оценён на неизменяемом validation E37."
|
||||||
|
status={gateLabel}
|
||||||
|
statusTone={result.qualityGatePassed ? "success" : "warning"}
|
||||||
|
facts={[
|
||||||
|
{
|
||||||
|
label: "Конфигурация",
|
||||||
|
value: `${rigLabel} · ${result.sourceDisplayName}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Development",
|
||||||
|
value: `${formatNumber(metrics.developmentItems, 0)} · 5-fold CV`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Validation",
|
||||||
|
value: `${formatNumber(metrics.validationItems, 0)} · sealed`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Исполнение",
|
||||||
|
value: `Worker 006 · ${result.workerNode}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
brief={{
|
||||||
|
question: "Закроет ли точная совокупность camera-crop, LiDAR-формы и проекционных признаков разрыв E38 до 90% без обучения на validation?",
|
||||||
|
approach: "Для каждого case сформированы 262 детерминированных признака. Robust-scaled 3-NN и правила dimension projection были зафиксированы после пятифолдовой проверки только на 340 development-кейсах; validation labels при выборе не использовались.",
|
||||||
|
principalResult: `Development CV показал presence ${percent(development.presence.accuracy)} и geometry ${percent(development.geometryAssociation.accuracy)}, но sealed validation — по ${percent(dimensions.presence.accuracy)}. Freshness удержан выше порога: ${percent(dimensions.freshness.accuracy)}.`,
|
||||||
|
limitation: "Модель включает координаты исходного кадра и относится только к RAVNOVES00. Разрыв CV → validation показывает переоценку устойчивости; перенос на другой маршрут, риг или растительную среду не доказан.",
|
||||||
|
}}
|
||||||
|
method={{
|
||||||
|
completeness: "complete",
|
||||||
|
executionClass: "deterministic",
|
||||||
|
pipelineId: result.profileId,
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
kind: "source",
|
||||||
|
name: "E37 frozen acceptance contract",
|
||||||
|
version: `${formatNumber(metrics.developmentItems, 0)} development + ${formatNumber(metrics.validationItems, 0)} sealed validation`,
|
||||||
|
role: "неизменяемый denominator и раздельные reference-метрики",
|
||||||
|
identitySha256: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "algorithm",
|
||||||
|
name: "Robust-scaled 3-neighbour refinement",
|
||||||
|
version: "262 camera + LiDAR features · deterministic 5-fold CV",
|
||||||
|
role: "source-scoped presence classification без validation-label fit",
|
||||||
|
identitySha256: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "tool",
|
||||||
|
name: "Package-bound feature projection",
|
||||||
|
version: "exact camera crops + LiDAR projection statistics",
|
||||||
|
role: "воспроизводимый вход Worker без скрытого доступа к исходным данным",
|
||||||
|
identitySha256: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "runtime",
|
||||||
|
name: "Worker 006",
|
||||||
|
version: result.workerNode,
|
||||||
|
role: "ограниченное исполнение immutable package без командных полномочий",
|
||||||
|
identitySha256: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
evidence={(
|
||||||
|
<LaboratoryEvidence
|
||||||
|
eyebrow="DEVELOPMENT → SEALED VALIDATION"
|
||||||
|
title="Проверка устойчивости refinement"
|
||||||
|
kind="diagnostic-model"
|
||||||
|
>
|
||||||
|
<div className="laboratory-result-metrics">
|
||||||
|
<div>
|
||||||
|
<span>Development presence</span>
|
||||||
|
<strong>{percent(development.presence.accuracy)}</strong>
|
||||||
|
<small>
|
||||||
|
{`${formatNumber(development.presence.correct, 0)} / ${formatNumber(development.presence.total, 0)} · 5-fold CV`}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Validation presence</span>
|
||||||
|
<strong>{percent(dimensions.presence.accuracy)}</strong>
|
||||||
|
<small>
|
||||||
|
{`${formatNumber(dimensions.presence.correct, 0)} / ${formatNumber(dimensions.presence.total, 0)} · цель 90%`}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Validation geometry</span>
|
||||||
|
<strong>{percent(dimensions.geometryAssociation.accuracy)}</strong>
|
||||||
|
<small>
|
||||||
|
{`${formatNumber(dimensions.geometryAssociation.correct, 0)} / ${formatNumber(dimensions.geometryAssociation.total, 0)} · цель 90%`}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Validation freshness</span>
|
||||||
|
<strong>{percent(dimensions.freshness.accuracy)}</strong>
|
||||||
|
<small>
|
||||||
|
{`${formatNumber(dimensions.freshness.correct, 0)} / ${formatNumber(dimensions.freshness.total, 0)} · цель 90%`}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LaboratoryEvidence>
|
||||||
|
)}
|
||||||
|
result={(
|
||||||
|
<LaboratoryResultSummary
|
||||||
|
title={result.qualityGatePassed
|
||||||
|
? "Refinement достиг всех source-scoped целей R1"
|
||||||
|
: "Refinement улучшил baseline, но не закрыл R1"}
|
||||||
|
status={gateLabel}
|
||||||
|
statusTone={result.qualityGatePassed ? "success" : "warning"}
|
||||||
|
metrics={[
|
||||||
|
{
|
||||||
|
label: "Presence",
|
||||||
|
value: percent(dimensions.presence.accuracy),
|
||||||
|
hint: `${formatNumber(dimensions.presence.incorrect, 0)} ошибок · E38: 82,2%`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Geometry association",
|
||||||
|
value: percent(dimensions.geometryAssociation.accuracy),
|
||||||
|
hint: `${formatNumber(dimensions.geometryAssociation.incorrect, 0)} ошибок · E38: 81,5%`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Freshness",
|
||||||
|
value: percent(dimensions.freshness.accuracy),
|
||||||
|
hint: `${formatNumber(dimensions.freshness.incorrect, 0)} ошибок · порог пройден`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "High severity",
|
||||||
|
value: formatNumber(metrics.highSeverityFailures, 0),
|
||||||
|
hint: `E38: 14 · учёт ${percent(metrics.accountingFraction)} · false free ${formatNumber(metrics.falseFreeClaims, 0)}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
conclusion={{
|
||||||
|
proved: `По сравнению с E38 presence вырос с 82,2% до ${percent(dimensions.presence.accuracy)}, geometry — с 81,5% до ${percent(dimensions.geometryAssociation.accuracy)}, high-severity ошибки сократились с 14 до ${formatNumber(metrics.highSeverityFailures, 0)}. Учёт остался 100%, false-free claims — 0.`,
|
||||||
|
notProved: `Порог 90% не достигнут по presence и geometry; development CV переоценил sealed validation примерно на 5,4 п.п. Результат не даёт полномочий навигации, команд или safety.`,
|
||||||
|
decision: "Зафиксировать E39 как измеренное улучшение, но не принимать R1. Следующую итерацию строить на более устойчивом development-only разбиении и более содержательном представлении объекта, не подбирая параметры по sealed validation.",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -71,6 +71,7 @@ const EMPTY_ADVANCED_RESULTS: AdvancedLaboratoryResults = {
|
|||||||
e35: null,
|
e35: null,
|
||||||
e37: null,
|
e37: null,
|
||||||
e38: null,
|
e38: null,
|
||||||
|
e39: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
function laboratoryWorkOrdinal(value: string): number {
|
function laboratoryWorkOrdinal(value: string): number {
|
||||||
|
|||||||
@@ -432,6 +432,100 @@ function e38() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function e39DevelopmentDimension({
|
||||||
|
accuracy,
|
||||||
|
correct,
|
||||||
|
incorrect,
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
correct,
|
||||||
|
incorrect,
|
||||||
|
total: 340,
|
||||||
|
accuracy,
|
||||||
|
target: 0.9,
|
||||||
|
passed: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function e39() {
|
||||||
|
return {
|
||||||
|
result_id: `e39-perception-refinement-${"9".repeat(64)}`,
|
||||||
|
created_at_utc: "2026-07-28T06:29:42.847Z",
|
||||||
|
source_session_id: "20260720T065719Z_viewer_live",
|
||||||
|
source_display_name: "RAVNOVES00",
|
||||||
|
status: "measured-r1-source-scoped-refinement",
|
||||||
|
profile_id: "e39-ravnoves00-r1-development-knn/v1",
|
||||||
|
worker_node: "DESKTOP-OPJ8J04",
|
||||||
|
quality_gate_passed: false,
|
||||||
|
development_cross_validation: {
|
||||||
|
strategy: "deterministic-item-hash-five-fold",
|
||||||
|
seed: "e39-dev-cv",
|
||||||
|
folds: 5,
|
||||||
|
items: 340,
|
||||||
|
validation_labels_used: false,
|
||||||
|
passed: true,
|
||||||
|
dimensions: {
|
||||||
|
presence: e39DevelopmentDimension({
|
||||||
|
accuracy: 0.902941,
|
||||||
|
correct: 307,
|
||||||
|
incorrect: 33,
|
||||||
|
}),
|
||||||
|
geometry_association: e39DevelopmentDimension({
|
||||||
|
accuracy: 0.905882,
|
||||||
|
correct: 308,
|
||||||
|
incorrect: 32,
|
||||||
|
}),
|
||||||
|
freshness: e39DevelopmentDimension({
|
||||||
|
accuracy: 0.964706,
|
||||||
|
correct: 328,
|
||||||
|
incorrect: 12,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metrics: {
|
||||||
|
development_items: 340,
|
||||||
|
validation_items: 146,
|
||||||
|
terminal_outcomes: 146,
|
||||||
|
accounting_fraction: 1,
|
||||||
|
false_free_claims: 0,
|
||||||
|
high_severity_failures: 8,
|
||||||
|
dimensions: {
|
||||||
|
presence: e38Dimension({
|
||||||
|
accuracy: 0.849315,
|
||||||
|
correct: 124,
|
||||||
|
incorrect: 22,
|
||||||
|
passed: false,
|
||||||
|
}),
|
||||||
|
geometry_association: e38Dimension({
|
||||||
|
accuracy: 0.849315,
|
||||||
|
correct: 124,
|
||||||
|
incorrect: 22,
|
||||||
|
passed: false,
|
||||||
|
}),
|
||||||
|
freshness: e38Dimension({
|
||||||
|
accuracy: 0.931507,
|
||||||
|
correct: 136,
|
||||||
|
incorrect: 10,
|
||||||
|
passed: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
blocking_checks: [
|
||||||
|
"presence_target_reached",
|
||||||
|
"geometry_association_target_reached",
|
||||||
|
"high_severity_failures_zero",
|
||||||
|
],
|
||||||
|
method: {
|
||||||
|
summary: "robust-scaled 3-neighbour presence classification",
|
||||||
|
selection: "development-only deterministic five-fold cross-validation",
|
||||||
|
dimension_projection: "derived from predicted presence and immutable stratum",
|
||||||
|
},
|
||||||
|
limitations: ["source-scoped"],
|
||||||
|
authority,
|
||||||
|
access: "read-only",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
server = await createServer({
|
server = await createServer({
|
||||||
appType: "custom",
|
appType: "custom",
|
||||||
@@ -448,9 +542,9 @@ after(async () => {
|
|||||||
await server?.close();
|
await server?.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("decodes E31–E38 from separate read-only catalogs", async () => {
|
test("decodes E31–E39 from separate read-only catalogs", async () => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
const items = [e31(), e32(), e33(), e34(), e35(), e37(), e38()];
|
const items = [e31(), e32(), e33(), e34(), e35(), e37(), e38(), e39()];
|
||||||
const decoded = await fetchAdvancedLaboratoryResults({
|
const decoded = await fetchAdvancedLaboratoryResults({
|
||||||
fetcher: async (input, init) => {
|
fetcher: async (input, init) => {
|
||||||
requests.push({ input: String(input), method: init?.method });
|
requests.push({ input: String(input), method: init?.method });
|
||||||
@@ -476,6 +570,14 @@ test("decodes E31–E38 from separate read-only catalogs", async () => {
|
|||||||
assert.equal(decoded.e38.metrics.dimensions.presence.accuracy, 0.821918);
|
assert.equal(decoded.e38.metrics.dimensions.presence.accuracy, 0.821918);
|
||||||
assert.equal(decoded.e38.metrics.dimensions.freshness.passed, true);
|
assert.equal(decoded.e38.metrics.dimensions.freshness.passed, true);
|
||||||
assert.equal(decoded.e38.qualityGatePassed, false);
|
assert.equal(decoded.e38.qualityGatePassed, false);
|
||||||
|
assert.equal(
|
||||||
|
decoded.e39.developmentCrossValidation.dimensions.presence.accuracy,
|
||||||
|
0.902941,
|
||||||
|
);
|
||||||
|
assert.equal(decoded.e39.developmentCrossValidation.validationLabelsUsed, false);
|
||||||
|
assert.equal(decoded.e39.metrics.dimensions.presence.accuracy, 0.849315);
|
||||||
|
assert.equal(decoded.e39.metrics.highSeverityFailures, 8);
|
||||||
|
assert.equal(decoded.e39.qualityGatePassed, false);
|
||||||
assert.deepEqual(requests, [
|
assert.deepEqual(requests, [
|
||||||
{ input: "/api/v1/laboratory/e31/results?limit=1", method: "GET" },
|
{ input: "/api/v1/laboratory/e31/results?limit=1", method: "GET" },
|
||||||
{ input: "/api/v1/laboratory/e32/results?limit=1", method: "GET" },
|
{ input: "/api/v1/laboratory/e32/results?limit=1", method: "GET" },
|
||||||
@@ -484,6 +586,7 @@ test("decodes E31–E38 from separate read-only catalogs", async () => {
|
|||||||
{ input: "/api/v1/laboratory/e35/results?limit=1", method: "GET" },
|
{ input: "/api/v1/laboratory/e35/results?limit=1", method: "GET" },
|
||||||
{ input: "/api/v1/laboratory/e37/results?limit=1", method: "GET" },
|
{ input: "/api/v1/laboratory/e37/results?limit=1", method: "GET" },
|
||||||
{ input: "/api/v1/laboratory/e38/results?limit=1", method: "GET" },
|
{ input: "/api/v1/laboratory/e38/results?limit=1", method: "GET" },
|
||||||
|
{ input: "/api/v1/laboratory/e39/results?limit=1", method: "GET" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -500,7 +603,8 @@ test("rejects authority escalation in an accepted-looking result", async () => {
|
|||||||
: String(input).includes("/e33/") ? e33()
|
: String(input).includes("/e33/") ? e33()
|
||||||
: String(input).includes("/e34/") ? e34()
|
: String(input).includes("/e34/") ? e34()
|
||||||
: String(input).includes("/e35/") ? e35()
|
: String(input).includes("/e35/") ? e35()
|
||||||
: String(input).includes("/e37/") ? e37() : e38(),
|
: String(input).includes("/e37/") ? e37()
|
||||||
|
: String(input).includes("/e38/") ? e38() : e39(),
|
||||||
)), { status: 200 }),
|
)), { status: 200 }),
|
||||||
}),
|
}),
|
||||||
AdvancedLaboratoryContractError,
|
AdvancedLaboratoryContractError,
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ const e38ResultUrl = new URL(
|
|||||||
"../src/workspaces/laboratory/E38Result.tsx",
|
"../src/workspaces/laboratory/E38Result.tsx",
|
||||||
import.meta.url,
|
import.meta.url,
|
||||||
);
|
);
|
||||||
|
const e39ResultUrl = new URL(
|
||||||
|
"../src/workspaces/laboratory/E39Result.tsx",
|
||||||
|
import.meta.url,
|
||||||
|
);
|
||||||
const e35StylesUrl = new URL(
|
const e35StylesUrl = new URL(
|
||||||
"../src/styles/e35-degradation-recovery.css",
|
"../src/styles/e35-degradation-recovery.css",
|
||||||
import.meta.url,
|
import.meta.url,
|
||||||
@@ -239,6 +243,24 @@ test("E38 reports the frozen R1 baseline through the canonical LAB anatomy", asy
|
|||||||
assert.match(advancedSource, /<E38Result/);
|
assert.match(advancedSource, /<E38Result/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("E39 reports refinement and the CV-to-validation gap through the canonical LAB anatomy", async () => {
|
||||||
|
const [e39Source, advancedSource] = await Promise.all([
|
||||||
|
readFile(e39ResultUrl, "utf8"),
|
||||||
|
readFile(advancedLaboratoryResultUrl, "utf8"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert.match(e39Source, /<LaboratoryWorkTemplate/);
|
||||||
|
assert.match(e39Source, /<LaboratoryEvidence/);
|
||||||
|
assert.match(e39Source, /<LaboratoryResultSummary/);
|
||||||
|
assert.match(e39Source, /validation labels при выборе не использовались/);
|
||||||
|
assert.match(e39Source, /Разрыв CV → validation/);
|
||||||
|
assert.match(e39Source, /не принимать R1/);
|
||||||
|
assert.match(e39Source, /не подбирая параметры по sealed validation/);
|
||||||
|
assert.doesNotMatch(e39Source, /className="laboratory-(?:summary|result-summary)"/);
|
||||||
|
assert.match(advancedSource, /id: "e39-perception-refinement"/);
|
||||||
|
assert.match(advancedSource, /<E39Result/);
|
||||||
|
});
|
||||||
|
|
||||||
test("the primary point-cloud viewer restores from fullscreen on Escape", async () => {
|
test("the primary point-cloud viewer restores from fullscreen on Escape", async () => {
|
||||||
const workspacesSource = await readFile(workspacesUrl, "utf8");
|
const workspacesSource = await readFile(workspacesUrl, "utf8");
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ from k1link.compute.e38_perception_baseline import (
|
|||||||
E38PerceptionBaselineError,
|
E38PerceptionBaselineError,
|
||||||
read_e38_perception_baseline,
|
read_e38_perception_baseline,
|
||||||
)
|
)
|
||||||
|
from k1link.compute.e39_perception_refinement import (
|
||||||
|
E39PerceptionRefinement,
|
||||||
|
E39PerceptionRefinementError,
|
||||||
|
read_e39_perception_refinement,
|
||||||
|
)
|
||||||
|
|
||||||
LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = (
|
LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = (
|
||||||
"missioncore.laboratory-advanced-catalog/v1"
|
"missioncore.laboratory-advanced-catalog/v1"
|
||||||
@@ -56,6 +61,7 @@ _E34_RESULT_ID = re.compile(r"^e34-temporal-occupied-[a-f0-9]{64}$")
|
|||||||
_E35_RESULT_ID = re.compile(r"^e35-degradation-recovery-[a-f0-9]{64}$")
|
_E35_RESULT_ID = re.compile(r"^e35-degradation-recovery-[a-f0-9]{64}$")
|
||||||
_E37_RESULT_ID = re.compile(r"^e37-ravnoves-acceptance-[a-f0-9]{64}$")
|
_E37_RESULT_ID = re.compile(r"^e37-ravnoves-acceptance-[a-f0-9]{64}$")
|
||||||
_E38_RESULT_ID = re.compile(r"^e38-perception-baseline-[a-f0-9]{64}$")
|
_E38_RESULT_ID = re.compile(r"^e38-perception-baseline-[a-f0-9]{64}$")
|
||||||
|
_E39_RESULT_ID = re.compile(r"^e39-perception-refinement-[a-f0-9]{64}$")
|
||||||
|
|
||||||
RootProvider = Callable[[], Path | None]
|
RootProvider = Callable[[], Path | None]
|
||||||
|
|
||||||
@@ -133,6 +139,15 @@ def _read_e38_cached(
|
|||||||
return read_e38_perception_baseline(Path(root_text))
|
return read_e38_perception_baseline(Path(root_text))
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=16)
|
||||||
|
def _read_e39_cached(
|
||||||
|
root_text: str,
|
||||||
|
signature: tuple[int, ...],
|
||||||
|
) -> E39PerceptionRefinement:
|
||||||
|
del signature
|
||||||
|
return read_e39_perception_refinement(Path(root_text))
|
||||||
|
|
||||||
|
|
||||||
def _configured_root(provider: RootProvider) -> Path | None:
|
def _configured_root(provider: RootProvider) -> Path | None:
|
||||||
value = provider()
|
value = provider()
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -604,6 +619,46 @@ def _project_e38(result: E38PerceptionBaseline) -> dict[str, object]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _project_e39(result: E39PerceptionRefinement) -> dict[str, object]:
|
||||||
|
identity = _object(result.manifest.get("identity"), "E39 identity")
|
||||||
|
source = _object(identity.get("source"), "E39 source")
|
||||||
|
execution = _object(identity.get("execution"), "E39 execution")
|
||||||
|
profile = _object(identity.get("profile"), "E39 profile")
|
||||||
|
metrics = _object(result.report.get("metrics"), "E39 metrics")
|
||||||
|
dimensions = _object(metrics.get("dimensions"), "E39 dimensions")
|
||||||
|
quality_gate = _object(result.report.get("quality_gate"), "E39 gate")
|
||||||
|
development_cv = _object(
|
||||||
|
result.report.get("development_cross_validation"),
|
||||||
|
"E39 development CV",
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"result_id": result.result_id,
|
||||||
|
"created_at_utc": result.manifest.get("created_at_utc"),
|
||||||
|
"source_session_id": source.get("session_id"),
|
||||||
|
"source_display_name": source.get("display_name"),
|
||||||
|
"status": result.report.get("status"),
|
||||||
|
"profile_id": profile.get("profile_id"),
|
||||||
|
"worker_node": execution.get("worker_node"),
|
||||||
|
"quality_gate_passed": quality_gate.get("passed"),
|
||||||
|
"development_cross_validation": copy.deepcopy(development_cv),
|
||||||
|
"metrics": {
|
||||||
|
"development_items": metrics.get("development_items"),
|
||||||
|
"validation_items": metrics.get("validation_items"),
|
||||||
|
"terminal_outcomes": metrics.get("terminal_outcomes"),
|
||||||
|
"accounting_fraction": metrics.get("accounting_fraction"),
|
||||||
|
"false_free_claims": metrics.get("false_free_claims"),
|
||||||
|
"high_severity_failures": metrics.get("high_severity_failures"),
|
||||||
|
"dimensions": copy.deepcopy(dimensions),
|
||||||
|
},
|
||||||
|
"blocking_checks": copy.deepcopy(quality_gate.get("blocking_checks")),
|
||||||
|
"method": copy.deepcopy(result.report.get("method")),
|
||||||
|
"decision": copy.deepcopy(result.report.get("decision")),
|
||||||
|
"limitations": copy.deepcopy(result.report.get("limitations")),
|
||||||
|
"authority": copy.deepcopy(result.report.get("authority")),
|
||||||
|
"access": "read-only",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _empty_catalog(configured: bool) -> dict[str, object]:
|
def _empty_catalog(configured: bool) -> dict[str, object]:
|
||||||
return {
|
return {
|
||||||
"schema_version": LABORATORY_ADVANCED_CATALOG_SCHEMA,
|
"schema_version": LABORATORY_ADVANCED_CATALOG_SCHEMA,
|
||||||
@@ -624,6 +679,7 @@ def build_advanced_laboratory_router(
|
|||||||
e35_root_provider: RootProvider = lambda: None,
|
e35_root_provider: RootProvider = lambda: None,
|
||||||
e37_root_provider: RootProvider = lambda: None,
|
e37_root_provider: RootProvider = lambda: None,
|
||||||
e38_root_provider: RootProvider = lambda: None,
|
e38_root_provider: RootProvider = lambda: None,
|
||||||
|
e39_root_provider: RootProvider = lambda: None,
|
||||||
) -> APIRouter:
|
) -> APIRouter:
|
||||||
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
|
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
|
||||||
|
|
||||||
@@ -886,4 +942,37 @@ def build_advanced_laboratory_router(
|
|||||||
"invalid_total": invalid_total,
|
"invalid_total": invalid_total,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@router.get("/e39/results")
|
||||||
|
def list_e39_results(
|
||||||
|
limit: int = Query(default=1, ge=1, le=10),
|
||||||
|
) -> dict[str, object]:
|
||||||
|
root = _configured_root(e39_root_provider)
|
||||||
|
if root is None:
|
||||||
|
return _empty_catalog(False)
|
||||||
|
candidates = _candidates(root, _E39_RESULT_ID)
|
||||||
|
items: list[dict[str, object]] = []
|
||||||
|
invalid_total = 0
|
||||||
|
for candidate in candidates:
|
||||||
|
try:
|
||||||
|
result = _read_e39_cached(
|
||||||
|
str(candidate.resolve()),
|
||||||
|
_result_signature(candidate),
|
||||||
|
)
|
||||||
|
if len(items) < limit:
|
||||||
|
items.append(_project_e39(result))
|
||||||
|
except (
|
||||||
|
E39PerceptionRefinementError,
|
||||||
|
KeyError,
|
||||||
|
OSError,
|
||||||
|
TypeError,
|
||||||
|
ValueError,
|
||||||
|
):
|
||||||
|
invalid_total += 1
|
||||||
|
return {
|
||||||
|
**_empty_catalog(True),
|
||||||
|
"items": items,
|
||||||
|
"candidate_total": len(candidates),
|
||||||
|
"invalid_total": invalid_total,
|
||||||
|
}
|
||||||
|
|
||||||
return router
|
return router
|
||||||
|
|||||||
@@ -550,6 +550,13 @@ app.include_router(
|
|||||||
/ "e38"
|
/ "e38"
|
||||||
/ "results"
|
/ "results"
|
||||||
),
|
),
|
||||||
|
e39_root_provider=lambda: (
|
||||||
|
REPOSITORY_ROOT
|
||||||
|
/ ".runtime"
|
||||||
|
/ "compute-experiments"
|
||||||
|
/ "e39"
|
||||||
|
/ "results"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
app.include_router(
|
app.include_router(
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ def _endpoint(router: APIRouter, path: str) -> object:
|
|||||||
def test_advanced_catalogs_are_empty_when_not_configured() -> None:
|
def test_advanced_catalogs_are_empty_when_not_configured() -> None:
|
||||||
router = build_advanced_laboratory_router()
|
router = build_advanced_laboratory_router()
|
||||||
|
|
||||||
for name in ("e31", "e32", "e33", "e34", "e35", "e37", "e38"):
|
for name in ("e31", "e32", "e33", "e34", "e35", "e37", "e38", "e39"):
|
||||||
route = _endpoint(router, f"/api/v1/laboratory/{name}/results")
|
route = _endpoint(router, f"/api/v1/laboratory/{name}/results")
|
||||||
catalog = route(limit=1) # type: ignore[operator]
|
catalog = route(limit=1) # type: ignore[operator]
|
||||||
assert catalog == {
|
assert catalog == {
|
||||||
@@ -49,7 +49,8 @@ def test_advanced_catalogs_fail_closed_on_incomplete_results(
|
|||||||
e35 = tmp_path / "e35"
|
e35 = tmp_path / "e35"
|
||||||
e37 = tmp_path / "e37"
|
e37 = tmp_path / "e37"
|
||||||
e38 = tmp_path / "e38"
|
e38 = tmp_path / "e38"
|
||||||
for root in (e31, e32, e33, e34, e35, e37, e38):
|
e39 = tmp_path / "e39"
|
||||||
|
for root in (e31, e32, e33, e34, e35, e37, e38, e39):
|
||||||
root.mkdir()
|
root.mkdir()
|
||||||
(e31 / f"e31-source-qualification-{'1' * 64}").mkdir()
|
(e31 / f"e31-source-qualification-{'1' * 64}").mkdir()
|
||||||
(e32 / f"e32-track-geometry-{'2' * 64}").mkdir()
|
(e32 / f"e32-track-geometry-{'2' * 64}").mkdir()
|
||||||
@@ -58,6 +59,7 @@ def test_advanced_catalogs_fail_closed_on_incomplete_results(
|
|||||||
(e35 / f"e35-degradation-recovery-{'5' * 64}").mkdir()
|
(e35 / f"e35-degradation-recovery-{'5' * 64}").mkdir()
|
||||||
(e37 / f"e37-ravnoves-acceptance-{'7' * 64}").mkdir()
|
(e37 / f"e37-ravnoves-acceptance-{'7' * 64}").mkdir()
|
||||||
(e38 / f"e38-perception-baseline-{'8' * 64}").mkdir()
|
(e38 / f"e38-perception-baseline-{'8' * 64}").mkdir()
|
||||||
|
(e39 / f"e39-perception-refinement-{'9' * 64}").mkdir()
|
||||||
router = build_advanced_laboratory_router(
|
router = build_advanced_laboratory_router(
|
||||||
e31_root_provider=lambda: e31,
|
e31_root_provider=lambda: e31,
|
||||||
e32_root_provider=lambda: e32,
|
e32_root_provider=lambda: e32,
|
||||||
@@ -66,9 +68,10 @@ def test_advanced_catalogs_fail_closed_on_incomplete_results(
|
|||||||
e35_root_provider=lambda: e35,
|
e35_root_provider=lambda: e35,
|
||||||
e37_root_provider=lambda: e37,
|
e37_root_provider=lambda: e37,
|
||||||
e38_root_provider=lambda: e38,
|
e38_root_provider=lambda: e38,
|
||||||
|
e39_root_provider=lambda: e39,
|
||||||
)
|
)
|
||||||
|
|
||||||
for name in ("e31", "e32", "e33", "e34", "e35", "e37", "e38"):
|
for name in ("e31", "e32", "e33", "e34", "e35", "e37", "e38", "e39"):
|
||||||
route = _endpoint(router, f"/api/v1/laboratory/{name}/results")
|
route = _endpoint(router, f"/api/v1/laboratory/{name}/results")
|
||||||
catalog = route(limit=1) # type: ignore[operator]
|
catalog = route(limit=1) # type: ignore[operator]
|
||||||
assert catalog["configured"] is True
|
assert catalog["configured"] is True
|
||||||
@@ -220,6 +223,153 @@ def test_e34_catalog_projects_only_accepted_read_only_evidence(
|
|||||||
assert item["access"] == "read-only"
|
assert item["access"] == "read-only"
|
||||||
|
|
||||||
|
|
||||||
|
def test_e39_catalog_projects_development_cv_and_sealed_validation(
|
||||||
|
tmp_path: Path,
|
||||||
|
monkeypatch: MonkeyPatch,
|
||||||
|
) -> None:
|
||||||
|
result_id = f"e39-perception-refinement-{'9' * 64}"
|
||||||
|
root = tmp_path / "e39"
|
||||||
|
candidate = root / result_id
|
||||||
|
candidate.mkdir(parents=True)
|
||||||
|
(candidate / "manifest.json").write_text("{}", encoding="utf-8")
|
||||||
|
authority = {
|
||||||
|
"commands_enabled": False,
|
||||||
|
"navigation_or_safety_accepted": False,
|
||||||
|
}
|
||||||
|
dimension = {
|
||||||
|
"correct": 124,
|
||||||
|
"incorrect": 22,
|
||||||
|
"total": 146,
|
||||||
|
"accuracy": 0.849315,
|
||||||
|
"target": 0.9,
|
||||||
|
"passed": False,
|
||||||
|
"confusion": [],
|
||||||
|
"by_stratum": {},
|
||||||
|
}
|
||||||
|
result = SimpleNamespace(
|
||||||
|
result_id=result_id,
|
||||||
|
manifest={
|
||||||
|
"created_at_utc": "2026-07-28T06:29:42.847Z",
|
||||||
|
"identity": {
|
||||||
|
"source": {
|
||||||
|
"session_id": "20260720T065719Z_viewer_live",
|
||||||
|
"display_name": "RAVNOVES00",
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"profile_id": "e39-ravnoves00-r1-development-knn/v1",
|
||||||
|
},
|
||||||
|
"execution": {
|
||||||
|
"worker_node": "DESKTOP-OPJ8J04",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
report={
|
||||||
|
"status": "measured-r1-source-scoped-refinement",
|
||||||
|
"development_cross_validation": {
|
||||||
|
"strategy": "deterministic-item-hash-five-fold",
|
||||||
|
"seed": "e39-dev-cv",
|
||||||
|
"folds": 5,
|
||||||
|
"items": 340,
|
||||||
|
"validation_labels_used": False,
|
||||||
|
"passed": True,
|
||||||
|
"dimensions": {
|
||||||
|
"presence": {
|
||||||
|
"correct": 307,
|
||||||
|
"incorrect": 33,
|
||||||
|
"total": 340,
|
||||||
|
"accuracy": 0.902941,
|
||||||
|
"target": 0.9,
|
||||||
|
"passed": True,
|
||||||
|
},
|
||||||
|
"geometry_association": {
|
||||||
|
"correct": 308,
|
||||||
|
"incorrect": 32,
|
||||||
|
"total": 340,
|
||||||
|
"accuracy": 0.905882,
|
||||||
|
"target": 0.9,
|
||||||
|
"passed": True,
|
||||||
|
},
|
||||||
|
"freshness": {
|
||||||
|
"correct": 328,
|
||||||
|
"incorrect": 12,
|
||||||
|
"total": 340,
|
||||||
|
"accuracy": 0.964706,
|
||||||
|
"target": 0.9,
|
||||||
|
"passed": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"metrics": {
|
||||||
|
"development_items": 340,
|
||||||
|
"validation_items": 146,
|
||||||
|
"terminal_outcomes": 146,
|
||||||
|
"accounting_fraction": 1.0,
|
||||||
|
"false_free_claims": 0,
|
||||||
|
"high_severity_failures": 8,
|
||||||
|
"dimensions": {
|
||||||
|
"presence": dimension,
|
||||||
|
"geometry_association": dimension,
|
||||||
|
"freshness": {
|
||||||
|
**dimension,
|
||||||
|
"correct": 136,
|
||||||
|
"incorrect": 10,
|
||||||
|
"accuracy": 0.931507,
|
||||||
|
"passed": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"quality_gate": {
|
||||||
|
"passed": False,
|
||||||
|
"blocking_checks": [
|
||||||
|
"presence_target_reached",
|
||||||
|
"geometry_association_target_reached",
|
||||||
|
"high_severity_failures_zero",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"summary": "robust-scaled 3-neighbour classification",
|
||||||
|
"selection": "development-only five-fold cross-validation",
|
||||||
|
"dimension_projection": "presence plus immutable stratum",
|
||||||
|
},
|
||||||
|
"decision": {
|
||||||
|
"r1_refinement_measured": True,
|
||||||
|
"accepted_for_release": False,
|
||||||
|
},
|
||||||
|
"limitations": ["source-scoped"],
|
||||||
|
"authority": authority,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
def fake_read(
|
||||||
|
root_text: str,
|
||||||
|
signature: tuple[int, ...],
|
||||||
|
) -> SimpleNamespace:
|
||||||
|
assert root_text == str(candidate.resolve())
|
||||||
|
assert signature
|
||||||
|
return result
|
||||||
|
|
||||||
|
monkeypatch.setattr(advanced_api, "_read_e39_cached", fake_read)
|
||||||
|
router = build_advanced_laboratory_router(
|
||||||
|
e39_root_provider=lambda: root,
|
||||||
|
)
|
||||||
|
route = _endpoint(router, "/api/v1/laboratory/e39/results")
|
||||||
|
catalog = route(limit=1) # type: ignore[operator]
|
||||||
|
|
||||||
|
assert catalog["candidate_total"] == 1
|
||||||
|
assert catalog["invalid_total"] == 0
|
||||||
|
item = catalog["items"][0]
|
||||||
|
assert item["development_cross_validation"]["passed"] is True
|
||||||
|
assert (
|
||||||
|
item["development_cross_validation"]["validation_labels_used"]
|
||||||
|
is False
|
||||||
|
)
|
||||||
|
assert item["metrics"]["dimensions"]["presence"]["accuracy"] == 0.849315
|
||||||
|
assert item["metrics"]["high_severity_failures"] == 8
|
||||||
|
assert item["quality_gate_passed"] is False
|
||||||
|
assert item["authority"] == authority
|
||||||
|
assert item["access"] == "read-only"
|
||||||
|
|
||||||
|
|
||||||
def test_e35_catalog_projects_recovery_and_review(
|
def test_e35_catalog_projects_recovery_and_review(
|
||||||
tmp_path: Path,
|
tmp_path: Path,
|
||||||
monkeypatch: MonkeyPatch,
|
monkeypatch: MonkeyPatch,
|
||||||
|
|||||||
Reference in New Issue
Block a user