Type EveUnity capture contract

This commit is contained in:
Meta Vens 2026-07-09 09:57:17 +01:00
commit ceb6e005c4
7 changed files with 140 additions and 1 deletions

View file

@ -421,6 +421,12 @@ Recently cut:
compares it against the ledger, and the runtime-owner consumer smoke asserts
the exported release fields without pretending the tagged EveUnity release
already exists.
- EveUnity capture lifecycle now carries a structured pending capture contract.
`captureContract` names the Unity UI Toolkit runtime, capture kind, PNG
artifact pattern, conformance attachment point, required Aetheria provider
surface, and authority rule. The lifecycle smoke and runtime-owner consumer
smoke assert those fields while keeping the actual capture artifact as a
split blocker for EveUnity.
- Runtime-owner conformance consumption now asserts EveUnity lifecycle stage
evidence directly. The generic consumer supports
`--expect-runtime-lifecycle-status` and

View file

@ -116,6 +116,18 @@
"capture": {
"ownerRepo": "EveUnity",
"status": "pending-editor-capture",
"captureContract": {
"ownerRepo": "EveUnity",
"runtimeId": "unity-uitoolkit",
"captureKind": "unity-editor-or-batchmode-png",
"artifactKind": "png",
"artifactPattern": "artifacts/eveunity-uitoolkit-capture/{stamp}/unity-uitoolkit.png",
"conformanceAttachment": "runtime.captureArtifacts[]",
"requiredProvider": "aetheria",
"requiredSurface": "aetheria.daemon.game",
"authority": "Capture observes runtime projection only; provider state, command acceptance, and receipts stay provider-owned.",
"publishProof": "Unity editor or batchmode capture artifact is attached to the runtime conformance report from EveUnity."
},
"evidencePaths": [],
"pendingProofs": [
"Unity batchmode or editor capture artifact attached to the runtime conformance report."

View file

@ -378,6 +378,64 @@
"command": {
"type": "string"
},
"captureContract": {
"type": "object",
"required": [
"ownerRepo",
"runtimeId",
"captureKind",
"artifactKind",
"artifactPattern",
"conformanceAttachment",
"requiredProvider",
"requiredSurface",
"authority",
"publishProof"
],
"properties": {
"ownerRepo": {
"type": "string",
"minLength": 1
},
"runtimeId": {
"type": "string",
"minLength": 1
},
"captureKind": {
"type": "string",
"minLength": 1
},
"artifactKind": {
"type": "string",
"minLength": 1
},
"artifactPattern": {
"type": "string",
"minLength": 1
},
"conformanceAttachment": {
"type": "string",
"minLength": 1
},
"requiredProvider": {
"type": "string",
"minLength": 1
},
"requiredSurface": {
"type": "string",
"minLength": 1
},
"authority": {
"type": "string",
"minLength": 1
},
"publishProof": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": true
},
"evidencePaths": {
"type": "array",
"items": {

View file

@ -158,6 +158,28 @@ foreach ($expectedText in @($testContract.packageName, $testContract.testAssembl
}
}
$captureContract = $manifest.lifecycle.capture.captureContract
if ($null -eq $captureContract) {
throw "EveUnity capture lifecycle missing captureContract"
}
if ($captureContract.ownerRepo -ne "EveUnity") {
throw "EveUnity capture contract has unexpected owner: $($captureContract.ownerRepo)"
}
if ($captureContract.runtimeId -ne "unity-uitoolkit") {
throw "EveUnity capture contract has unexpected runtime: $($captureContract.runtimeId)"
}
if ($captureContract.captureKind -ne "unity-editor-or-batchmode-png") {
throw "EveUnity capture contract has unexpected capture kind: $($captureContract.captureKind)"
}
if ($captureContract.artifactKind -ne "png") {
throw "EveUnity capture contract has unexpected artifact kind: $($captureContract.artifactKind)"
}
foreach ($field in @("artifactPattern", "conformanceAttachment", "requiredProvider", "requiredSurface", "authority", "publishProof")) {
if (-not $captureContract.$field) {
throw "EveUnity capture contract missing $field"
}
}
& (Join-Path $projectRoot "scripts\run-aetheria-unity-package-smoke.ps1")
if ($LASTEXITCODE -ne 0) {
throw "Aetheria Unity package smoke failed with exit code $LASTEXITCODE"

View file

@ -95,7 +95,12 @@ node $consumerScript $consumerExport `
--expect-runtime-lifecycle-field "unity-uitoolkit:test:testContract.runnerScript:scripts/run-aetheria-unity-editmode-tests.ps1" `
--expect-runtime-lifecycle-field "unity-uitoolkit:test:testContract.packageName:org.gamecult.eve.unity-uitoolkit" `
--expect-runtime-lifecycle-field "unity-uitoolkit:test:testContract.testAssembly:GameCult.Eve.UnityUIToolkit.Tests" `
--expect-runtime-lifecycle-field "unity-uitoolkit:test:testContract.testPlatform:EditMode"
--expect-runtime-lifecycle-field "unity-uitoolkit:test:testContract.testPlatform:EditMode" `
--expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.captureKind:unity-editor-or-batchmode-png" `
--expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.artifactKind:png" `
--expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.conformanceAttachment:runtime.captureArtifacts[]" `
--expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.requiredProvider:aetheria" `
--expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.requiredSurface:aetheria.daemon.game"
if ($LASTEXITCODE -ne 0) {
throw "Runtime owner conformance consumer smoke failed with exit code $LASTEXITCODE"

View file

@ -1250,6 +1250,18 @@
"capture": {
"ownerRepo": "EveUnity",
"status": "pending-editor-capture",
"captureContract": {
"ownerRepo": "EveUnity",
"runtimeId": "unity-uitoolkit",
"captureKind": "unity-editor-or-batchmode-png",
"artifactKind": "png",
"artifactPattern": "artifacts/eveunity-uitoolkit-capture/{stamp}/unity-uitoolkit.png",
"conformanceAttachment": "runtime.captureArtifacts[]",
"requiredProvider": "aetheria",
"requiredSurface": "aetheria.daemon.game",
"authority": "Capture observes runtime projection only; provider state, command acceptance, and receipts stay provider-owned.",
"publishProof": "Unity editor or batchmode capture artifact is attached to the runtime conformance report from EveUnity."
},
"evidencePaths": [],
"pendingProofs": [
"Unity batchmode or editor capture artifact attached to the runtime conformance report."

View file

@ -1254,6 +1254,7 @@ function compareRuntimeLifecycleClaims(expectedLifecycle, actualLifecycle, manif
errors.push(...missingMembers(expected.pendingProofs || [], actual.pendingProofs || [], `${label}.pendingProofs`));
errors.push(...compareReleaseContract(expected.releaseContract, actual.releaseContract, `${label}.releaseContract`));
errors.push(...compareTestContract(expected.testContract, actual.testContract, `${label}.testContract`));
errors.push(...compareCaptureContract(expected.captureContract, actual.captureContract, `${label}.captureContract`));
for (const evidencePath of actual.evidencePaths || []) {
if (!existsSync(path.join(repoRoot, evidencePath))) {
@ -1264,6 +1265,29 @@ function compareRuntimeLifecycleClaims(expectedLifecycle, actualLifecycle, manif
return errors;
}
function compareCaptureContract(expected, actual, label) {
const errors = [];
if (!expected) return errors;
if (!actual) return [`${label}:missing`];
for (const key of [
"ownerRepo",
"runtimeId",
"captureKind",
"artifactKind",
"artifactPattern",
"conformanceAttachment",
"requiredProvider",
"requiredSurface",
"authority",
"publishProof",
]) {
if ((expected[key] || "") !== (actual[key] || "")) {
errors.push(`${label}.${key}:expected ${expected[key] || ""} got ${actual[key] || ""}`);
}
}
return errors;
}
function compareTestContract(expected, actual, label) {
const errors = [];
if (!expected) return errors;