feat(lab): publish E37 R0 acceptance result
This commit is contained in:
@@ -89,12 +89,56 @@ export interface E33LaboratoryResult {
|
|||||||
access: "read-only";
|
access: "read-only";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface E37AcceptanceContractResult {
|
||||||
|
resultId: string;
|
||||||
|
createdAtUtc: string | null;
|
||||||
|
sourceSessionId: string;
|
||||||
|
sourceDisplayName: string;
|
||||||
|
status: "accepted-r0-source-scoped-contract";
|
||||||
|
profileId: string;
|
||||||
|
workerNode: string;
|
||||||
|
metrics: {
|
||||||
|
reviewedItems: number;
|
||||||
|
developmentItems: number;
|
||||||
|
validationItems: number;
|
||||||
|
engineeringItems: number;
|
||||||
|
humanExceptionItems: number;
|
||||||
|
terminalOutcomes: number;
|
||||||
|
accountingFraction: number;
|
||||||
|
falseFreeClaims: number;
|
||||||
|
};
|
||||||
|
dimensionDistributions: {
|
||||||
|
presence: Readonly<Record<string, number>>;
|
||||||
|
geometryAssociation: Readonly<Record<string, number>>;
|
||||||
|
freshness: Readonly<Record<string, number>>;
|
||||||
|
};
|
||||||
|
severityDistribution: Readonly<Record<string, number>>;
|
||||||
|
labelProvenance: {
|
||||||
|
engineeringItems: number;
|
||||||
|
humanExceptionItems: number;
|
||||||
|
independentGroundTruth: false;
|
||||||
|
};
|
||||||
|
split: {
|
||||||
|
strategy: string;
|
||||||
|
validationFraction: number;
|
||||||
|
};
|
||||||
|
targets: {
|
||||||
|
presenceTarget: number;
|
||||||
|
geometryAssociationTarget: number;
|
||||||
|
freshnessTarget: number;
|
||||||
|
};
|
||||||
|
qualityTargetEvaluated: false;
|
||||||
|
limitations: readonly string[];
|
||||||
|
access: "read-only";
|
||||||
|
}
|
||||||
|
|
||||||
export interface AdvancedLaboratoryResults {
|
export interface AdvancedLaboratoryResults {
|
||||||
e31: E31LaboratoryResult | null;
|
e31: E31LaboratoryResult | null;
|
||||||
e32: E32LaboratoryResult | null;
|
e32: E32LaboratoryResult | null;
|
||||||
e33: E33LaboratoryResult | null;
|
e33: E33LaboratoryResult | null;
|
||||||
e34: E34TemporalLayerResult | null;
|
e34: E34TemporalLayerResult | null;
|
||||||
e35: E35DegradationRecoveryResult | null;
|
e35: E35DegradationRecoveryResult | null;
|
||||||
|
e37: E37AcceptanceContractResult | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AdvancedLaboratoryContractError extends Error {
|
export class AdvancedLaboratoryContractError extends Error {
|
||||||
@@ -181,6 +225,19 @@ function strings(value: unknown, label: string): readonly string[] {
|
|||||||
return value.map((item, index) => stringValue(item, `${label}[${index}]`));
|
return value.map((item, index) => stringValue(item, `${label}[${index}]`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function numberRecord(
|
||||||
|
value: unknown,
|
||||||
|
label: string,
|
||||||
|
): Readonly<Record<string, number>> {
|
||||||
|
const source = record(value, label);
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(source).map(([key, item]) => [
|
||||||
|
key,
|
||||||
|
integerValue(item, `${label}.${key}`),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function contentId(value: unknown, prefix: string, label: string): string {
|
function contentId(value: unknown, prefix: string, label: string): string {
|
||||||
const parsed = stringValue(value, label);
|
const parsed = stringValue(value, label);
|
||||||
if (!new RegExp(`^${prefix}-[a-f0-9]{64}$`).test(parsed)) {
|
if (!new RegExp(`^${prefix}-[a-f0-9]{64}$`).test(parsed)) {
|
||||||
@@ -349,6 +406,139 @@ function parseE33(value: unknown): E33LaboratoryResult {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseE37(value: unknown): E37AcceptanceContractResult {
|
||||||
|
const item = record(value, "E37");
|
||||||
|
const metrics = record(item.metrics, "E37.metrics");
|
||||||
|
const distributions = record(
|
||||||
|
item.dimension_distributions,
|
||||||
|
"E37.dimension_distributions",
|
||||||
|
);
|
||||||
|
const provenance = record(item.label_provenance, "E37.label_provenance");
|
||||||
|
const split = record(item.split, "E37.split");
|
||||||
|
const targets = record(item.targets, "E37.targets");
|
||||||
|
diagnosticAuthority(item.authority, "E37.authority");
|
||||||
|
if (item.quality_target_evaluated !== false) {
|
||||||
|
throw new AdvancedLaboratoryContractError(
|
||||||
|
"E37.quality_target_evaluated: R0 не должен объявлять метрику проверенной.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (provenance.independent_ground_truth !== false) {
|
||||||
|
throw new AdvancedLaboratoryContractError(
|
||||||
|
"E37.label_provenance: R0 не является независимой разметкой.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
resultId: contentId(
|
||||||
|
item.result_id,
|
||||||
|
"e37-ravnoves-acceptance",
|
||||||
|
"E37.result_id",
|
||||||
|
),
|
||||||
|
createdAtUtc: optionalString(item.created_at_utc, "E37.created_at_utc"),
|
||||||
|
sourceSessionId: stringValue(
|
||||||
|
item.source_session_id,
|
||||||
|
"E37.source_session_id",
|
||||||
|
),
|
||||||
|
sourceDisplayName: stringValue(
|
||||||
|
item.source_display_name,
|
||||||
|
"E37.source_display_name",
|
||||||
|
),
|
||||||
|
status: exactString(
|
||||||
|
item.status,
|
||||||
|
"accepted-r0-source-scoped-contract",
|
||||||
|
"E37.status",
|
||||||
|
),
|
||||||
|
profileId: stringValue(item.profile_id, "E37.profile_id"),
|
||||||
|
workerNode: stringValue(item.worker_node, "E37.worker_node"),
|
||||||
|
metrics: {
|
||||||
|
reviewedItems: integerValue(
|
||||||
|
metrics.reviewed_items,
|
||||||
|
"E37.metrics.reviewed_items",
|
||||||
|
),
|
||||||
|
developmentItems: integerValue(
|
||||||
|
metrics.development_items,
|
||||||
|
"E37.metrics.development_items",
|
||||||
|
),
|
||||||
|
validationItems: integerValue(
|
||||||
|
metrics.validation_items,
|
||||||
|
"E37.metrics.validation_items",
|
||||||
|
),
|
||||||
|
engineeringItems: integerValue(
|
||||||
|
metrics.engineering_items,
|
||||||
|
"E37.metrics.engineering_items",
|
||||||
|
),
|
||||||
|
humanExceptionItems: integerValue(
|
||||||
|
metrics.human_exception_items,
|
||||||
|
"E37.metrics.human_exception_items",
|
||||||
|
),
|
||||||
|
terminalOutcomes: integerValue(
|
||||||
|
metrics.terminal_outcomes,
|
||||||
|
"E37.metrics.terminal_outcomes",
|
||||||
|
),
|
||||||
|
accountingFraction: numberValue(
|
||||||
|
metrics.accounting_fraction,
|
||||||
|
"E37.metrics.accounting_fraction",
|
||||||
|
),
|
||||||
|
falseFreeClaims: integerValue(
|
||||||
|
metrics.false_free_claims,
|
||||||
|
"E37.metrics.false_free_claims",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
dimensionDistributions: {
|
||||||
|
presence: numberRecord(
|
||||||
|
distributions.presence,
|
||||||
|
"E37.dimension_distributions.presence",
|
||||||
|
),
|
||||||
|
geometryAssociation: numberRecord(
|
||||||
|
distributions.geometry_association,
|
||||||
|
"E37.dimension_distributions.geometry_association",
|
||||||
|
),
|
||||||
|
freshness: numberRecord(
|
||||||
|
distributions.freshness,
|
||||||
|
"E37.dimension_distributions.freshness",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
severityDistribution: numberRecord(
|
||||||
|
item.severity_distribution,
|
||||||
|
"E37.severity_distribution",
|
||||||
|
),
|
||||||
|
labelProvenance: {
|
||||||
|
engineeringItems: integerValue(
|
||||||
|
provenance.engineering_items,
|
||||||
|
"E37.label_provenance.engineering_items",
|
||||||
|
),
|
||||||
|
humanExceptionItems: integerValue(
|
||||||
|
provenance.human_exception_items,
|
||||||
|
"E37.label_provenance.human_exception_items",
|
||||||
|
),
|
||||||
|
independentGroundTruth: false,
|
||||||
|
},
|
||||||
|
split: {
|
||||||
|
strategy: stringValue(split.strategy, "E37.split.strategy"),
|
||||||
|
validationFraction: numberValue(
|
||||||
|
split.validation_fraction,
|
||||||
|
"E37.split.validation_fraction",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
targets: {
|
||||||
|
presenceTarget: numberValue(
|
||||||
|
targets.presence_target,
|
||||||
|
"E37.targets.presence_target",
|
||||||
|
),
|
||||||
|
geometryAssociationTarget: numberValue(
|
||||||
|
targets.geometry_association_target,
|
||||||
|
"E37.targets.geometry_association_target",
|
||||||
|
),
|
||||||
|
freshnessTarget: numberValue(
|
||||||
|
targets.freshness_target,
|
||||||
|
"E37.targets.freshness_target",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
qualityTargetEvaluated: false,
|
||||||
|
limitations: strings(item.limitations, "E37.limitations"),
|
||||||
|
access: exactString(item.access, "read-only", "E37.access"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchOne<T>(
|
async function fetchOne<T>(
|
||||||
path: string,
|
path: string,
|
||||||
parser: (value: unknown) => T,
|
parser: (value: unknown) => T,
|
||||||
@@ -373,14 +563,15 @@ export async function fetchAdvancedLaboratoryResults({
|
|||||||
fetcher?: LaboratoryFetch;
|
fetcher?: LaboratoryFetch;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
} = {}): Promise<AdvancedLaboratoryResults> {
|
} = {}): Promise<AdvancedLaboratoryResults> {
|
||||||
const [e31, e32, e33, e34, e35] = await Promise.all([
|
const [e31, e32, e33, e34, e35, e37] = 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),
|
||||||
fetchE34TemporalLayerResult({ fetcher, signal }),
|
fetchE34TemporalLayerResult({ fetcher, signal }),
|
||||||
fetchE35DegradationRecoveryResult({ fetcher, signal }),
|
fetchE35DegradationRecoveryResult({ fetcher, signal }),
|
||||||
|
fetchOne("/api/v1/laboratory/e37/results?limit=1", parseE37, fetcher, signal),
|
||||||
]);
|
]);
|
||||||
return { e31, e32, e33, e34, e35 };
|
return { e31, e32, e33, e34, e35, e37 };
|
||||||
}
|
}
|
||||||
import {
|
import {
|
||||||
fetchE34TemporalLayerResult,
|
fetchE34TemporalLayerResult,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { E32Result } from "./E32Result";
|
|||||||
import { E33Result } from "./E33Result";
|
import { E33Result } from "./E33Result";
|
||||||
import { E34Result } from "./E34Result";
|
import { E34Result } from "./E34Result";
|
||||||
import { E35Result } from "./E35Result";
|
import { E35Result } from "./E35Result";
|
||||||
|
import { E37Result } from "./E37Result";
|
||||||
import { RecordedReplayEvidence } from "./RecordedReplayEvidence";
|
import { RecordedReplayEvidence } from "./RecordedReplayEvidence";
|
||||||
|
|
||||||
export type AdvancedLaboratoryWorkId =
|
export type AdvancedLaboratoryWorkId =
|
||||||
@@ -16,7 +17,8 @@ export type AdvancedLaboratoryWorkId =
|
|||||||
| "e32-track-geometry"
|
| "e32-track-geometry"
|
||||||
| "e33-worker-shadow"
|
| "e33-worker-shadow"
|
||||||
| "e34-temporal-layer"
|
| "e34-temporal-layer"
|
||||||
| "e35-degradation-recovery";
|
| "e35-degradation-recovery"
|
||||||
|
| "e37-ravnoves-acceptance";
|
||||||
|
|
||||||
type LaboratoryWorkspaceProps = WorkspaceRendererProps & {
|
type LaboratoryWorkspaceProps = WorkspaceRendererProps & {
|
||||||
SpatialView: ComponentType<WorkspaceRendererProps>;
|
SpatialView: ComponentType<WorkspaceRendererProps>;
|
||||||
@@ -31,6 +33,7 @@ export function isAdvancedLaboratoryWorkId(
|
|||||||
|| value === "e33-worker-shadow"
|
|| value === "e33-worker-shadow"
|
||||||
|| value === "e34-temporal-layer"
|
|| value === "e34-temporal-layer"
|
||||||
|| value === "e35-degradation-recovery"
|
|| value === "e35-degradation-recovery"
|
||||||
|
|| value === "e37-ravnoves-acceptance"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +72,12 @@ export function advancedLaboratoryWorkOptions(
|
|||||||
label: "LAB E35 · degradation recovery",
|
label: "LAB E35 · degradation recovery",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (results.e37) {
|
||||||
|
options.push({
|
||||||
|
id: "e37-ravnoves-acceptance",
|
||||||
|
label: "LAB E37 · RAVNOVES00 acceptance R0",
|
||||||
|
});
|
||||||
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +115,9 @@ export function AdvancedLaboratoryResult({
|
|||||||
failedSessionId: string | null;
|
failedSessionId: string | null;
|
||||||
replayError: string | null;
|
replayError: string | null;
|
||||||
}) {
|
}) {
|
||||||
|
if (workId === "e37-ravnoves-acceptance" && results.e37) {
|
||||||
|
return <E37Result rigLabel={rigLabel} result={results.e37} />;
|
||||||
|
}
|
||||||
if (workId === "e35-degradation-recovery" && results.e35) {
|
if (workId === "e35-degradation-recovery" && results.e35) {
|
||||||
return <E35Result rigLabel={rigLabel} result={results.e35} />;
|
return <E35Result rigLabel={rigLabel} result={results.e35} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
import {
|
||||||
|
LaboratoryEvidence,
|
||||||
|
LaboratoryResultSummary,
|
||||||
|
LaboratorySummary,
|
||||||
|
LaboratoryWorkTemplate,
|
||||||
|
} from "../../components/laboratory/LaboratoryPresentation";
|
||||||
|
import type { E37AcceptanceContractResult } from "../../core/laboratory/advancedResults";
|
||||||
|
import { formatNumber } from "../../presentation";
|
||||||
|
|
||||||
|
function distribution(
|
||||||
|
values: Readonly<Record<string, number>>,
|
||||||
|
): string {
|
||||||
|
return Object.entries(values)
|
||||||
|
.sort((left, right) => right[1] - left[1])
|
||||||
|
.map(([label, count]) => `${label}: ${formatNumber(count, 0)}`)
|
||||||
|
.join(" · ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function ContractEvidence({
|
||||||
|
result,
|
||||||
|
}: {
|
||||||
|
result: E37AcceptanceContractResult;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="laboratory-result-metrics">
|
||||||
|
<div>
|
||||||
|
<span>Presence</span>
|
||||||
|
<strong>{Object.keys(result.dimensionDistributions.presence).length} исхода</strong>
|
||||||
|
<small>{distribution(result.dimensionDistributions.presence)}</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Geometry association</span>
|
||||||
|
<strong>
|
||||||
|
{Object.keys(result.dimensionDistributions.geometryAssociation).length}
|
||||||
|
{" исходов"}
|
||||||
|
</strong>
|
||||||
|
<small>{distribution(result.dimensionDistributions.geometryAssociation)}</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Freshness</span>
|
||||||
|
<strong>{Object.keys(result.dimensionDistributions.freshness).length} исхода</strong>
|
||||||
|
<small>{distribution(result.dimensionDistributions.freshness)}</small>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Критичность</span>
|
||||||
|
<strong>{Object.keys(result.severityDistribution).length} уровня</strong>
|
||||||
|
<small>{distribution(result.severityDistribution)}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function E37Result({
|
||||||
|
rigLabel,
|
||||||
|
result,
|
||||||
|
}: {
|
||||||
|
rigLabel: string;
|
||||||
|
result: E37AcceptanceContractResult;
|
||||||
|
}) {
|
||||||
|
const metrics = result.metrics;
|
||||||
|
const percent = (value: number) => (
|
||||||
|
`${(value * 100).toLocaleString("ru-RU", { maximumFractionDigits: 1 })}%`
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<LaboratoryWorkTemplate
|
||||||
|
summary={(
|
||||||
|
<LaboratorySummary
|
||||||
|
title="LAB E37 · контракт приёмки RAVNOVES00 R0"
|
||||||
|
description="Зафиксированы неизменяемый набор проверенных кейсов, отдельный validation holdout и три независимые метрики, по которым дальше будет измеряться качество сенсорного контура. Эта работа определяет честные правила измерения, но ещё не объявляет достижение 90%."
|
||||||
|
status="R0-контракт принят"
|
||||||
|
statusTone="success"
|
||||||
|
facts={[
|
||||||
|
{
|
||||||
|
label: "Конфигурация",
|
||||||
|
value: `${rigLabel} · RAVNOVES00`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Проверено",
|
||||||
|
value: `${formatNumber(metrics.reviewedItems, 0)} / ${formatNumber(metrics.terminalOutcomes, 0)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Holdout",
|
||||||
|
value: `${formatNumber(metrics.validationItems, 0)} validation`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Исполнение",
|
||||||
|
value: `Worker 006 · ${result.workerNode}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
brief={{
|
||||||
|
question: "На каком неизменяемом наборе и по каким отдельным критериям честно измерять приближение сенсорного контура к 90% на RAVNOVES00?",
|
||||||
|
approach: "Все 486 кейсов E30 сведены в одну онтологию presence, geometry association и freshness. Внутри каждого source stratum и диапазона детерминированно заморожен 30-процентный validation holdout; два спорных кейса заменены сохранёнными решениями пользователя.",
|
||||||
|
principalResult: `Учтены все ${formatNumber(metrics.reviewedItems, 0)} кейсов: ${formatNumber(metrics.developmentItems, 0)} development и ${formatNumber(metrics.validationItems, 0)} validation. Потерь учёта и false-free claims нет.`,
|
||||||
|
limitation: "Разметка инженерная и source-scoped, а не независимый ground truth. Точность presence, geometry и freshness в этой работе не вычислялась.",
|
||||||
|
}}
|
||||||
|
method={{
|
||||||
|
completeness: "complete",
|
||||||
|
executionClass: "deterministic",
|
||||||
|
pipelineId: result.profileId,
|
||||||
|
components: [
|
||||||
|
{
|
||||||
|
kind: "source",
|
||||||
|
name: result.sourceDisplayName,
|
||||||
|
version: `${formatNumber(metrics.reviewedItems, 0)} reviewed E30 items`,
|
||||||
|
role: "неизменяемое camera + LiDAR evidence",
|
||||||
|
identitySha256: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "algorithm",
|
||||||
|
name: "Stratified deterministic holdout",
|
||||||
|
version: `${percent(result.split.validationFraction)} validation`,
|
||||||
|
role: "source-stratum и range-balanced split без ручной перетасовки",
|
||||||
|
identitySha256: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "runtime",
|
||||||
|
name: "Worker 006",
|
||||||
|
version: result.workerNode,
|
||||||
|
role: "изолированная offline-сборка контракта без командных полномочий",
|
||||||
|
identitySha256: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
evidence={(
|
||||||
|
<LaboratoryEvidence
|
||||||
|
eyebrow="ЗАМОРОЖЕННЫЙ КОНТРАКТ"
|
||||||
|
title="Онтология, распределение меток и критичность"
|
||||||
|
kind="diagnostic-model"
|
||||||
|
>
|
||||||
|
<ContractEvidence result={result} />
|
||||||
|
</LaboratoryEvidence>
|
||||||
|
)}
|
||||||
|
result={(
|
||||||
|
<LaboratoryResultSummary
|
||||||
|
title="Измерительная база R0 заморожена; quality gate переносится в R1"
|
||||||
|
status="R0 принят"
|
||||||
|
statusTone="success"
|
||||||
|
metrics={[
|
||||||
|
{
|
||||||
|
label: "Полный учёт",
|
||||||
|
value: percent(metrics.accountingFraction),
|
||||||
|
hint: `${formatNumber(metrics.terminalOutcomes, 0)} terminal outcomes`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Development / validation",
|
||||||
|
value: `${formatNumber(metrics.developmentItems, 0)} / ${formatNumber(metrics.validationItems, 0)}`,
|
||||||
|
hint: `${percent(result.split.validationFraction)} holdout`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Human exceptions",
|
||||||
|
value: formatNumber(metrics.humanExceptionItems, 0),
|
||||||
|
hint: `${formatNumber(metrics.engineeringItems, 0)} engineering-reviewed`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "False-free claims",
|
||||||
|
value: formatNumber(metrics.falseFreeClaims, 0),
|
||||||
|
hint: "отсутствие точек не считается свободным пространством",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
conclusion={{
|
||||||
|
proved: "Для RAVNOVES00 зафиксированы воспроизводимый denominator, неизменяемый validation holdout, раздельные метрики presence, geometry association и freshness, полная provenance и 100-процентный terminal accounting.",
|
||||||
|
notProved: "Не доказаны 90-процентная точность ни по одной метрике, независимый ground truth, перенос на другой маршрут или риг, а также пригодность для навигации и safety.",
|
||||||
|
decision: "Принять R0 как единственную измерительную базу RAVNOVES00. Следующая плановая работа R1 должна вычислить baseline на замороженном validation и улучшать development без изменения holdout.",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -68,6 +68,7 @@ const EMPTY_ADVANCED_RESULTS: AdvancedLaboratoryResults = {
|
|||||||
e33: null,
|
e33: null,
|
||||||
e34: null,
|
e34: null,
|
||||||
e35: null,
|
e35: null,
|
||||||
|
e37: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
function digestFromContentId(value: string | null | undefined): string | null {
|
function digestFromContentId(value: string | null | undefined): string | null {
|
||||||
|
|||||||
@@ -299,6 +299,62 @@ function e35() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function e37() {
|
||||||
|
return {
|
||||||
|
result_id: `e37-ravnoves-acceptance-${"7".repeat(64)}`,
|
||||||
|
created_at_utc: "2026-07-27T23:27:02Z",
|
||||||
|
source_session_id: "20260720T065719Z_viewer_live",
|
||||||
|
source_display_name: "RAVNOVES00",
|
||||||
|
status: "accepted-r0-source-scoped-contract",
|
||||||
|
profile_id: "e37-ravnoves00-r0-acceptance/v1",
|
||||||
|
worker_node: "DESKTOP-OPJ8J04",
|
||||||
|
metrics: {
|
||||||
|
reviewed_items: 486,
|
||||||
|
development_items: 340,
|
||||||
|
validation_items: 146,
|
||||||
|
engineering_items: 484,
|
||||||
|
human_exception_items: 2,
|
||||||
|
terminal_outcomes: 486,
|
||||||
|
accounting_fraction: 1,
|
||||||
|
false_free_claims: 0,
|
||||||
|
},
|
||||||
|
dimension_distributions: {
|
||||||
|
presence: {
|
||||||
|
"object-present": 300,
|
||||||
|
"occupied-environment": 104,
|
||||||
|
"background-or-noise": 82,
|
||||||
|
},
|
||||||
|
geometry_association: {
|
||||||
|
"object-associated": 108,
|
||||||
|
"independent-occupied": 104,
|
||||||
|
"insufficient-support": 100,
|
||||||
|
unknown: 92,
|
||||||
|
"rejected-nonobject": 82,
|
||||||
|
},
|
||||||
|
freshness: { current: 292, unavailable: 102, stale: 92 },
|
||||||
|
},
|
||||||
|
severity_distribution: { standard: 290, medium: 71, high: 125 },
|
||||||
|
label_provenance: {
|
||||||
|
engineering_items: 484,
|
||||||
|
human_exception_items: 2,
|
||||||
|
independent_ground_truth: false,
|
||||||
|
},
|
||||||
|
split: {
|
||||||
|
strategy: "deterministic-source-stratum-range-holdout",
|
||||||
|
validation_fraction: 0.3,
|
||||||
|
},
|
||||||
|
targets: {
|
||||||
|
presence_target: 0.9,
|
||||||
|
geometry_association_target: 0.9,
|
||||||
|
freshness_target: 0.9,
|
||||||
|
},
|
||||||
|
quality_target_evaluated: false,
|
||||||
|
limitations: ["source-scoped"],
|
||||||
|
authority,
|
||||||
|
access: "read-only",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
server = await createServer({
|
server = await createServer({
|
||||||
appType: "custom",
|
appType: "custom",
|
||||||
@@ -315,9 +371,9 @@ after(async () => {
|
|||||||
await server?.close();
|
await server?.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("decodes E31–E35 from separate read-only catalogs", async () => {
|
test("decodes E31–E37 from separate read-only catalogs", async () => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
const items = [e31(), e32(), e33(), e34(), e35()];
|
const items = [e31(), e32(), e33(), e34(), e35(), e37()];
|
||||||
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 });
|
||||||
@@ -337,12 +393,16 @@ test("decodes E31–E35 from separate read-only catalogs", async () => {
|
|||||||
assert.equal(decoded.e35.metrics.variantFrameOutcomes, 26934);
|
assert.equal(decoded.e35.metrics.variantFrameOutcomes, 26934);
|
||||||
assert.equal(decoded.e35.scenarios[0].recoverySeconds, 0.086);
|
assert.equal(decoded.e35.scenarios[0].recoverySeconds, 0.086);
|
||||||
assert.equal(decoded.e35.reviewScenarios[0].frames[0].faultPhase, "during");
|
assert.equal(decoded.e35.reviewScenarios[0].frames[0].faultPhase, "during");
|
||||||
|
assert.equal(decoded.e37.metrics.reviewedItems, 486);
|
||||||
|
assert.equal(decoded.e37.metrics.validationItems, 146);
|
||||||
|
assert.equal(decoded.e37.qualityTargetEvaluated, 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" },
|
||||||
{ input: "/api/v1/laboratory/e33/results?limit=1", method: "GET" },
|
{ input: "/api/v1/laboratory/e33/results?limit=1", method: "GET" },
|
||||||
{ input: "/api/v1/laboratory/e34/results?limit=1", method: "GET" },
|
{ input: "/api/v1/laboratory/e34/results?limit=1", method: "GET" },
|
||||||
{ 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" },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -357,7 +417,8 @@ test("rejects authority escalation in an accepted-looking result", async () => {
|
|||||||
String(input).includes("/e31/") ? forged
|
String(input).includes("/e31/") ? forged
|
||||||
: String(input).includes("/e32/") ? e32()
|
: String(input).includes("/e32/") ? e32()
|
||||||
: String(input).includes("/e33/") ? e33()
|
: String(input).includes("/e33/") ? e33()
|
||||||
: String(input).includes("/e34/") ? e34() : e35(),
|
: String(input).includes("/e34/") ? e34()
|
||||||
|
: String(input).includes("/e35/") ? e35() : e37(),
|
||||||
)), { status: 200 }),
|
)), { status: 200 }),
|
||||||
}),
|
}),
|
||||||
AdvancedLaboratoryContractError,
|
AdvancedLaboratoryContractError,
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
# LAB E37 — RAVNOVES00 acceptance contract R0
|
||||||
|
|
||||||
|
## Result identity
|
||||||
|
|
||||||
|
Status: `accepted-r0-source-scoped-contract`.
|
||||||
|
|
||||||
|
Result:
|
||||||
|
`e37-ravnoves-acceptance-01b1efd586f747341c712d82f0907b39436a6f91ae92b1dfae987eca05fd8344`.
|
||||||
|
|
||||||
|
Worker package:
|
||||||
|
`e37-worker-package-960b804df639dd2937895377aa67d5dca4b325f293ab48868d16049da2ff28bc`.
|
||||||
|
|
||||||
|
Physical execution node: `DESKTOP-OPJ8J04` / Worker 006.
|
||||||
|
|
||||||
|
## Question
|
||||||
|
|
||||||
|
E37 does not ask whether K1 has already reached 90% quality. It asks which
|
||||||
|
immutable RAVNOVES00 cases, task ontology, split and metrics will be used to
|
||||||
|
make that claim honestly in the next gate.
|
||||||
|
|
||||||
|
The prior E30 evidence review supplied a useful engineering-reviewed
|
||||||
|
substrate, but it was not yet an acceptance contract. Without freezing the
|
||||||
|
denominator and validation holdout, later tuning could silently move the
|
||||||
|
evaluation set or collapse presence, point ownership and freshness into one
|
||||||
|
ambiguous score.
|
||||||
|
|
||||||
|
## Frozen source and provenance
|
||||||
|
|
||||||
|
Source recording:
|
||||||
|
|
||||||
|
- display name: `RAVNOVES00`;
|
||||||
|
- session: `20260720T065719Z_viewer_live`;
|
||||||
|
- classification: immutable private physical recording.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
|
||||||
|
- E30 materialization:
|
||||||
|
`e30-materialization-841af926d8d28ab93538c46d8f31278a2234c4d1c12c7dc4dc296b249d59735a`;
|
||||||
|
- E30 engineering generation:
|
||||||
|
`e30-engineering-generation-62a4fea10dea9b77f69ceac1af5bf0e4928d9c7716083c22258a03670fe5bd4f`;
|
||||||
|
- E30 human exception generation:
|
||||||
|
`e30-review-generation-7982a882558d0be690b4c7092e328c080bfcbf52478a220452be7e887a588250`.
|
||||||
|
|
||||||
|
The result binds the exact manifest and decision-file SHA-256 values for all
|
||||||
|
three inputs. Of 486 terminal labels, 484 come from the accepted engineering
|
||||||
|
generation and two from the saved user exception decisions. These labels are
|
||||||
|
not described as independent ground truth.
|
||||||
|
|
||||||
|
## Method
|
||||||
|
|
||||||
|
Profile: `e37-ravnoves00-r0-acceptance/v1`.
|
||||||
|
|
||||||
|
The deterministic builder:
|
||||||
|
|
||||||
|
1. verifies the exact E30 identities and artifact digests;
|
||||||
|
2. requires one engineering decision for every materialized review item;
|
||||||
|
3. requires human decisions to match the declared exception set exactly;
|
||||||
|
4. projects each reviewed item into three independent dimensions:
|
||||||
|
presence, geometry association and freshness;
|
||||||
|
5. assigns severity without changing the reviewed outcome;
|
||||||
|
6. creates a deterministic 30% validation holdout inside each source-stratum
|
||||||
|
and range bucket using seed `ravnoves00-r0-validation-v1`;
|
||||||
|
7. closes terminal accounting and rejects any free-space claim;
|
||||||
|
8. publishes four immutable artifacts atomically.
|
||||||
|
|
||||||
|
The worker package contains only the runtime projection, profile and the six
|
||||||
|
required input manifest/data files. Execution used the pinned Triton image
|
||||||
|
with no network, a read-only container filesystem, dropped capabilities,
|
||||||
|
`no-new-privileges`, a bounded PID limit and no GPU allocation.
|
||||||
|
|
||||||
|
## Contract
|
||||||
|
|
||||||
|
| Measure | Result |
|
||||||
|
| --- | ---: |
|
||||||
|
| reviewed items | 486 |
|
||||||
|
| development items | 340 |
|
||||||
|
| validation items | 146 |
|
||||||
|
| terminal outcomes | 486 |
|
||||||
|
| accounting | 100% |
|
||||||
|
| engineering-reviewed labels | 484 |
|
||||||
|
| human exception labels | 2 |
|
||||||
|
| false-free claims | 0 |
|
||||||
|
|
||||||
|
Frozen distributions:
|
||||||
|
|
||||||
|
- presence: 300 `object-present`, 104 `occupied-environment`,
|
||||||
|
82 `background-or-noise`;
|
||||||
|
- geometry association: 108 `object-associated`,
|
||||||
|
104 `independent-occupied`, 100 `insufficient-support`,
|
||||||
|
92 `unknown`, 82 `rejected-nonobject`;
|
||||||
|
- freshness: 292 `current`, 102 `unavailable`, 92 `stale`;
|
||||||
|
- severity: 290 `standard`, 71 `medium`, 125 `high`.
|
||||||
|
|
||||||
|
The following targets are declared separately for R1 and later gates:
|
||||||
|
|
||||||
|
- presence quality: at least 90%;
|
||||||
|
- geometry-association quality: at least 90%;
|
||||||
|
- freshness quality: at least 90%;
|
||||||
|
- accounting: 100%;
|
||||||
|
- false-free claims: zero.
|
||||||
|
|
||||||
|
## Acceptance
|
||||||
|
|
||||||
|
All seven predeclared R0 checks pass:
|
||||||
|
|
||||||
|
- source identity is frozen;
|
||||||
|
- reviewed denominator is complete;
|
||||||
|
- development and validation split is complete;
|
||||||
|
- every item has a terminal label in all three dimensions;
|
||||||
|
- human exception accounting is complete;
|
||||||
|
- false-free claims are zero;
|
||||||
|
- authority remains diagnostic.
|
||||||
|
|
||||||
|
## What this proves
|
||||||
|
|
||||||
|
RAVNOVES00 now has one reproducible source-scoped evaluation contract. Future
|
||||||
|
algorithm changes can use the 340-item development set without changing the
|
||||||
|
146-item validation holdout, label ontology or denominator. Presence,
|
||||||
|
geometry association and freshness can no longer be reported as one blended
|
||||||
|
success score.
|
||||||
|
|
||||||
|
## What this does not prove
|
||||||
|
|
||||||
|
E37 does not evaluate or pass any 90% quality target. It does not provide
|
||||||
|
independent ground truth, prove another route, camera, rig or mount, validate
|
||||||
|
free space, or grant navigation, command or safety authority.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Accept R0 as the only RAVNOVES00 measurement basis. The next planned K1
|
||||||
|
laboratory gate is R1: compute the first source-scoped perception-quality
|
||||||
|
baseline on the frozen validation holdout, diagnose the separate deficits and
|
||||||
|
tune only against the development partition.
|
||||||
|
|
||||||
@@ -34,6 +34,11 @@ from k1link.compute.e35_degradation_replay import (
|
|||||||
E35DegradationReplayError,
|
E35DegradationReplayError,
|
||||||
read_e35_degradation_replay,
|
read_e35_degradation_replay,
|
||||||
)
|
)
|
||||||
|
from k1link.compute.e37_acceptance_contract import (
|
||||||
|
E37AcceptanceContract,
|
||||||
|
E37AcceptanceContractError,
|
||||||
|
read_e37_acceptance_contract,
|
||||||
|
)
|
||||||
|
|
||||||
LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = (
|
LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = (
|
||||||
"missioncore.laboratory-advanced-catalog/v1"
|
"missioncore.laboratory-advanced-catalog/v1"
|
||||||
@@ -44,6 +49,7 @@ _E32_RESULT_ID = re.compile(r"^e32-track-geometry-[a-f0-9]{64}$")
|
|||||||
_E33_RESULT_ID = re.compile(r"^e33-worker-shadow-[a-f0-9]{64}$")
|
_E33_RESULT_ID = re.compile(r"^e33-worker-shadow-[a-f0-9]{64}$")
|
||||||
_E34_RESULT_ID = re.compile(r"^e34-temporal-occupied-[a-f0-9]{64}$")
|
_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}$")
|
||||||
|
|
||||||
RootProvider = Callable[[], Path | None]
|
RootProvider = Callable[[], Path | None]
|
||||||
|
|
||||||
@@ -103,6 +109,15 @@ def _read_e35_cached(
|
|||||||
return read_e35_degradation_replay(Path(root_text))
|
return read_e35_degradation_replay(Path(root_text))
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(maxsize=16)
|
||||||
|
def _read_e37_cached(
|
||||||
|
root_text: str,
|
||||||
|
signature: tuple[int, ...],
|
||||||
|
) -> E37AcceptanceContract:
|
||||||
|
del signature
|
||||||
|
return read_e37_acceptance_contract(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:
|
||||||
@@ -486,6 +501,60 @@ def _project_e35(result: E35DegradationReplay) -> dict[str, object]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _project_e37(result: E37AcceptanceContract) -> dict[str, object]:
|
||||||
|
identity = _object(result.manifest.get("identity"), "E37 identity")
|
||||||
|
source = _object(identity.get("source"), "E37 source")
|
||||||
|
execution = _object(identity.get("execution"), "E37 execution")
|
||||||
|
profile = _object(identity.get("profile"), "E37 profile")
|
||||||
|
provenance = _object(
|
||||||
|
result.contract.get("label_provenance"),
|
||||||
|
"E37 label provenance",
|
||||||
|
)
|
||||||
|
metrics = _object(result.report.get("metrics"), "E37 metrics")
|
||||||
|
decision = _object(result.report.get("decision"), "E37 decision")
|
||||||
|
acceptance = _object(result.report.get("acceptance"), "E37 acceptance")
|
||||||
|
if acceptance.get("accepted") is not True:
|
||||||
|
raise ValueError("E37 result is not accepted")
|
||||||
|
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.manifest.get("acceptance_state"),
|
||||||
|
"profile_id": profile.get("profile_id"),
|
||||||
|
"worker_node": execution.get("worker_node"),
|
||||||
|
"metrics": {
|
||||||
|
"reviewed_items": metrics.get("reviewed_items"),
|
||||||
|
"development_items": metrics.get("development_items"),
|
||||||
|
"validation_items": metrics.get("validation_items"),
|
||||||
|
"engineering_items": metrics.get("engineering_items"),
|
||||||
|
"human_exception_items": metrics.get("human_exception_items"),
|
||||||
|
"terminal_outcomes": metrics.get("terminal_outcomes"),
|
||||||
|
"accounting_fraction": metrics.get("accounting_fraction"),
|
||||||
|
"false_free_claims": metrics.get("false_free_claims"),
|
||||||
|
},
|
||||||
|
"dimension_distributions": copy.deepcopy(
|
||||||
|
result.contract.get("dimension_distributions")
|
||||||
|
),
|
||||||
|
"severity_distribution": copy.deepcopy(
|
||||||
|
result.contract.get("severity_distribution")
|
||||||
|
),
|
||||||
|
"label_provenance": {
|
||||||
|
"engineering_items": provenance.get("engineering_items"),
|
||||||
|
"human_exception_items": provenance.get("human_exception_items"),
|
||||||
|
"independent_ground_truth": provenance.get(
|
||||||
|
"independent_ground_truth"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"split": copy.deepcopy(result.contract.get("split")),
|
||||||
|
"targets": copy.deepcopy(result.contract.get("targets")),
|
||||||
|
"quality_target_evaluated": decision.get("quality_target_evaluated"),
|
||||||
|
"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,
|
||||||
@@ -504,6 +573,7 @@ def build_advanced_laboratory_router(
|
|||||||
e33_root_provider: RootProvider = lambda: None,
|
e33_root_provider: RootProvider = lambda: None,
|
||||||
e34_root_provider: RootProvider = lambda: None,
|
e34_root_provider: RootProvider = lambda: None,
|
||||||
e35_root_provider: RootProvider = lambda: None,
|
e35_root_provider: RootProvider = lambda: None,
|
||||||
|
e37_root_provider: RootProvider = lambda: None,
|
||||||
) -> APIRouter:
|
) -> APIRouter:
|
||||||
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
|
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
|
||||||
|
|
||||||
@@ -698,4 +768,39 @@ def build_advanced_laboratory_router(
|
|||||||
"invalid_total": invalid_total,
|
"invalid_total": invalid_total,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@router.get("/e37/results")
|
||||||
|
def list_e37_results(
|
||||||
|
limit: int = Query(default=1, ge=1, le=10),
|
||||||
|
) -> dict[str, object]:
|
||||||
|
root = _configured_root(e37_root_provider)
|
||||||
|
if root is None:
|
||||||
|
return _empty_catalog(False)
|
||||||
|
candidates = _candidates(root, _E37_RESULT_ID)
|
||||||
|
items: list[dict[str, object]] = []
|
||||||
|
invalid_total = 0
|
||||||
|
for candidate in candidates:
|
||||||
|
try:
|
||||||
|
result = _read_e37_cached(
|
||||||
|
str(candidate.resolve()),
|
||||||
|
_result_signature(candidate),
|
||||||
|
)
|
||||||
|
if not result.accepted:
|
||||||
|
raise ValueError("E37 result is not accepted")
|
||||||
|
if len(items) < limit:
|
||||||
|
items.append(_project_e37(result))
|
||||||
|
except (
|
||||||
|
E37AcceptanceContractError,
|
||||||
|
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
|
||||||
|
|||||||
@@ -536,6 +536,13 @@ app.include_router(
|
|||||||
/ "e35"
|
/ "e35"
|
||||||
/ "results"
|
/ "results"
|
||||||
),
|
),
|
||||||
|
e37_root_provider=lambda: (
|
||||||
|
REPOSITORY_ROOT
|
||||||
|
/ ".runtime"
|
||||||
|
/ "compute-experiments"
|
||||||
|
/ "e37"
|
||||||
|
/ "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"):
|
for name in ("e31", "e32", "e33", "e34", "e35", "e37"):
|
||||||
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 == {
|
||||||
@@ -47,22 +47,25 @@ def test_advanced_catalogs_fail_closed_on_incomplete_results(
|
|||||||
e33 = tmp_path / "e33"
|
e33 = tmp_path / "e33"
|
||||||
e34 = tmp_path / "e34"
|
e34 = tmp_path / "e34"
|
||||||
e35 = tmp_path / "e35"
|
e35 = tmp_path / "e35"
|
||||||
for root in (e31, e32, e33, e34, e35):
|
e37 = tmp_path / "e37"
|
||||||
|
for root in (e31, e32, e33, e34, e35, e37):
|
||||||
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()
|
||||||
(e33 / f"e33-worker-shadow-{'3' * 64}").mkdir()
|
(e33 / f"e33-worker-shadow-{'3' * 64}").mkdir()
|
||||||
(e34 / f"e34-temporal-occupied-{'4' * 64}").mkdir()
|
(e34 / f"e34-temporal-occupied-{'4' * 64}").mkdir()
|
||||||
(e35 / f"e35-degradation-recovery-{'5' * 64}").mkdir()
|
(e35 / f"e35-degradation-recovery-{'5' * 64}").mkdir()
|
||||||
|
(e37 / f"e37-ravnoves-acceptance-{'7' * 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,
|
||||||
e33_root_provider=lambda: e33,
|
e33_root_provider=lambda: e33,
|
||||||
e34_root_provider=lambda: e34,
|
e34_root_provider=lambda: e34,
|
||||||
e35_root_provider=lambda: e35,
|
e35_root_provider=lambda: e35,
|
||||||
|
e37_root_provider=lambda: e37,
|
||||||
)
|
)
|
||||||
|
|
||||||
for name in ("e31", "e32", "e33", "e34", "e35"):
|
for name in ("e31", "e32", "e33", "e34", "e35", "e37"):
|
||||||
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
|
||||||
@@ -312,3 +315,110 @@ def test_e35_catalog_projects_recovery_and_review(
|
|||||||
assert item["review"]["scenarios"] == []
|
assert item["review"]["scenarios"] == []
|
||||||
assert item["authority"] == authority
|
assert item["authority"] == authority
|
||||||
assert item["access"] == "read-only"
|
assert item["access"] == "read-only"
|
||||||
|
|
||||||
|
|
||||||
|
def test_e37_catalog_projects_the_frozen_r0_contract(
|
||||||
|
tmp_path: Path,
|
||||||
|
monkeypatch: MonkeyPatch,
|
||||||
|
) -> None:
|
||||||
|
result_id = f"e37-ravnoves-acceptance-{'7' * 64}"
|
||||||
|
root = tmp_path / "e37"
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
result = SimpleNamespace(
|
||||||
|
result_id=result_id,
|
||||||
|
accepted=True,
|
||||||
|
manifest={
|
||||||
|
"created_at_utc": "2026-07-28T10:00:00Z",
|
||||||
|
"acceptance_state": "accepted-r0-source-scoped-contract",
|
||||||
|
"identity": {
|
||||||
|
"source": {
|
||||||
|
"session_id": "20260720T065719Z_viewer_live",
|
||||||
|
"display_name": "RAVNOVES00",
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"profile_id": "e37-ravnoves00-r0-acceptance/v1",
|
||||||
|
},
|
||||||
|
"execution": {
|
||||||
|
"class": "deterministic-offline-contract-build",
|
||||||
|
"worker_node": "DESKTOP-OPJ8J04",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
contract={
|
||||||
|
"dimension_distributions": {
|
||||||
|
"presence": {"object-present": 200, "unknown": 2},
|
||||||
|
"geometry_association": {
|
||||||
|
"object-associated": 180,
|
||||||
|
"unknown": 2,
|
||||||
|
},
|
||||||
|
"freshness": {"current": 300, "unavailable": 186},
|
||||||
|
},
|
||||||
|
"severity_distribution": {
|
||||||
|
"standard": 401,
|
||||||
|
"medium": 81,
|
||||||
|
"high": 4,
|
||||||
|
},
|
||||||
|
"label_provenance": {
|
||||||
|
"engineering_items": 484,
|
||||||
|
"human_exception_items": 2,
|
||||||
|
"independent_ground_truth": False,
|
||||||
|
},
|
||||||
|
"split": {
|
||||||
|
"strategy": "deterministic-source-stratum-range-holdout",
|
||||||
|
"validation_fraction": 0.3,
|
||||||
|
},
|
||||||
|
"targets": {
|
||||||
|
"presence_target": 0.9,
|
||||||
|
"geometry_association_target": 0.9,
|
||||||
|
"freshness_target": 0.9,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
report={
|
||||||
|
"metrics": {
|
||||||
|
"reviewed_items": 486,
|
||||||
|
"development_items": 340,
|
||||||
|
"validation_items": 146,
|
||||||
|
"engineering_items": 484,
|
||||||
|
"human_exception_items": 2,
|
||||||
|
"terminal_outcomes": 486,
|
||||||
|
"accounting_fraction": 1.0,
|
||||||
|
"false_free_claims": 0,
|
||||||
|
},
|
||||||
|
"acceptance": {"accepted": True, "checks": {}},
|
||||||
|
"decision": {"quality_target_evaluated": 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_e37_cached", fake_read)
|
||||||
|
router = build_advanced_laboratory_router(
|
||||||
|
e37_root_provider=lambda: root,
|
||||||
|
)
|
||||||
|
route = _endpoint(router, "/api/v1/laboratory/e37/results")
|
||||||
|
catalog = route(limit=1) # type: ignore[operator]
|
||||||
|
|
||||||
|
assert catalog["candidate_total"] == 1
|
||||||
|
assert catalog["invalid_total"] == 0
|
||||||
|
item = catalog["items"][0]
|
||||||
|
assert item["status"] == "accepted-r0-source-scoped-contract"
|
||||||
|
assert item["worker_node"] == "DESKTOP-OPJ8J04"
|
||||||
|
assert item["metrics"]["reviewed_items"] == 486
|
||||||
|
assert item["metrics"]["validation_items"] == 146
|
||||||
|
assert item["quality_target_evaluated"] is False
|
||||||
|
assert item["authority"] == authority
|
||||||
|
assert item["access"] == "read-only"
|
||||||
|
|||||||
Reference in New Issue
Block a user