From 718e9f773b95e38abfcb41dddd9d256f213a71d6 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 9 Jul 2026 17:24:28 +0100 Subject: [PATCH] Select runtime capture surfaces explicitly --- docs/eve-migration-roadmap.md | 5 +++ docs/parity-testing-harness.md | 5 +++ .../eve-runtime-capability.json | 5 +++ .../eve-electron/eve-runtime-capability.json | 5 +++ .../eve-tui/eve-runtime-capability.json | 5 +++ ...ntime-owner-conformance-consumer-smoke.ps1 | 8 ++++- .../eveelectron-capture-artifact.mjs | 3 ++ .../eveelectron-capture-contract.mjs | 19 ++++++++++-- .../eveelectron-capture-contract.test.mjs | 19 ++++++++++++ tools/evetui/evetui-capture-artifact.mjs | 3 ++ tools/evetui/evetui-capture-contract.mjs | 19 ++++++++++-- tools/evetui/evetui-capture-contract.test.mjs | 19 ++++++++++++ tools/eveunity/eveunity-capture-contract.mjs | 19 ++++++++++-- .../eveunity-capture-contract.test.mjs | 31 +++++++++++++++++++ .../eveunity-scene-capture-artifact.mjs | 3 ++ .../eveunity-uitoolkit-capture-artifact.mjs | 3 ++ tools/parity/parity-manifest.json | 5 +++ 17 files changed, 166 insertions(+), 10 deletions(-) diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index 61d2784..3053433 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -709,6 +709,11 @@ Recently cut: Aetheria `runtime.captureArtifacts[]` for `aetheria.daemon.game`. That makes the provider-side proof consume generic lowering clients instead of stopping at advertised target coverage. +- Runtime capture requests now select a declared provider surface, not only a + provider id. Unity UI Toolkit, Electron shell, and TUI declare + `aetheria.daemon.editor` as an additional capture surface, while Unity Scene + rejects the editor surface because Aetheria does not advertise `unity-scene` + for editor lowering. This keeps game/editor capture authority explicit. - Conformance export now carries first-class `capabilityGaps[]` records derived from plugin errors, provider advertisement/scenario errors, runtime missing evidence, declared unsupported plugin projection, capture gaps, and split diff --git a/docs/parity-testing-harness.md b/docs/parity-testing-harness.md index b051f81..10c6716 100644 --- a/docs/parity-testing-harness.md +++ b/docs/parity-testing-harness.md @@ -296,6 +296,11 @@ Electron shell, and TUI, so provider consumption proves real runtime artifacts rather than only advertised lowering targets. Generated copies remain under Eve's `artifacts/aetheria-conformance-consumer-smoke` so the provider worktree does not become dirty merely by proving the boundary. +Runtime capture request builders select a declared provider surface by id when +requested. Unity UI Toolkit, Electron shell, and TUI declare +`aetheria.daemon.editor` as an additional capture surface; Unity Scene does not, +because the editor advertisement does not include the `unity-scene` lowering +target. Plugin owner handoff smoke: diff --git a/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json b/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json index 3118155..b419a6c 100644 --- a/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json +++ b/packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json @@ -205,6 +205,11 @@ "providerId": "eve.world-smoke", "surfaceId": "eve.world-smoke.surface", "purpose": "Generic non-product interactive-world capture control." + }, + { + "providerId": "aetheria", + "surfaceId": "aetheria.daemon.editor", + "purpose": "Aetheria interactive-world-editor capture control." } ], "authority": "Capture observes runtime projection only; provider state, command acceptance, and receipts stay provider-owned.", diff --git a/runtimes/incubating/eve-electron/eve-runtime-capability.json b/runtimes/incubating/eve-electron/eve-runtime-capability.json index d3b83f7..e93038a 100644 --- a/runtimes/incubating/eve-electron/eve-runtime-capability.json +++ b/runtimes/incubating/eve-electron/eve-runtime-capability.json @@ -149,6 +149,11 @@ "providerId": "eve.world-smoke", "surfaceId": "eve.world-smoke.surface", "purpose": "Generic non-product interactive-world capture control." + }, + { + "providerId": "aetheria", + "surfaceId": "aetheria.daemon.editor", + "purpose": "Aetheria interactive-world-editor capture control." } ], "authority": "Capture observes Electron projection only; provider state, command acceptance, and receipts stay provider-owned.", diff --git a/runtimes/incubating/eve-tui/eve-runtime-capability.json b/runtimes/incubating/eve-tui/eve-runtime-capability.json index 13ccb60..26bdd3d 100644 --- a/runtimes/incubating/eve-tui/eve-runtime-capability.json +++ b/runtimes/incubating/eve-tui/eve-runtime-capability.json @@ -154,6 +154,11 @@ "providerId": "eve.world-smoke", "surfaceId": "eve.world-smoke.surface", "purpose": "Generic non-product interactive-world capture control." + }, + { + "providerId": "aetheria", + "surfaceId": "aetheria.daemon.editor", + "purpose": "Aetheria interactive-world-editor capture control." } ], "authority": "Capture observes terminal projection only; provider state, command acceptance, and receipts stay provider-owned.", diff --git a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 index 9b71548..e4cf688 100644 --- a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 @@ -215,6 +215,8 @@ node $consumerScript $consumerExport ` --expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.requiredSurface:aetheria.daemon.game" ` --expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.additionalProviderSurfaces.0.providerId:eve.world-smoke" ` --expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.additionalProviderSurfaces.0.surfaceId:eve.world-smoke.surface" ` + --expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.additionalProviderSurfaces.1.providerId:aetheria" ` + --expect-runtime-lifecycle-field "unity-uitoolkit:capture:captureContract.additionalProviderSurfaces.1.surfaceId:aetheria.daemon.editor" ` --expect-runtime-lifecycle-status unity-scene:release:pending-unity-scene-package ` --expect-runtime-lifecycle-status unity-scene:test:provider-shell-contract-skeleton ` --expect-runtime-lifecycle-status unity-scene:capture:pending-unity-scene-capture ` @@ -262,6 +264,8 @@ node $consumerScript $consumerExport ` --expect-runtime-lifecycle-field "electron-shell:capture:captureContract.requiredSurface:aetheria.daemon.game" ` --expect-runtime-lifecycle-field "electron-shell:capture:captureContract.additionalProviderSurfaces.0.providerId:eve.world-smoke" ` --expect-runtime-lifecycle-field "electron-shell:capture:captureContract.additionalProviderSurfaces.0.surfaceId:eve.world-smoke.surface" ` + --expect-runtime-lifecycle-field "electron-shell:capture:captureContract.additionalProviderSurfaces.1.providerId:aetheria" ` + --expect-runtime-lifecycle-field "electron-shell:capture:captureContract.additionalProviderSurfaces.1.surfaceId:aetheria.daemon.editor" ` --expect-runtime-lifecycle-status tui:release:pending-tui-package ` --expect-runtime-lifecycle-status tui:test:provider-shell-contract-skeleton ` --expect-runtime-lifecycle-status tui:capture:cell-grid-json-capture ` @@ -284,7 +288,9 @@ node $consumerScript $consumerExport ` --expect-runtime-lifecycle-field "tui:capture:captureContract.advertisementPath:web/fixtures/aetheria.provider-advertisement.json" ` --expect-runtime-lifecycle-field "tui:capture:captureContract.requiredSurface:aetheria.daemon.game" ` --expect-runtime-lifecycle-field "tui:capture:captureContract.additionalProviderSurfaces.0.providerId:eve.world-smoke" ` - --expect-runtime-lifecycle-field "tui:capture:captureContract.additionalProviderSurfaces.0.surfaceId:eve.world-smoke.surface" + --expect-runtime-lifecycle-field "tui:capture:captureContract.additionalProviderSurfaces.0.surfaceId:eve.world-smoke.surface" ` + --expect-runtime-lifecycle-field "tui:capture:captureContract.additionalProviderSurfaces.1.providerId:aetheria" ` + --expect-runtime-lifecycle-field "tui:capture:captureContract.additionalProviderSurfaces.1.surfaceId:aetheria.daemon.editor" if ($LASTEXITCODE -ne 0) { throw "Runtime owner conformance consumer smoke failed with exit code $LASTEXITCODE" diff --git a/tools/eveelectron/eveelectron-capture-artifact.mjs b/tools/eveelectron/eveelectron-capture-artifact.mjs index 7e140c2..56a1579 100644 --- a/tools/eveelectron/eveelectron-capture-artifact.mjs +++ b/tools/eveelectron/eveelectron-capture-artifact.mjs @@ -10,6 +10,7 @@ export function buildElectronCaptureArtifact({ surfaceDocument, advertisementPath = "", capabilityManifestPath = "", + captureSurfaceId = "", stamp = "latest", } = {}) { const request = buildElectronCaptureRequest({ @@ -17,6 +18,7 @@ export function buildElectronCaptureArtifact({ capabilityManifest, advertisementPath, capabilityManifestPath, + captureSurfaceId, stamp, }); const shell = new EveElectronShell(); @@ -97,6 +99,7 @@ function runCli() { surfaceDocument: loadJsonFile(args.surface), advertisementPath: args.advertisement, capabilityManifestPath: args.capability, + captureSurfaceId: args["surface-id"] || "", stamp, }); writeElectronCaptureArtifact(artifact, { diff --git a/tools/eveelectron/eveelectron-capture-contract.mjs b/tools/eveelectron/eveelectron-capture-contract.mjs index f7d7938..6a26a08 100644 --- a/tools/eveelectron/eveelectron-capture-contract.mjs +++ b/tools/eveelectron/eveelectron-capture-contract.mjs @@ -7,6 +7,7 @@ export function buildElectronCaptureRequest({ capabilityManifest, advertisementPath = "", capabilityManifestPath = "", + captureSurfaceId = "", stamp = new Date().toISOString().replace(/[:.]/g, "-"), } = {}) { if (!advertisement || typeof advertisement !== "object") { @@ -21,8 +22,13 @@ export function buildElectronCaptureRequest({ throw new Error("capability manifest is missing lifecycle.capture.captureContract"); } - const captureSurface = selectCaptureSurface(captureContract, advertisement.providerId); + const captureSurface = selectCaptureSurface(captureContract, advertisement.providerId, captureSurfaceId); if (!captureSurface) { + if (captureSurfaceId) { + throw new Error( + `capture surface mismatch: expected ${captureSurfaceList(captureContract)} got ${advertisement.providerId || "missing"}:${captureSurfaceId}`, + ); + } throw new Error( `capture provider mismatch: expected ${captureProviderList(captureContract)} got ${advertisement.providerId || "missing"}`, ); @@ -79,14 +85,20 @@ function replaceStamp(pattern, stamp) { return pattern.replace("{stamp}", stamp); } -function selectCaptureSurface(captureContract, providerId) { - return captureSurfaceClaims(captureContract).find(claim => claim.providerId === providerId) || null; +function selectCaptureSurface(captureContract, providerId, surfaceId = "") { + const claims = captureSurfaceClaims(captureContract).filter(claim => claim.providerId === providerId); + if (surfaceId) return claims.find(claim => claim.surfaceId === surfaceId) || null; + return claims[0] || null; } function captureProviderList(captureContract) { return captureSurfaceClaims(captureContract).map(claim => claim.providerId).filter(Boolean).join(", ") || "missing"; } +function captureSurfaceList(captureContract) { + return captureSurfaceClaims(captureContract).map(claim => `${claim.providerId}:${claim.surfaceId}`).join(", ") || "missing"; +} + function captureSurfaceClaims(captureContract) { return [ { @@ -134,6 +146,7 @@ function runCli() { capabilityManifest: loadJsonFile(args.capability), advertisementPath: args.advertisement, capabilityManifestPath: args.capability, + captureSurfaceId: args["surface-id"] || "", stamp, }); writeCaptureRequest(request, args.output); diff --git a/tools/eveelectron/eveelectron-capture-contract.test.mjs b/tools/eveelectron/eveelectron-capture-contract.test.mjs index 339c36f..010acfa 100644 --- a/tools/eveelectron/eveelectron-capture-contract.test.mjs +++ b/tools/eveelectron/eveelectron-capture-contract.test.mjs @@ -29,6 +29,25 @@ test("builds Electron shell capture request from provider advertisement", () => assert.match(request.authority, /provider state/); }); +test("builds Electron shell capture request for Aetheria editor surface", () => { + const request = buildElectronCaptureRequest({ + advertisement, + capabilityManifest, + captureSurfaceId: "aetheria.daemon.editor", + advertisementPath: "web/fixtures/aetheria.provider-advertisement.json", + capabilityManifestPath: "runtimes/incubating/eve-electron/eve-runtime-capability.json", + stamp: "smoke", + }); + + assert.equal(request.runtimeId, "electron-shell"); + assert.equal(request.providerId, "aetheria"); + assert.equal(request.surfaceId, "aetheria.daemon.editor"); + assert.equal(request.surfaceKind, "interactive-world-editor"); + assert.equal(request.projectionKind, "provider-authored-world-editor-surface"); + assert.equal(request.commandBoundary, "aetheria.daemon.commands"); + assert.equal(request.receiptSchema, "aetheria.eve_command_acceptance_status.v1"); +}); + test("builds Electron shell capture request from a declared generic world provider", () => { const request = buildElectronCaptureRequest({ advertisement: worldSmokeAdvertisement, diff --git a/tools/evetui/evetui-capture-artifact.mjs b/tools/evetui/evetui-capture-artifact.mjs index 41c96e6..2d55e25 100644 --- a/tools/evetui/evetui-capture-artifact.mjs +++ b/tools/evetui/evetui-capture-artifact.mjs @@ -10,6 +10,7 @@ export function buildTuiCaptureArtifact({ surfaceDocument, advertisementPath = "", capabilityManifestPath = "", + captureSurfaceId = "", stamp = "latest", width = 80, } = {}) { @@ -18,6 +19,7 @@ export function buildTuiCaptureArtifact({ capabilityManifest, advertisementPath, capabilityManifestPath, + captureSurfaceId, stamp, }); const shell = new EveTuiShell({ width }); @@ -98,6 +100,7 @@ function runCli() { surfaceDocument: loadJsonFile(args.surface), advertisementPath: args.advertisement, capabilityManifestPath: args.capability, + captureSurfaceId: args["surface-id"] || "", stamp, width: Number(args.width || 80), }); diff --git a/tools/evetui/evetui-capture-contract.mjs b/tools/evetui/evetui-capture-contract.mjs index 9a074af..6984e72 100644 --- a/tools/evetui/evetui-capture-contract.mjs +++ b/tools/evetui/evetui-capture-contract.mjs @@ -7,6 +7,7 @@ export function buildTuiCaptureRequest({ capabilityManifest, advertisementPath = "", capabilityManifestPath = "", + captureSurfaceId = "", stamp = new Date().toISOString().replace(/[:.]/g, "-"), } = {}) { if (!advertisement || typeof advertisement !== "object") { @@ -21,8 +22,13 @@ export function buildTuiCaptureRequest({ throw new Error("capability manifest is missing lifecycle.capture.captureContract"); } - const captureSurface = selectCaptureSurface(captureContract, advertisement.providerId); + const captureSurface = selectCaptureSurface(captureContract, advertisement.providerId, captureSurfaceId); if (!captureSurface) { + if (captureSurfaceId) { + throw new Error( + `capture surface mismatch: expected ${captureSurfaceList(captureContract)} got ${advertisement.providerId || "missing"}:${captureSurfaceId}`, + ); + } throw new Error( `capture provider mismatch: expected ${captureProviderList(captureContract)} got ${advertisement.providerId || "missing"}`, ); @@ -79,14 +85,20 @@ function replaceStamp(pattern, stamp) { return pattern.replace("{stamp}", stamp); } -function selectCaptureSurface(captureContract, providerId) { - return captureSurfaceClaims(captureContract).find(claim => claim.providerId === providerId) || null; +function selectCaptureSurface(captureContract, providerId, surfaceId = "") { + const claims = captureSurfaceClaims(captureContract).filter(claim => claim.providerId === providerId); + if (surfaceId) return claims.find(claim => claim.surfaceId === surfaceId) || null; + return claims[0] || null; } function captureProviderList(captureContract) { return captureSurfaceClaims(captureContract).map(claim => claim.providerId).filter(Boolean).join(", ") || "missing"; } +function captureSurfaceList(captureContract) { + return captureSurfaceClaims(captureContract).map(claim => `${claim.providerId}:${claim.surfaceId}`).join(", ") || "missing"; +} + function captureSurfaceClaims(captureContract) { return [ { @@ -134,6 +146,7 @@ function runCli() { capabilityManifest: loadJsonFile(args.capability), advertisementPath: args.advertisement, capabilityManifestPath: args.capability, + captureSurfaceId: args["surface-id"] || "", stamp, }); writeCaptureRequest(request, args.output); diff --git a/tools/evetui/evetui-capture-contract.test.mjs b/tools/evetui/evetui-capture-contract.test.mjs index 73ede9b..fdec72f 100644 --- a/tools/evetui/evetui-capture-contract.test.mjs +++ b/tools/evetui/evetui-capture-contract.test.mjs @@ -31,6 +31,25 @@ test("builds TUI capture request from provider advertisement", () => { assert.match(request.authority, /provider state/); }); +test("builds TUI capture request for Aetheria editor surface", () => { + const request = buildTuiCaptureRequest({ + advertisement, + capabilityManifest, + captureSurfaceId: "aetheria.daemon.editor", + advertisementPath: "web/fixtures/aetheria.provider-advertisement.json", + capabilityManifestPath: "runtimes/incubating/eve-tui/eve-runtime-capability.json", + stamp: "smoke", + }); + + assert.equal(request.runtimeId, "tui"); + assert.equal(request.providerId, "aetheria"); + assert.equal(request.surfaceId, "aetheria.daemon.editor"); + assert.equal(request.surfaceKind, "interactive-world-editor"); + assert.equal(request.projectionKind, "provider-authored-world-editor-surface"); + assert.equal(request.commandBoundary, "aetheria.daemon.commands"); + assert.equal(request.receiptSchema, "aetheria.eve_command_acceptance_status.v1"); +}); + test("builds TUI capture request from a declared generic world provider", () => { const request = buildTuiCaptureRequest({ advertisement: worldSmokeAdvertisement, diff --git a/tools/eveunity/eveunity-capture-contract.mjs b/tools/eveunity/eveunity-capture-contract.mjs index ad59bd1..5766ceb 100644 --- a/tools/eveunity/eveunity-capture-contract.mjs +++ b/tools/eveunity/eveunity-capture-contract.mjs @@ -7,6 +7,7 @@ export function buildUnityCaptureRequest({ capabilityManifest, advertisementPath = "", capabilityManifestPath = "", + captureSurfaceId = "", stamp = new Date().toISOString().replace(/[:.]/g, "-"), } = {}) { if (!advertisement || typeof advertisement !== "object") { @@ -21,8 +22,13 @@ export function buildUnityCaptureRequest({ throw new Error("capability manifest is missing lifecycle.capture.captureContract"); } - const captureSurface = selectCaptureSurface(captureContract, advertisement.providerId); + const captureSurface = selectCaptureSurface(captureContract, advertisement.providerId, captureSurfaceId); if (!captureSurface) { + if (captureSurfaceId) { + throw new Error( + `capture surface mismatch: expected ${captureSurfaceList(captureContract)} got ${advertisement.providerId || "missing"}:${captureSurfaceId}`, + ); + } throw new Error( `capture provider mismatch: expected ${captureProviderList(captureContract)} got ${advertisement.providerId || "missing"}`, ); @@ -79,14 +85,20 @@ function replaceStamp(pattern, stamp) { return pattern.replace("{stamp}", stamp); } -function selectCaptureSurface(captureContract, providerId) { - return captureSurfaceClaims(captureContract).find(claim => claim.providerId === providerId) || null; +function selectCaptureSurface(captureContract, providerId, surfaceId = "") { + const claims = captureSurfaceClaims(captureContract).filter(claim => claim.providerId === providerId); + if (surfaceId) return claims.find(claim => claim.surfaceId === surfaceId) || null; + return claims[0] || null; } function captureProviderList(captureContract) { return captureSurfaceClaims(captureContract).map(claim => claim.providerId).filter(Boolean).join(", ") || "missing"; } +function captureSurfaceList(captureContract) { + return captureSurfaceClaims(captureContract).map(claim => `${claim.providerId}:${claim.surfaceId}`).join(", ") || "missing"; +} + function captureSurfaceClaims(captureContract) { return [ { @@ -134,6 +146,7 @@ function runCli() { capabilityManifest: loadJsonFile(args.capability), advertisementPath: args.advertisement, capabilityManifestPath: args.capability, + captureSurfaceId: args["surface-id"] || "", stamp, }); writeCaptureRequest(request, args.output); diff --git a/tools/eveunity/eveunity-capture-contract.test.mjs b/tools/eveunity/eveunity-capture-contract.test.mjs index a5049b3..e27cbe2 100644 --- a/tools/eveunity/eveunity-capture-contract.test.mjs +++ b/tools/eveunity/eveunity-capture-contract.test.mjs @@ -30,6 +30,25 @@ test("builds Unity UI Toolkit capture request from provider advertisement", () = assert.match(request.authority, /provider state/); }); +test("builds Unity UI Toolkit capture request for Aetheria editor surface", () => { + const request = buildUnityCaptureRequest({ + advertisement, + capabilityManifest, + captureSurfaceId: "aetheria.daemon.editor", + advertisementPath: "web/fixtures/aetheria.provider-advertisement.json", + capabilityManifestPath: "packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json", + stamp: "smoke", + }); + + assert.equal(request.runtimeId, "unity-uitoolkit"); + assert.equal(request.providerId, "aetheria"); + assert.equal(request.surfaceId, "aetheria.daemon.editor"); + assert.equal(request.surfaceKind, "interactive-world-editor"); + assert.equal(request.projectionKind, "provider-authored-world-editor-surface"); + assert.equal(request.commandBoundary, "aetheria.daemon.commands"); + assert.equal(request.receiptSchema, "aetheria.eve_command_acceptance_status.v1"); +}); + test("builds Unity UI Toolkit capture request from a declared generic world provider", () => { const request = buildUnityCaptureRequest({ advertisement: worldSmokeAdvertisement, @@ -94,3 +113,15 @@ test("builds Unity scene capture request from a declared generic world provider" assert.equal(request.commandBoundary, "eve.world-smoke.commands"); assert.equal(request.receiptSchema, "eve.world_smoke.command_receipt.v1"); }); + +test("rejects Unity scene capture request for Aetheria editor surface", () => { + assert.throws( + () => buildUnityCaptureRequest({ + advertisement, + capabilityManifest: sceneCapabilityManifest, + captureSurfaceId: "aetheria.daemon.editor", + stamp: "smoke", + }), + /capture surface mismatch/, + ); +}); diff --git a/tools/eveunity/eveunity-scene-capture-artifact.mjs b/tools/eveunity/eveunity-scene-capture-artifact.mjs index 878cea0..4805d66 100644 --- a/tools/eveunity/eveunity-scene-capture-artifact.mjs +++ b/tools/eveunity/eveunity-scene-capture-artifact.mjs @@ -9,6 +9,7 @@ export function buildUnitySceneCaptureArtifact({ surfaceDocument, advertisementPath = "", capabilityManifestPath = "", + captureSurfaceId = "", stamp = "latest", } = {}) { const request = buildUnityCaptureRequest({ @@ -16,6 +17,7 @@ export function buildUnitySceneCaptureArtifact({ capabilityManifest, advertisementPath, capabilityManifestPath, + captureSurfaceId, stamp, }); const projection = buildUnitySceneProjection(surfaceDocument, advertisement, request.surfaceId); @@ -292,6 +294,7 @@ function runCli() { surfaceDocument: loadJsonFile(args.surface), advertisementPath: args.advertisement, capabilityManifestPath: args.capability, + captureSurfaceId: args["surface-id"] || "", stamp, }); writeUnitySceneCaptureArtifact(artifact, { diff --git a/tools/eveunity/eveunity-uitoolkit-capture-artifact.mjs b/tools/eveunity/eveunity-uitoolkit-capture-artifact.mjs index d082b2d..b20bf15 100644 --- a/tools/eveunity/eveunity-uitoolkit-capture-artifact.mjs +++ b/tools/eveunity/eveunity-uitoolkit-capture-artifact.mjs @@ -9,6 +9,7 @@ export function buildUnityUiToolkitCaptureArtifact({ surfaceDocument, advertisementPath = "", capabilityManifestPath = "", + captureSurfaceId = "", stamp = "latest", } = {}) { const request = buildUnityCaptureRequest({ @@ -16,6 +17,7 @@ export function buildUnityUiToolkitCaptureArtifact({ capabilityManifest, advertisementPath, capabilityManifestPath, + captureSurfaceId, stamp, }); const projection = buildUnityUiToolkitProjection(surfaceDocument, advertisement, request.surfaceId); @@ -308,6 +310,7 @@ function runCli() { surfaceDocument: loadJsonFile(args.surface), advertisementPath: args.advertisement, capabilityManifestPath: args.capability, + captureSurfaceId: args["surface-id"] || "", stamp, }); writeUnityUiToolkitCaptureArtifact(artifact, { diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index 710fe78..f7c702a 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -1789,6 +1789,11 @@ "providerId": "eve.world-smoke", "surfaceId": "eve.world-smoke.surface", "purpose": "Generic non-product interactive-world capture control." + }, + { + "providerId": "aetheria", + "surfaceId": "aetheria.daemon.editor", + "purpose": "Aetheria interactive-world-editor capture control." } ], "authority": "Capture observes runtime projection only; provider state, command acceptance, and receipts stay provider-owned.",