Schema-back runtime lifecycle evidence
This commit is contained in:
parent
811a4da395
commit
3f47ac0f31
11 changed files with 323 additions and 4 deletions
|
|
@ -430,6 +430,13 @@ Recently cut:
|
|||
demand those contracts explicitly, so Sai, Norn, EvePlugins, Aetheria, and
|
||||
EveConformance can consume handoff shape without depending on Eve's local
|
||||
smoke script folklore.
|
||||
- Runtime lifecycle shape is now schema-backed as
|
||||
`gamecult.eve.runtime_lifecycle.v1`. Flutter's standalone
|
||||
`eveflutter-lifecycle.json` validates against that contract, embedded
|
||||
release/test/capture lifecycle blocks in runtime capability manifests are
|
||||
wrapped and validated through the same schema, and the conformance export
|
||||
carries `lifecycleManifestPath` plus `lifecycleErrors` so runtime owners can
|
||||
consume lifecycle status without guessing from prose.
|
||||
- EveElectron now has a pending split target and handoff at
|
||||
`runtimes/incubating/eve-electron/eveelectron-split-handoff.json`. It does
|
||||
claim a provider-agnostic Electron shell surface-tree projection and command
|
||||
|
|
|
|||
|
|
@ -224,6 +224,10 @@ Plugin, provider, and EveConformance handoff documents are also schema-backed:
|
|||
`gamecult.eve.plugin_handoff.v1`, `gamecult.eve.provider_handoff.v1`, and
|
||||
`gamecult.eve.conformance_handoff.v1` are exported through the schema catalog.
|
||||
Owner consumer smokes assert those schemas before trusting handoff paths.
|
||||
Runtime lifecycle records use `gamecult.eve.runtime_lifecycle.v1`. Standalone
|
||||
lifecycle documents such as `flutter/eve_parity/eveflutter-lifecycle.json` and
|
||||
embedded runtime capability lifecycle blocks validate against the same stage
|
||||
shape, and exported runtime records carry `lifecycleErrors`.
|
||||
|
||||
After generating the parity report, `run-parity-harness.ps1` copies
|
||||
`artifacts/conformance/latest` into
|
||||
|
|
|
|||
|
|
@ -1020,6 +1020,12 @@
|
|||
"capabilityManifestErrors": {
|
||||
"type": "array"
|
||||
},
|
||||
"lifecycleManifestPath": {
|
||||
"type": "string"
|
||||
},
|
||||
"lifecycleErrors": {
|
||||
"type": "array"
|
||||
},
|
||||
"splitHandoffPath": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
|||
178
schemas/gamecult.eve.runtime_lifecycle.v1.schema.json
Normal file
178
schemas/gamecult.eve.runtime_lifecycle.v1.schema.json
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "gamecult.eve.runtime_lifecycle.v1",
|
||||
"title": "Eve Runtime Lifecycle",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"schema",
|
||||
"splitTarget",
|
||||
"ownerRepo",
|
||||
"currentHostRepo",
|
||||
"runtimes",
|
||||
"release",
|
||||
"test",
|
||||
"capture"
|
||||
],
|
||||
"properties": {
|
||||
"schema": {
|
||||
"const": "gamecult.eve.runtime_lifecycle.v1"
|
||||
},
|
||||
"splitTarget": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"ownerRepo": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"currentHostRepo": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"runtimes": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"release": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ownerRepo",
|
||||
"status",
|
||||
"evidencePaths"
|
||||
],
|
||||
"properties": {
|
||||
"ownerRepo": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"commands": {
|
||||
"type": "array"
|
||||
},
|
||||
"releaseContract": {
|
||||
"type": "object"
|
||||
},
|
||||
"evidencePaths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"pendingProofs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"test": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ownerRepo",
|
||||
"status",
|
||||
"evidencePaths"
|
||||
],
|
||||
"properties": {
|
||||
"ownerRepo": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"commands": {
|
||||
"type": "array"
|
||||
},
|
||||
"testContract": {
|
||||
"type": "object"
|
||||
},
|
||||
"evidencePaths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"pendingProofs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"capture": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ownerRepo",
|
||||
"status",
|
||||
"evidencePaths"
|
||||
],
|
||||
"properties": {
|
||||
"ownerRepo": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"command": {
|
||||
"type": "string"
|
||||
},
|
||||
"commands": {
|
||||
"type": "array"
|
||||
},
|
||||
"captureContract": {
|
||||
"type": "object"
|
||||
},
|
||||
"evidencePaths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
},
|
||||
"pendingProofs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"remainingSplitBlockers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ try {
|
|||
--expect-schema gamecult.eve.plugin_abi.response.v1 `
|
||||
--expect-schema gamecult.eve.runtime_release_request.v1 `
|
||||
--expect-schema gamecult.eve.runtime_capture_request.v1 `
|
||||
--expect-schema gamecult.eve.runtime_lifecycle.v1 `
|
||||
--expect-schema gamecult.eve.runtime_split_handoff.v1 `
|
||||
--expect-schema gamecult.eve.plugin_handoff.v1 `
|
||||
--expect-schema gamecult.eve.provider_handoff.v1 `
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ foreach ($contract in @(
|
|||
"gamecult.eve.provider_advertisement.v1",
|
||||
"gamecult.eve.provider_handoff.v1",
|
||||
"gamecult.eve.runtime_capability.v1",
|
||||
"gamecult.eve.runtime_lifecycle.v1",
|
||||
"gamecult.eve.runtime_split_handoff.v1"
|
||||
)) {
|
||||
if (-not (@($handoff.contractInputs) -contains $contract)) {
|
||||
|
|
@ -124,6 +125,7 @@ if (Test-Path -LiteralPath (Join-Path $absoluteExportDirectory "index.json")) {
|
|||
"gamecult.eve.provider_advertisement.v1",
|
||||
"gamecult.eve.provider_handoff.v1",
|
||||
"gamecult.eve.runtime_capability.v1",
|
||||
"gamecult.eve.runtime_lifecycle.v1",
|
||||
"gamecult.eve.runtime_split_handoff.v1",
|
||||
"gamecult.eve.command_receipt.v1",
|
||||
"gamecult.eve.plugin.v1",
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ node $consumerScript $consumerExport `
|
|||
--expect-runtime direct2d `
|
||||
--expect-schema gamecult.eve.runtime_release_request.v1 `
|
||||
--expect-schema gamecult.eve.runtime_capture_request.v1 `
|
||||
--expect-schema gamecult.eve.runtime_lifecycle.v1 `
|
||||
--expect-schema gamecult.eve.runtime_split_handoff.v1 `
|
||||
--expect-runtime-status web:active `
|
||||
--expect-runtime-status windows-flutter:active `
|
||||
|
|
|
|||
|
|
@ -974,7 +974,7 @@ function validateRuntimeRecords(runtimes, errors) {
|
|||
for (const field of ["runtimeId", "status", "ownerRepo", "splitTarget", "captureStatus"]) {
|
||||
if (!runtime?.[field]) errors.push(`${label}:${field}:missing`);
|
||||
}
|
||||
for (const field of ["supportedFeatures", "supportedPlugins", "unsupportedPlugins", "capabilityManifestErrors", "worldSurfaceLowering"]) {
|
||||
for (const field of ["supportedFeatures", "supportedPlugins", "unsupportedPlugins", "capabilityManifestErrors", "lifecycleErrors", "worldSurfaceLowering"]) {
|
||||
if (!Array.isArray(runtime?.[field])) errors.push(`${label}:${field}:expected array`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
"schemas/gamecult.eve.provider_advertisement.v1.schema.json",
|
||||
"schemas/gamecult.eve.provider_handoff.v1.schema.json",
|
||||
"schemas/gamecult.eve.runtime_capability.v1.schema.json",
|
||||
"schemas/gamecult.eve.runtime_lifecycle.v1.schema.json",
|
||||
"schemas/gamecult.eve.runtime_split_handoff.v1.schema.json",
|
||||
"schemas/gamecult.eve.command_receipt.v1.schema.json",
|
||||
"schemas/gamecult.eve.plugin.v1.schema.json",
|
||||
|
|
@ -88,6 +89,7 @@
|
|||
"gamecult.eve.provider_advertisement.v1",
|
||||
"gamecult.eve.provider_handoff.v1",
|
||||
"gamecult.eve.runtime_capability.v1",
|
||||
"gamecult.eve.runtime_lifecycle.v1",
|
||||
"gamecult.eve.runtime_split_handoff.v1"
|
||||
],
|
||||
"forbiddenImports": [
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
"gamecult.eve.plugin_advertisement.v1": "schemas/gamecult.eve.plugin_advertisement.v1.schema.json",
|
||||
"gamecult.eve.plugin_handoff.v1": "schemas/gamecult.eve.plugin_handoff.v1.schema.json",
|
||||
"gamecult.eve.runtime_capability.v1": "schemas/gamecult.eve.runtime_capability.v1.schema.json",
|
||||
"gamecult.eve.runtime_lifecycle.v1": "schemas/gamecult.eve.runtime_lifecycle.v1.schema.json",
|
||||
"gamecult.eve.runtime_split_handoff.v1": "schemas/gamecult.eve.runtime_split_handoff.v1.schema.json",
|
||||
"gamecult.eve.runtime_release_request.v1": "schemas/gamecult.eve.runtime_release_request.v1.schema.json",
|
||||
"gamecult.eve.runtime_capture_request.v1": "schemas/gamecult.eve.runtime_capture_request.v1.schema.json",
|
||||
|
|
@ -1120,6 +1121,10 @@
|
|||
"repoRole": "runtime-incubating",
|
||||
"splitTarget": "EveFlutter",
|
||||
"graduationTrigger": "Split when Flutter has provider picker, command transport, plugin projection adapters, and its own build/release lifecycle.",
|
||||
"lifecycleManifest": {
|
||||
"schemaPath": "schemas/gamecult.eve.runtime_lifecycle.v1.schema.json",
|
||||
"manifestPath": "flutter/eve_parity/eveflutter-lifecycle.json"
|
||||
},
|
||||
"requiredFixtures": ["embedded-surface"],
|
||||
"pluginFixtures": ["sai-vn"],
|
||||
"supportedFeatures": ["embeddedDocuments"],
|
||||
|
|
@ -1171,6 +1176,10 @@
|
|||
"repoRole": "runtime-incubating",
|
||||
"splitTarget": "EveFlutter",
|
||||
"graduationTrigger": "Split with EveFlutter when Linux capture and runner health become runtime-owned.",
|
||||
"lifecycleManifest": {
|
||||
"schemaPath": "schemas/gamecult.eve.runtime_lifecycle.v1.schema.json",
|
||||
"manifestPath": "flutter/eve_parity/eveflutter-lifecycle.json"
|
||||
},
|
||||
"requiredFixtures": ["embedded-surface"],
|
||||
"pluginFixtures": ["sai-vn"],
|
||||
"supportedFeatures": ["embeddedDocuments"],
|
||||
|
|
@ -1259,6 +1268,10 @@
|
|||
"repoRole": "runtime-incubating",
|
||||
"splitTarget": "EveFlutter",
|
||||
"graduationTrigger": "Split with EveFlutter when Android APK smoke, provider discovery, command transport, and plugin projection adapters are runtime-owned.",
|
||||
"lifecycleManifest": {
|
||||
"schemaPath": "schemas/gamecult.eve.runtime_lifecycle.v1.schema.json",
|
||||
"manifestPath": "flutter/eve_parity/eveflutter-lifecycle.json"
|
||||
},
|
||||
"requiredFixtures": ["embedded-surface"],
|
||||
"pluginFixtures": ["sai-vn"],
|
||||
"supportedFeatures": ["embeddedDocuments"],
|
||||
|
|
|
|||
|
|
@ -310,6 +310,9 @@ async function evaluateRuntime(runtime, fixtureResults) {
|
|||
const commandTransportSmokeErrors = await validateRuntimeCommandTransportSmoke(runtime);
|
||||
const capabilityManifestErrors = await validateRuntimeCapabilityManifest(runtime);
|
||||
const capabilityManifestDocument = await readRuntimeCapabilityManifestDocument(runtime);
|
||||
const lifecycleManifestDocument = await readRuntimeLifecycleManifestDocument(runtime);
|
||||
const lifecycle = runtime.lifecycle || capabilityManifestDocument?.lifecycle || readLifecycleStages(lifecycleManifestDocument);
|
||||
const lifecycleErrors = await validateRuntimeLifecycle(runtime, lifecycle, lifecycleManifestDocument);
|
||||
const splitHandoffPath = await readRuntimeSplitHandoffPath(runtime);
|
||||
const splitHandoffErrors = await validateRuntimeSplitHandoff(runtime, splitHandoffPath);
|
||||
const localProviderCatalogErrors = await validateRuntimeLocalProviderCatalog(runtime);
|
||||
|
|
@ -323,6 +326,7 @@ async function evaluateRuntime(runtime, fixtureResults) {
|
|||
if (runtime.kind === "active" && missingRequiredFeatures.length) status = "missing-required-feature";
|
||||
if (runtime.kind === "active" && commandTransportSmokeErrors.length) status = "missing-command-transport-smoke";
|
||||
if (runtime.kind === "active" && capabilityManifestErrors.length) status = "invalid-runtime-capability";
|
||||
if (runtime.kind === "active" && lifecycleErrors.length) status = "invalid-runtime-lifecycle";
|
||||
if (runtime.kind === "active" && splitHandoffErrors.length) status = "invalid-runtime-split-handoff";
|
||||
if (runtime.kind === "active" && localProviderCatalogErrors.length) status = "invalid-local-provider-catalog";
|
||||
if (runtime.kind === "active" && missingIncubationFields.length) status = "missing-incubation-metadata";
|
||||
|
|
@ -361,11 +365,13 @@ async function evaluateRuntime(runtime, fixtureResults) {
|
|||
commandTransportSmokeErrors,
|
||||
capabilityManifest: runtime.capabilityManifest || null,
|
||||
capabilityManifestErrors,
|
||||
lifecycleManifest: runtime.lifecycleManifest || null,
|
||||
lifecycleErrors,
|
||||
splitHandoffPath,
|
||||
splitHandoffErrors,
|
||||
localProviderCatalog: runtime.localProviderCatalog || null,
|
||||
localProviderCatalogErrors,
|
||||
lifecycle: runtime.lifecycle || capabilityManifestDocument?.lifecycle || null,
|
||||
lifecycle,
|
||||
ownerRepo: runtime.ownerRepo || "",
|
||||
repoRole: runtime.repoRole || "",
|
||||
graduationTrigger: runtime.graduationTrigger || "",
|
||||
|
|
@ -393,6 +399,82 @@ async function readRuntimeCapabilityManifestDocument(runtime) {
|
|||
}
|
||||
}
|
||||
|
||||
async function readRuntimeLifecycleManifestDocument(runtime) {
|
||||
const lifecyclePath = runtime.lifecycleManifest?.manifestPath;
|
||||
if (!lifecyclePath) return null;
|
||||
try {
|
||||
return await readJsonDocument(lifecyclePath);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function readLifecycleStages(lifecycleDocument) {
|
||||
if (!lifecycleDocument) return null;
|
||||
return {
|
||||
release: lifecycleDocument.release,
|
||||
test: lifecycleDocument.test,
|
||||
capture: lifecycleDocument.capture,
|
||||
};
|
||||
}
|
||||
|
||||
async function validateRuntimeLifecycle(runtime, lifecycle, lifecycleDocument) {
|
||||
if (!lifecycle && !runtime.lifecycleManifest) return [];
|
||||
|
||||
const schemaPath = runtime.lifecycleManifest?.schemaPath || manifest.schemas?.["gamecult.eve.runtime_lifecycle.v1"];
|
||||
const errors = [];
|
||||
if (runtime.lifecycleManifest?.manifestPath) {
|
||||
errors.push(...await validateJsonDocument(schemaPath, runtime.lifecycleManifest.manifestPath, {
|
||||
schema: "gamecult.eve.runtime_lifecycle.v1",
|
||||
}));
|
||||
if (!lifecycleDocument) {
|
||||
errors.push(`${runtime.lifecycleManifest.manifestPath}:unreadable`);
|
||||
} else if (!Array.isArray(lifecycleDocument.runtimes) || !lifecycleDocument.runtimes.includes(runtime.id)) {
|
||||
errors.push(`${runtime.lifecycleManifest.manifestPath}:runtimes:${runtime.id}:missing`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lifecycle) {
|
||||
errors.push("lifecycle:missing");
|
||||
return errors;
|
||||
}
|
||||
|
||||
const ownerRepo = lifecycleDocument?.ownerRepo
|
||||
|| lifecycle.release?.ownerRepo
|
||||
|| lifecycle.test?.ownerRepo
|
||||
|| lifecycle.capture?.ownerRepo
|
||||
|| runtime.splitTarget
|
||||
|| runtime.ownerRepo
|
||||
|| "";
|
||||
const currentHostRepo = lifecycleDocument?.currentHostRepo || runtime.ownerRepo || "Eve";
|
||||
const lifecycleEnvelope = {
|
||||
schema: "gamecult.eve.runtime_lifecycle.v1",
|
||||
splitTarget: lifecycleDocument?.splitTarget || runtime.splitTarget || runtime.id,
|
||||
ownerRepo,
|
||||
currentHostRepo,
|
||||
status: lifecycleDocument?.status || runtime.status || "",
|
||||
runtimes: lifecycleDocument?.runtimes || [runtime.id],
|
||||
release: lifecycle.release,
|
||||
test: lifecycle.test,
|
||||
capture: lifecycle.capture,
|
||||
remainingSplitBlockers: lifecycleDocument?.remainingSplitBlockers || [],
|
||||
};
|
||||
|
||||
const schemaErrors = await validateJsonDocumentAgainstSchemaPath(schemaPath, lifecycleEnvelope, `runtimeLifecycle:${runtime.id}`);
|
||||
errors.push(...schemaErrors);
|
||||
|
||||
for (const stage of ["release", "test", "capture"]) {
|
||||
const stageDocument = lifecycle[stage];
|
||||
for (const evidencePath of stageDocument?.evidencePaths || []) {
|
||||
if (!existsSync(path.join(repoRoot, evidencePath))) {
|
||||
errors.push(`lifecycle.${stage}.evidence:${evidencePath}:missing`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
async function validateRuntimeLocalProviderCatalog(runtime) {
|
||||
const catalogConfig = runtime.localProviderCatalog;
|
||||
if (!catalogConfig) return [];
|
||||
|
|
@ -1116,6 +1198,23 @@ async function validateJsonDocument(schemaPath, documentPath, expected = {}) {
|
|||
return errors;
|
||||
}
|
||||
|
||||
async function validateJsonDocumentAgainstSchemaPath(schemaPath, document, label) {
|
||||
const errors = [];
|
||||
if (!schemaPath) return ["schemaPath:missing"];
|
||||
|
||||
const absoluteSchemaPath = path.join(repoRoot, schemaPath);
|
||||
if (!existsSync(absoluteSchemaPath)) return [`${schemaPath}:missing`];
|
||||
|
||||
try {
|
||||
const schema = JSON.parse(await readFile(absoluteSchemaPath, "utf8"));
|
||||
errors.push(...validateSchemaSubset(schema, document, label));
|
||||
} catch (error) {
|
||||
errors.push(`${label}:invalid-json:${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
function extractProviderSchemaIds(schemas) {
|
||||
return schemas.map(schema => {
|
||||
if (typeof schema === "string") return schema;
|
||||
|
|
@ -1783,15 +1882,18 @@ function buildConformanceExport(report) {
|
|||
requiredFixtures: runtime.requiredFixtures,
|
||||
pluginFixtures: runtime.pluginFixtures,
|
||||
capabilityManifestPath: runtime.capabilityManifest?.manifestPath || "",
|
||||
lifecycleManifestPath: runtime.lifecycleManifest?.manifestPath || "",
|
||||
commandTransportSchema: runtimeCommandTransportSchema(runtime),
|
||||
captureStatus: runtime.capture?.status || "",
|
||||
lifecycle: runtime.lifecycle,
|
||||
missingEvidence: [
|
||||
lifecycle: runtime.lifecycle,
|
||||
lifecycleErrors: runtime.lifecycleErrors || [],
|
||||
missingEvidence: [
|
||||
...runtime.missingPaths,
|
||||
...runtime.missingRequiredFixtures.map(id => `fixture:${id}`),
|
||||
...runtime.missingRequiredFeatures.map(id => `feature:${id}`),
|
||||
...runtime.commandTransportSmokeErrors.map(id => `command-smoke:${id}`),
|
||||
...runtime.capabilityManifestErrors.map(id => `runtime-capability:${id}`),
|
||||
...runtime.lifecycleErrors.map(id => `runtime-lifecycle:${id}`),
|
||||
...runtime.localProviderCatalogErrors.map(id => `local-provider-catalog:${id}`),
|
||||
],
|
||||
}))
|
||||
|
|
@ -1874,6 +1976,8 @@ function buildConformanceExport(report) {
|
|||
unsupportedPlugins: runtime.unsupportedPlugins,
|
||||
capabilityManifestPath: runtime.capabilityManifest?.manifestPath || "",
|
||||
capabilityManifestErrors: runtime.capabilityManifestErrors || [],
|
||||
lifecycleManifestPath: runtime.lifecycleManifest?.manifestPath || "",
|
||||
lifecycleErrors: runtime.lifecycleErrors || [],
|
||||
splitHandoffPath: runtime.splitHandoffPath || "",
|
||||
splitHandoffErrors: runtime.splitHandoffErrors || [],
|
||||
splitHandoffExportPath: makeHandoffExportPath("runtime", runtime.id, runtime.splitHandoffPath || ""),
|
||||
|
|
@ -2049,6 +2153,7 @@ function collectCapabilityGaps(report) {
|
|||
...(runtime.missingRequiredFeatures || []).map(id => `feature:${id}`),
|
||||
...(runtime.commandTransportSmokeErrors || []).map(id => `command-smoke:${id}`),
|
||||
...(runtime.capabilityManifestErrors || []).map(id => `runtime-capability:${id}`),
|
||||
...(runtime.lifecycleErrors || []).map(id => `runtime-lifecycle:${id}`),
|
||||
...(runtime.splitHandoffErrors || []).map(id => `runtime-split-handoff:${id}`),
|
||||
...(runtime.localProviderCatalogErrors || []).map(id => `local-provider-catalog:${id}`),
|
||||
...(runtime.pluginCapabilityGaps || []).map(id => `plugin-capability:${id}`),
|
||||
|
|
|
|||
Loading…
Reference in a new issue