Attach runtime witnesses to conformance exports
This commit is contained in:
parent
7a9493b67d
commit
a3b1123186
7 changed files with 267 additions and 8 deletions
|
|
@ -285,9 +285,7 @@ Exit criteria:
|
|||
|
||||
## Active Work Queue
|
||||
|
||||
1. Turn the Unity live witness into a conformance-pack attachment with cold and
|
||||
warm asset-transfer timings, command receipts, and screenshot metrics.
|
||||
2. Replace Aetheria's specialized browser embedded-document methods with a
|
||||
1. Replace Aetheria's specialized browser embedded-document methods with a
|
||||
generic CultMesh document handle once the field/plugin document contract is
|
||||
explicit; do not move Aetheria gravity or object schemas into Eve.
|
||||
|
||||
|
|
@ -336,6 +334,16 @@ Recently cut:
|
|||
witness requires the Eve-owned world scene, provider entity markers, and one
|
||||
controlled marker in the rendered DOM, so surrounding HUD text cannot stand
|
||||
in for interactive-world lowering proof.
|
||||
- Eve now defines `gamecult.eve.runtime_witness.v1`, and EveUnity's live
|
||||
Aetheria runner emits owner-repo witnesses with cache mode, wall/test timing,
|
||||
provider advertisement and asset assertions, movement distance, initial and
|
||||
final surface versions, terminal movement/target/action receipts, screenshot
|
||||
dimensions/hash/size, and hashed test results. The conformance attachment
|
||||
tool validates the schema, copies declared artifacts into export-relative
|
||||
paths, and indexes the witness without retaining EveUnity source paths.
|
||||
Export consumption passed for both `eveunity.aetheria.game.warm` (68.27 s
|
||||
wall, 7.72 s test) and `eveunity.aetheria.game.cold` (138.90 s wall,
|
||||
111.52 s test), including all three reconciled command receipts.
|
||||
|
||||
- The clean EveUnity PlayMode client now consumes Aetheria's independently
|
||||
running daemon without importing Aetheria code. Aetheria builds its authored
|
||||
|
|
@ -1382,10 +1390,9 @@ Evidence on 2026-07-10:
|
|||
runtime surface serializer. Core surface wire fields use CultMesh transport
|
||||
records; provider-private surface documents remain separate authority.
|
||||
|
||||
Remaining before this gate is complete:
|
||||
|
||||
- attach both PNGs, cold/warm transfer timings, and receipt/version evidence to the exported conformance
|
||||
pack rather than leaving them only in EveUnity's local artifacts.
|
||||
This gate is complete: cold and warm runtime-owned witnesses attach their PNG,
|
||||
test result, receipt, version, movement, timing, and screenshot evidence to a
|
||||
consumer-verifiable conformance export.
|
||||
|
||||
## Stop Conditions
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,26 @@
|
|||
"incubationPolicy": {
|
||||
"type": "string"
|
||||
},
|
||||
"runtimeWitnesses": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["witnessId", "runtimeId", "runtimeOwnerRepo", "providerId", "surfaceId", "projectionKind", "status", "cacheState", "witnessExportPath", "artifactCount"],
|
||||
"properties": {
|
||||
"witnessId": { "type": "string", "minLength": 1 },
|
||||
"runtimeId": { "type": "string", "minLength": 1 },
|
||||
"runtimeOwnerRepo": { "type": "string", "minLength": 1 },
|
||||
"providerId": { "type": "string", "minLength": 1 },
|
||||
"surfaceId": { "type": "string", "minLength": 1 },
|
||||
"projectionKind": { "type": "string", "minLength": 1 },
|
||||
"status": { "enum": ["pass", "fail"] },
|
||||
"cacheState": { "enum": ["cold", "warm"] },
|
||||
"witnessExportPath": { "type": "string", "minLength": 1 },
|
||||
"artifactCount": { "type": "integer", "minimum": 1 }
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"packs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
|
|||
93
schemas/gamecult.eve.runtime_witness.v1.schema.json
Normal file
93
schemas/gamecult.eve.runtime_witness.v1.schema.json
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "gamecult.eve.runtime_witness.v1",
|
||||
"title": "Eve Runtime Witness",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"schema", "witnessId", "runtimeId", "runtimeOwnerRepo", "providerId",
|
||||
"surfaceId", "projectionKind", "status", "generatedAtUtc", "execution",
|
||||
"assertions", "receipts", "screenshotMetrics", "artifacts", "authority"
|
||||
],
|
||||
"properties": {
|
||||
"schema": { "const": "gamecult.eve.runtime_witness.v1" },
|
||||
"witnessId": { "type": "string", "minLength": 1 },
|
||||
"runtimeId": { "type": "string", "minLength": 1 },
|
||||
"runtimeOwnerRepo": { "type": "string", "minLength": 1 },
|
||||
"providerId": { "type": "string", "minLength": 1 },
|
||||
"surfaceId": { "type": "string", "minLength": 1 },
|
||||
"projectionKind": { "type": "string", "minLength": 1 },
|
||||
"status": { "enum": ["pass", "fail"] },
|
||||
"generatedAtUtc": { "type": "string", "minLength": 1 },
|
||||
"execution": {
|
||||
"type": "object",
|
||||
"required": ["cacheState", "durationMs", "testDurationMs"],
|
||||
"properties": {
|
||||
"cacheState": { "enum": ["cold", "warm"] },
|
||||
"durationMs": { "type": "number", "minimum": 0 },
|
||||
"testDurationMs": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"assertions": {
|
||||
"type": "object",
|
||||
"required": ["providerAdvertisement", "providerAssets", "movement", "targeting", "action", "initialVersion", "finalVersion"],
|
||||
"properties": {
|
||||
"providerAdvertisement": { "type": "boolean" },
|
||||
"providerAssets": { "type": "boolean" },
|
||||
"movement": { "type": "boolean" },
|
||||
"targeting": { "type": "boolean" },
|
||||
"action": { "type": "boolean" },
|
||||
"initialVersion": { "type": "number", "minimum": 0 },
|
||||
"finalVersion": { "type": "number", "minimum": 0 },
|
||||
"movementDistance": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"receipts": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["commandKind", "commandId", "state", "sourceVersion"],
|
||||
"properties": {
|
||||
"commandKind": { "type": "string", "minLength": 1 },
|
||||
"commandId": { "type": "string", "minLength": 1 },
|
||||
"state": { "enum": ["accepted", "reconciled"] },
|
||||
"sourceVersion": { "type": "number", "minimum": 0 }
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"screenshotMetrics": {
|
||||
"type": "object",
|
||||
"required": ["width", "height", "encodedSizeBytes", "sha256"],
|
||||
"properties": {
|
||||
"width": { "type": "integer", "minimum": 1 },
|
||||
"height": { "type": "integer", "minimum": 1 },
|
||||
"encodedSizeBytes": { "type": "integer", "minimum": 1 },
|
||||
"sha256": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$" }
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["kind", "path", "sha256", "sizeBytes"],
|
||||
"properties": {
|
||||
"kind": { "type": "string", "minLength": 1 },
|
||||
"path": { "type": "string", "minLength": 1 },
|
||||
"sha256": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$" },
|
||||
"sizeBytes": { "type": "integer", "minimum": 1 },
|
||||
"width": { "type": "integer", "minimum": 1 },
|
||||
"height": { "type": "integer", "minimum": 1 },
|
||||
"exportPath": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"authority": { "type": "string", "minLength": 1 }
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
78
tools/conformance/attach-runtime-witness.mjs
Normal file
78
tools/conformance/attach-runtime-witness.mjs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { validateSchemaSubset } from "../../runtimes/incubating/test-support/schema-subset.mjs";
|
||||
|
||||
const [witnessArgument, exportArgument] = process.argv.slice(2);
|
||||
if (!witnessArgument || !exportArgument) {
|
||||
console.error("Usage: node tools/conformance/attach-runtime-witness.mjs <runtime-witness.json> <conformance-export-directory>");
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const witnessPath = path.resolve(witnessArgument);
|
||||
const exportDirectory = path.resolve(exportArgument);
|
||||
const indexPath = path.join(exportDirectory, "index.json");
|
||||
const witness = parseJson(await readFile(witnessPath, "utf8"));
|
||||
validateWitness(witness);
|
||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const witnessSchema = parseJson(await readFile(path.join(repoRoot, "schemas/gamecult.eve.runtime_witness.v1.schema.json"), "utf8"));
|
||||
const schemaErrors = validateSchemaSubset(witnessSchema, witness);
|
||||
if (schemaErrors.length) throw new Error(`Runtime witness schema errors: ${schemaErrors.join("; ")}`);
|
||||
|
||||
const attachmentRoot = path.join(exportDirectory, "attachments", "runtime", safeSegment(witness.witnessId));
|
||||
await mkdir(attachmentRoot, { recursive: true });
|
||||
const artifacts = [];
|
||||
for (const artifact of witness.artifacts) {
|
||||
const sourcePath = path.resolve(path.dirname(witnessPath), artifact.path);
|
||||
const fileName = path.basename(sourcePath);
|
||||
const destinationPath = path.join(attachmentRoot, fileName);
|
||||
await copyFile(sourcePath, destinationPath);
|
||||
artifacts.push({
|
||||
...artifact,
|
||||
exportPath: slash(path.relative(exportDirectory, destinationPath)),
|
||||
});
|
||||
}
|
||||
|
||||
const exportedWitness = { ...witness, artifacts };
|
||||
const exportedWitnessPath = path.join(attachmentRoot, "witness.json");
|
||||
await writeFile(exportedWitnessPath, `${JSON.stringify(exportedWitness, null, 2)}\n`);
|
||||
|
||||
const index = parseJson(await readFile(indexPath, "utf8"));
|
||||
const record = {
|
||||
witnessId: witness.witnessId,
|
||||
runtimeId: witness.runtimeId,
|
||||
runtimeOwnerRepo: witness.runtimeOwnerRepo,
|
||||
providerId: witness.providerId,
|
||||
surfaceId: witness.surfaceId,
|
||||
projectionKind: witness.projectionKind,
|
||||
status: witness.status,
|
||||
cacheState: witness.execution.cacheState,
|
||||
witnessExportPath: slash(path.relative(exportDirectory, exportedWitnessPath)),
|
||||
artifactCount: artifacts.length,
|
||||
};
|
||||
index.runtimeWitnesses = [
|
||||
...(Array.isArray(index.runtimeWitnesses) ? index.runtimeWitnesses : []).filter(candidate => candidate.witnessId !== record.witnessId),
|
||||
record,
|
||||
].sort((left, right) => left.witnessId.localeCompare(right.witnessId));
|
||||
await writeFile(indexPath, `${JSON.stringify(index, null, 2)}\n`);
|
||||
console.log(exportedWitnessPath);
|
||||
|
||||
function validateWitness(value) {
|
||||
for (const field of ["witnessId", "runtimeId", "runtimeOwnerRepo", "providerId", "surfaceId", "projectionKind", "status", "generatedAtUtc", "authority"]) {
|
||||
if (!value?.[field]) throw new Error(`Runtime witness missing ${field}.`);
|
||||
}
|
||||
if (value.schema !== "gamecult.eve.runtime_witness.v1") throw new Error(`Unexpected runtime witness schema: ${value.schema || ""}`);
|
||||
if (!value.execution?.cacheState || !Number.isFinite(value.execution?.durationMs)) throw new Error("Runtime witness execution is incomplete.");
|
||||
if (!value.assertions || typeof value.assertions !== "object") throw new Error("Runtime witness assertions are missing.");
|
||||
if (!Array.isArray(value.receipts) || !value.receipts.length) throw new Error("Runtime witness receipts are missing.");
|
||||
if (!Array.isArray(value.artifacts) || !value.artifacts.length) throw new Error("Runtime witness artifacts are missing.");
|
||||
for (const artifact of value.artifacts) {
|
||||
if (!artifact.path || !/^[a-f0-9]{64}$/i.test(artifact.sha256 || "") || !(artifact.sizeBytes > 0)) {
|
||||
throw new Error(`Runtime witness artifact is invalid: ${artifact.path || "unknown"}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function safeSegment(value) { return String(value).replace(/[^a-zA-Z0-9._-]+/g, "-"); }
|
||||
function slash(value) { return value.replaceAll("\\", "/"); }
|
||||
function parseJson(value) { return JSON.parse(value.replace(/^\uFEFF/, "")); }
|
||||
|
|
@ -59,6 +59,7 @@ if (!exportDirectory) {
|
|||
" --expect-runtime-command-schema <runtimeId:schema>",
|
||||
" --expect-runtime-capture-status <runtimeId:status>",
|
||||
" --expect-runtime-capture-artifact <runtimeId:kind:schema:providerId:surfaceId>",
|
||||
" --expect-runtime-witness <runtimeId:providerId:surfaceId:cacheState:status>",
|
||||
" --expect-runtime-lifecycle-status <runtimeId:stage:status>",
|
||||
" --expect-runtime-lifecycle-pending <runtimeId:stage:pending-proof-substring>",
|
||||
" --expect-runtime-lifecycle-field <runtimeId:stage:field.path:value>",
|
||||
|
|
@ -154,6 +155,7 @@ function validateIndex(index, directory, expectations, errors) {
|
|||
const commandBoundaryCoverage = Array.isArray(index.commandBoundaryCoverage) ? index.commandBoundaryCoverage : [];
|
||||
const screenshotComparisonMetrics = Array.isArray(index.screenshotComparisonMetrics) ? index.screenshotComparisonMetrics : [];
|
||||
const runtimeCaptureProbeCoverage = Array.isArray(index.runtimeCaptureProbeCoverage) ? index.runtimeCaptureProbeCoverage : [];
|
||||
const runtimeWitnesses = Array.isArray(index.runtimeWitnesses) ? index.runtimeWitnesses : [];
|
||||
const splitTargetBlockers = Array.isArray(index.splitTargetBlockers) ? index.splitTargetBlockers : [];
|
||||
const splitHandoffMoveCoverage = Array.isArray(index.splitHandoffMoveCoverage) ? index.splitHandoffMoveCoverage : [];
|
||||
const pluginHandoffMoveCoverage = Array.isArray(index.pluginHandoffMoveCoverage) ? index.pluginHandoffMoveCoverage : [];
|
||||
|
|
@ -190,6 +192,7 @@ function validateIndex(index, directory, expectations, errors) {
|
|||
validateCommandBoundaryCoverage(index.commandBoundaryCoverage, errors);
|
||||
validateScreenshotComparisonMetrics(index.screenshotComparisonMetrics, errors);
|
||||
validateRuntimeCaptureProbeCoverage(index.runtimeCaptureProbeCoverage, errors);
|
||||
validateRuntimeWitnesses(runtimeWitnesses, directory, errors);
|
||||
validateWorldSurfaceLoweringGaps(index.worldSurfaceLoweringGaps, errors);
|
||||
for (const expectedGap of expectations.capabilityGaps) {
|
||||
if (!capabilityGaps.some(gap => capabilityGapText(gap).includes(expectedGap))) {
|
||||
|
|
@ -211,6 +214,20 @@ function validateIndex(index, directory, expectations, errors) {
|
|||
errors.push(`runtimePluginProjectionCoverage:${expectation.runtimeId}:${expectation.pluginId}:runtimeOwnerRepo:expected ${expectation.ownerRepo} got ${record.runtimeOwnerRepo || ""}`);
|
||||
}
|
||||
}
|
||||
for (const expectation of expectations.runtimeWitnesses) {
|
||||
const witness = runtimeWitnesses.find(candidate =>
|
||||
candidate.runtimeId === expectation.runtimeId &&
|
||||
candidate.providerId === expectation.providerId &&
|
||||
candidate.surfaceId === expectation.surfaceId &&
|
||||
candidate.cacheState === expectation.cacheState);
|
||||
if (!witness) {
|
||||
errors.push(`runtimeWitnesses:${expectation.runtimeId}:${expectation.providerId}:${expectation.surfaceId}:${expectation.cacheState}:missing`);
|
||||
continue;
|
||||
}
|
||||
if (witness.status !== expectation.status) {
|
||||
errors.push(`runtimeWitnesses:${witness.witnessId}:status:expected ${expectation.status} got ${witness.status || ""}`);
|
||||
}
|
||||
}
|
||||
for (const expectation of expectations.providerRuntimePluginProjectionCoverage) {
|
||||
const record = providerRuntimePluginProjectionCoverage.find(candidate =>
|
||||
candidate.providerId === expectation.providerId &&
|
||||
|
|
@ -1239,6 +1256,28 @@ function validateRuntimeRecords(runtimes, errors) {
|
|||
}
|
||||
}
|
||||
|
||||
function validateRuntimeWitnesses(witnesses, directory, errors) {
|
||||
if (!Array.isArray(witnesses)) return;
|
||||
for (const [index, witness] of witnesses.entries()) {
|
||||
for (const field of ["witnessId", "runtimeId", "runtimeOwnerRepo", "providerId", "surfaceId", "projectionKind", "status", "cacheState", "witnessExportPath", "artifactCount"]) {
|
||||
if (witness?.[field] === undefined || witness?.[field] === "") errors.push(`runtimeWitnesses:${index}:${field}:missing`);
|
||||
}
|
||||
const witnessPath = witness?.witnessExportPath ? path.join(directory, witness.witnessExportPath) : "";
|
||||
if (!witnessPath || !existsSync(witnessPath)) {
|
||||
errors.push(`runtimeWitnesses:${index}:witnessExportPath:missing`);
|
||||
continue;
|
||||
}
|
||||
const document = JSON.parse(readFileSyncUtf8(witnessPath));
|
||||
if (document.schema !== "gamecult.eve.runtime_witness.v1") errors.push(`runtimeWitnesses:${index}:schema:unexpected`);
|
||||
if ((document.artifacts || []).length !== witness.artifactCount) errors.push(`runtimeWitnesses:${index}:artifactCount:mismatch`);
|
||||
for (const artifact of document.artifacts || []) {
|
||||
if (!artifact.exportPath || !existsSync(path.join(directory, artifact.exportPath))) {
|
||||
errors.push(`runtimeWitnesses:${index}:artifact:${artifact.kind || "unknown"}:missing`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateSplitTargetRecords(splitTargets, errors) {
|
||||
for (const target of splitTargets) {
|
||||
const label = `splitTargets:${target.id || "unknown"}`;
|
||||
|
|
@ -1325,6 +1364,7 @@ function parseArguments(args) {
|
|||
runtimeCommandSchemas: [],
|
||||
runtimeCaptureStatuses: [],
|
||||
runtimeCaptureArtifacts: [],
|
||||
runtimeWitnesses: [],
|
||||
runtimeLifecycleStatuses: [],
|
||||
runtimeLifecyclePendingProofs: [],
|
||||
runtimeLifecycleFields: [],
|
||||
|
|
@ -1387,6 +1427,7 @@ function parseArguments(args) {
|
|||
["--expect-runtime-command-schema", expectations.runtimeCommandSchemas],
|
||||
["--expect-runtime-capture-status", expectations.runtimeCaptureStatuses],
|
||||
["--expect-runtime-capture-artifact", expectations.runtimeCaptureArtifacts],
|
||||
["--expect-runtime-witness", expectations.runtimeWitnesses],
|
||||
["--expect-runtime-lifecycle-status", expectations.runtimeLifecycleStatuses],
|
||||
["--expect-runtime-lifecycle-pending", expectations.runtimeLifecyclePendingProofs],
|
||||
["--expect-runtime-lifecycle-field", expectations.runtimeLifecycleFields],
|
||||
|
|
@ -1485,6 +1526,8 @@ function parseArguments(args) {
|
|||
target.push(parseRuntimeExpectation(value, "status"));
|
||||
} else if (option === "--expect-runtime-capture-artifact") {
|
||||
target.push(parseRuntimeCaptureArtifactExpectation(value));
|
||||
} else if (option === "--expect-runtime-witness") {
|
||||
target.push(parseRuntimeWitnessExpectation(value));
|
||||
} else if (option === "--expect-runtime-lifecycle-status") {
|
||||
target.push(parseRuntimeLifecycleExpectation(value, "status"));
|
||||
} else if (option === "--expect-runtime-lifecycle-pending") {
|
||||
|
|
@ -1910,6 +1953,21 @@ function parseRuntimeExpectation(value, field) {
|
|||
};
|
||||
}
|
||||
|
||||
function parseRuntimeWitnessExpectation(value) {
|
||||
const parts = value.split(":");
|
||||
if (parts.length !== 5 || parts.some(part => !part)) {
|
||||
console.error(`Expected runtime witness in <runtimeId:providerId:surfaceId:cacheState:status> form, got: ${value}`);
|
||||
process.exit(2);
|
||||
}
|
||||
return {
|
||||
runtimeId: parts[0],
|
||||
providerId: parts[1],
|
||||
surfaceId: parts[2],
|
||||
cacheState: parts[3],
|
||||
status: parts[4],
|
||||
};
|
||||
}
|
||||
|
||||
function parseRuntimeWorldTargetExpectation(value) {
|
||||
const separator = value.indexOf(":");
|
||||
if (separator <= 0 || separator === value.length - 1) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@
|
|||
"schemas/gamecult.eve.plugin_abi.request.v1.schema.json",
|
||||
"schemas/gamecult.eve.plugin_abi.response.v1.schema.json",
|
||||
"schemas/gamecult.eve.runtime_release_request.v1.schema.json",
|
||||
"schemas/gamecult.eve.runtime_capture_request.v1.schema.json"
|
||||
"schemas/gamecult.eve.runtime_capture_request.v1.schema.json",
|
||||
"schemas/gamecult.eve.runtime_witness.v1.schema.json"
|
||||
],
|
||||
"replacementProof": "EveConformance publishes the schema catalog and copied schema documents needed by conformance, plugin, provider, and runtime consumers."
|
||||
},
|
||||
|
|
@ -92,6 +93,7 @@
|
|||
"gamecult.eve.plugin_abi.response.v1",
|
||||
"gamecult.eve.runtime_release_request.v1",
|
||||
"gamecult.eve.runtime_capture_request.v1",
|
||||
"gamecult.eve.runtime_witness.v1",
|
||||
"gamecult.eve.provider_advertisement.v1",
|
||||
"gamecult.eve.provider_handoff.v1",
|
||||
"gamecult.eve.electron_shell_projection.v1",
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
"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",
|
||||
"gamecult.eve.runtime_witness.v1": "schemas/gamecult.eve.runtime_witness.v1.schema.json",
|
||||
"gamecult.eve.web_layout_probe.v1": "schemas/gamecult.eve.web_layout_probe.v1.schema.json",
|
||||
"gamecult.eve.provider_scenario.v1": "schemas/gamecult.eve.provider_scenario.v1.schema.json",
|
||||
"gamecult.eve.provider_advertisement.v1": "schemas/gamecult.eve.provider_advertisement.v1.schema.json",
|
||||
|
|
|
|||
Loading…
Reference in a new issue