Assert runtime lifecycle in conformance export

This commit is contained in:
Meta Vens 2026-07-09 02:12:33 +01:00
commit 06fea925ff
4 changed files with 65 additions and 2 deletions

View file

@ -280,6 +280,13 @@ Exit criteria:
Recently cut:
- Runtime-owner conformance consumption now asserts EveUnity lifecycle stage
evidence directly. The generic consumer supports
`--expect-runtime-lifecycle-status` and
`--expect-runtime-lifecycle-pending`; the runtime-owner smoke verifies the
Unity UI Toolkit release/test/capture statuses plus the tagged UPM release,
batchmode runner, and capture artifact pending proofs from the exported
runtime record.
- Plugin manifests and advertisements now carry a runtime-independent sidecar
ABI boundary. Sai, Norn, and TeX declare `invocationModel:
executable-sidecar`, `gamecult.eve.plugin_abi.v1`, CultMesh/stdio transports,

View file

@ -115,7 +115,9 @@ The runtime conformance pack is evidence-shaped, not fixture-shaped. Its
`packs/runtime.json` document includes `runtimeTargets` so runtime repos can
consume status, supported features, plugin support, command schema, lifecycle,
capture status, and missing evidence without reading Eve's local parity
manifest.
manifest. The runtime-owner consumer smoke asserts EveUnity lifecycle stage
status and pending release/test/capture proofs from the exported runtime record,
so split blockers stay machine-readable instead of hiding in handoff prose.
After generating the parity report, `run-parity-harness.ps1` copies
`artifacts/conformance/latest` into

View file

@ -57,7 +57,13 @@ node $consumerScript $consumerExport `
--expect-runtime-capture-status linux-flutter:ssh-golden `
--expect-runtime-capture-status android-flutter:adb-png `
--expect-runtime-capture-status unity-uitoolkit:semantic `
--expect-runtime-capture-status direct2d:missing
--expect-runtime-capture-status direct2d:missing `
--expect-runtime-lifecycle-status unity-uitoolkit:release:incubating-upm-package `
--expect-runtime-lifecycle-status unity-uitoolkit:test:batchmode-editmode-tests-and-consumer-build-smoke `
--expect-runtime-lifecycle-status unity-uitoolkit:capture:pending-editor-capture `
--expect-runtime-lifecycle-pending "unity-uitoolkit:release:Tagged UPM release" `
--expect-runtime-lifecycle-pending "unity-uitoolkit:test:Unity batchmode EditMode runner" `
--expect-runtime-lifecycle-pending "unity-uitoolkit:capture:Unity batchmode or editor capture artifact"
if ($LASTEXITCODE -ne 0) {
throw "Runtime owner conformance consumer smoke failed with exit code $LASTEXITCODE"

View file

@ -35,6 +35,8 @@ if (!exportDirectory) {
" --expect-runtime-handoff <runtimeId>",
" --expect-runtime-command-schema <runtimeId:schema>",
" --expect-runtime-capture-status <runtimeId:status>",
" --expect-runtime-lifecycle-status <runtimeId:stage:status>",
" --expect-runtime-lifecycle-pending <runtimeId:stage:pending-proof-substring>",
" --expect-split-target-status <targetId:status>",
" --expect-split-target-blocker <targetId:blocker-substring>",
" --expect-split-target-proof <targetId:proof-substring>",
@ -298,6 +300,31 @@ function validateIndex(index, directory, expectations, errors) {
errors.push(`runtimes:${expectation.runtimeId}:captureStatus:expected ${expectation.status} got ${runtime.captureStatus || ""}`);
}
}
for (const expectation of expectations.runtimeLifecycleStatuses) {
const runtime = runtimes.find(candidate => candidate.runtimeId === expectation.runtimeId);
if (!runtime) {
errors.push(`runtimes:${expectation.runtimeId}:missing`);
continue;
}
const stage = runtime.lifecycle?.[expectation.stage];
if (!stage) {
errors.push(`runtimes:${expectation.runtimeId}:lifecycle.${expectation.stage}:missing`);
} else if (stage.status !== expectation.status) {
errors.push(`runtimes:${expectation.runtimeId}:lifecycle.${expectation.stage}.status:expected ${expectation.status} got ${stage.status || ""}`);
}
}
for (const expectation of expectations.runtimeLifecyclePendingProofs) {
const runtime = runtimes.find(candidate => candidate.runtimeId === expectation.runtimeId);
if (!runtime) {
errors.push(`runtimes:${expectation.runtimeId}:missing`);
continue;
}
const stage = runtime.lifecycle?.[expectation.stage];
const pendingProofs = Array.isArray(stage?.pendingProofs) ? stage.pendingProofs : [];
if (!pendingProofs.some(proof => proof.includes(expectation.pendingProof))) {
errors.push(`runtimes:${expectation.runtimeId}:lifecycle.${expectation.stage}.pendingProof:${expectation.pendingProof}:missing`);
}
}
for (const expectedRuntime of expectations.runtimeHandoffs) {
const runtime = runtimes.find(candidate => candidate.runtimeId === expectedRuntime);
if (!runtime) {
@ -471,6 +498,8 @@ function parseArguments(args) {
runtimeHandoffs: [],
runtimeCommandSchemas: [],
runtimeCaptureStatuses: [],
runtimeLifecycleStatuses: [],
runtimeLifecyclePendingProofs: [],
scenarios: [],
splitTargets: [],
splitTargetStatuses: [],
@ -504,6 +533,8 @@ function parseArguments(args) {
["--expect-runtime-handoff", expectations.runtimeHandoffs],
["--expect-runtime-command-schema", expectations.runtimeCommandSchemas],
["--expect-runtime-capture-status", expectations.runtimeCaptureStatuses],
["--expect-runtime-lifecycle-status", expectations.runtimeLifecycleStatuses],
["--expect-runtime-lifecycle-pending", expectations.runtimeLifecyclePendingProofs],
["--expect-split-target-status", expectations.splitTargetStatuses],
["--expect-split-target-blocker", expectations.splitTargetBlockers],
["--expect-split-target-proof", expectations.splitTargetProofs],
@ -562,6 +593,10 @@ function parseArguments(args) {
target.push(parseRuntimeExpectation(value, "schema"));
} else if (option === "--expect-runtime-capture-status") {
target.push(parseRuntimeExpectation(value, "status"));
} else if (option === "--expect-runtime-lifecycle-status") {
target.push(parseRuntimeLifecycleExpectation(value, "status"));
} else if (option === "--expect-runtime-lifecycle-pending") {
target.push(parseRuntimeLifecycleExpectation(value, "pendingProof"));
} else if (option === "--expect-split-target-status") {
target.push(parseSplitTargetExpectation(value, "status"));
} else if (option === "--expect-split-target-blocker") {
@ -626,6 +661,19 @@ function parseRuntimeExpectation(value, field) {
};
}
function parseRuntimeLifecycleExpectation(value, field) {
const parts = value.split(":");
if (parts.length < 3 || !parts[0] || !parts[1] || !parts.slice(2).join(":")) {
console.error(`Expected runtime lifecycle ${field} in <runtimeId:stage:${field}> form, got: ${value}`);
process.exit(2);
}
return {
runtimeId: parts[0],
stage: parts[1],
[field]: parts.slice(2).join(":"),
};
}
function parseSplitTargetExpectation(value, field) {
const separator = value.indexOf(":");
if (separator <= 0 || separator === value.length - 1) {