Add Unity scene Norn projection boundary

This commit is contained in:
Meta Vens 2026-07-09 12:55:32 +01:00
commit 7aba6a8ec4
11 changed files with 213 additions and 54 deletions

View file

@ -296,8 +296,8 @@ Recently cut:
artifacts so `web:embedded-surface:bounding-boxes` and
`web:sai-vn:bounding-boxes` are measured runtime evidence instead of
`pending-runtime-probe`. This proves the browser oracle can measure both core
embedded slots and Sai's nested Norn/TeX plugin composition without taking
custody of plugin semantics.
embedded slots and a Sai surface that optionally composes independent Norn
and TeX plugin surfaces without taking custody of their semantics.
- The conformance export now carries `screenshotComparisonMetrics[]` records.
Runtime owners get structure, color-token, bounding-box, and text-presence
metrics per runtime/fixture pair without relying on byte-identical screenshots
@ -391,15 +391,15 @@ Recently cut:
are available, but Sai does not own their graph or math semantics.
- Runtime/plugin projection claims are now exported as root
`runtimePluginProjectionCoverage[]` records. Runtime-owner smokes assert
Unity UI Toolkit support for `sai.vn` and `norn.graph`, its declared TeX gap,
and the pending Unity scene/Electron unsupported Sai projection until their
generic lowerers exist.
Unity UI Toolkit support for `sai.vn` and `norn.graph`, Unity scene support
for `norn.graph`, the declared TeX gaps, and the pending Unity
scene/Electron unsupported Sai projection until their generic lowerers exist.
- Provider/runtime/plugin projection coverage is now exported as
`providerRuntimePluginProjectionCoverage[]`. The runtime-owner smoke proves
the Sai VN provider surface lowers fully in web, lowers in Unity UI Toolkit
with Norn support and TeX as a degraded optional nested plugin, and does not
let UIKit's generic embedded-document path impersonate full Sai/Norn
projection.
let UIKit's generic embedded-document path impersonate required Sai VN or
optional Norn graph projection.
- Runtime/plugin projection gaps are now exported as
`runtimePluginProjectionGaps[]`. The runtime-owner smoke asserts Unity and
Electron plugin gaps as typed records, so missing Sai, Norn, or TeX projection
@ -431,8 +431,8 @@ Recently cut:
Unity scene PNG/frame artifact remains pending. The scene graph now preserves
embedded document slot identity for resolver-backed child surfaces without
owning the nested plugin semantics. Plugin projection adapters stay
unsupported until Sai, Norn, or TeX sidecar projection support exists in the
Unity scene runtime.
unsupported for Sai and TeX until those sidecar projection adapters exist in
the Unity scene runtime.
- Unity scene now has a direct split handoff smoke at
`scripts/run-eveunity-scene-split-handoff-smoke.ps1`. The smoke verifies the
scene runtime's current source paths for runtime body, scene graph lowering,
@ -630,8 +630,8 @@ Recently cut:
request/response schemas, operations, command envelope, receipt schema, and
state authority. The parity harness validates manifest/advertisement
agreement, checks sidecar operations against ABI fixture operations, exports
the runtime boundary, and the plugin-owner consumer smoke asserts the Sai/Norn
sidecar contract from the conformance pack.
the runtime boundary, and the plugin-owner consumer smoke asserts the Sai and
Norn sidecar contracts from the conformance pack.
- 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
@ -735,8 +735,8 @@ Recently cut:
tagged release, test runner ownership, and capture runner ownership must move
to `EveFlutter`, rather than pretending the lifecycle shape is still unknown.
- EveFlutter now has a provider-catalog picker primitive. `EveProviderCatalog`
parses conformance-export provider entries, including Sai/Norn/TeX plugin
requirements, and `EveProviderPicker` selects those provider ids without
parses conformance-export provider entries, including separate Sai, Norn, and
TeX plugin requirements, and `EveProviderPicker` selects those provider ids without
reading web fixture paths. The Flutter smoke test proves provider selection
from an export-shaped provider list, so the split-readiness report records the
provider-picker proof as passed while leaving release/capture lifecycle
@ -755,11 +755,12 @@ Recently cut:
the parity harness validates embedded-slot preservation, command descriptors,
runtime authority witnesses, and style tokens. Direct2D capture and
runtime-owned command smoke remain the activation blockers.
- UIKit and Kotlin device-edge runtimes now declare unsupported Sai/Norn/TeX
plugin projection explicitly. They remain generic embedded-document and
device-edge proofs; plugin projection authority belongs to EveFlutter,
EveUnity, or future runtime-specific projection adapters instead of being
reported as unexplained active capability gaps.
- UIKit and Kotlin device-edge runtimes now declare unsupported plugin
projection explicitly for separate Sai, Norn, and TeX capabilities. They
remain generic embedded-document and device-edge proofs; plugin projection
authority belongs to EveFlutter, EveUnity, or future runtime-specific
projection adapters instead of being reported as unexplained active capability
gaps.
- The web reference no longer hardcodes the local provider list in
`web/surface.js`. It loads `web/local-provider-catalog.json`, then opens
advertisement-backed entries for Aetheria, Repixelizer, and Sai through the
@ -771,8 +772,9 @@ Recently cut:
requirements against known plugin manifests, exports them in the conformance
provider list, and reports missing plugins or capabilities as provider
capability gaps. The Sai VN fixture now has an advertisement-shaped provider
entry for `gamecult.home.vn`, so Sai/Norn/TeX requirements sit at the
provider/plugin boundary instead of hiding only in fixture metadata.
entry for `gamecult.home.vn`, so Sai, Norn, and TeX requirements sit at
separate provider/plugin boundaries instead of hiding only in fixture
metadata.
- The conformance runtime pack now exports `runtimeTargets` in
`artifacts/conformance/latest/packs/runtime.json`. Runtime repos can consume
runtime status, feature/plugin claims, command schema, lifecycle, capture
@ -821,9 +823,14 @@ Recently cut:
- Unity UI Toolkit now has a first-party `norn.graph` projection-adapter proof
for `embed.norn`. `NornGraphUiToolkitProjectionAdapter` owns the native
embedded graph shell and graph command emission path, while the Norn sidecar
plugin keeps graph layout and graph semantics. EveUnity split-readiness is now
plugin keeps graph layout and graph semantics. UI Toolkit split-readiness is now
blocked on runtime-owned release, test, and capture lifecycle evidence rather
than missing Sai/Norn projection support.
than missing required Sai VN or optional Norn graph projection support.
- Unity scene now has the same kind of bounded `norn.graph` projection proof
for `embed.norn`. `NornGraphUnitySceneProjectionAdapter` emits a
scene-projection shell with the sidecar ABI, command boundary, document id,
and Norn semantic owner preserved; it does not calculate graph layout or make
graph-state decisions.
- Unity UI Toolkit now has a first-party `sai.vn` projection-adapter proof. The
runtime owns `IEveUiToolkitPluginProjectionAdapter`, registers
`SaiVisualNovelUiToolkitProjectionAdapter` through
@ -835,9 +842,9 @@ Recently cut:
`packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json`. The
parity harness validates that manifest against
`gamecult.eve.runtime_capability.v1`, cross-checks supported features,
unsupported Sai/Norn/TeX plugin declarations, command transport schema, and
incubation metadata, then exports the manifest path and validation errors
through the conformance report.
supported Sai and Norn plugin declarations, the unsupported TeX declaration,
command transport schema, and incubation metadata, then exports the manifest
path and validation errors through the conformance report.
- Aetheria now consumes the exported conformance pack from its own working
directory through `scripts/run-aetheria-conformance-consumer-smoke.ps1`. The
smoke asserts the provider pack, `aetheria-world` fixture, `aetheria`

View file

@ -150,8 +150,9 @@ assert them with `--expect-runtime-plugin-gap <runtimeId:pluginId:ownerRepo>`.
The same claims are exported as `runtimePluginProjectionCoverage[]`, including
positive `supported` projection adapters and declared `unsupported` gaps. This
lets runtime and plugin owners consume one ledger for "Unity UI Toolkit has
projection adapters for Sai/Norn sidecar-advertised output" and "Unity
scene/Electron do not have generic plugin projection yet" instead of walking
projection adapters for independent Sai and Norn sidecar-advertised output,"
"Unity scene can project Norn's sidecar-advertised embedded graph shell," and
"Electron does not have generic plugin projection yet" instead of walking
nested runtime records. Consumer smokes can assert entries with
`--expect-runtime-plugin-projection <runtimeId:pluginId:status:ownerRepo>`.
Provider surface plugin requirements are also joined with runtime projection

View file

@ -61,7 +61,7 @@
"provider internals",
"plugin semantic internals",
"Aetheria daemon state as Unity package authority",
"Sai or Norn implementation state as Unity projection authority"
"Sai, Norn, or TeX implementation state as Unity projection authority"
],
"requiredExternalProofs": [
"EveUnity publishes a tagged UPM release.",

View file

@ -9,6 +9,8 @@ namespace GameCult.Eve.UnityScene
{
public sealed class EveUnitySceneSurfaceLowerer
{
private static readonly NornGraphUnitySceneProjectionAdapter NornGraphAdapter = new NornGraphUnitySceneProjectionAdapter();
public EveUnitySceneProjection Lower(
EveSurfaceDocument document,
EveUnitySceneProviderSurfaceAdvertisement advertisedSurface)
@ -85,9 +87,17 @@ namespace GameCult.Eve.UnityScene
component.StateBindings.Count,
component.EmbeddedDocuments.Count,
BuildEmbeddedDocumentSlots(component.EmbeddedDocuments),
BuildPluginProjection(component),
children);
}
private static EveUnityScenePluginProjection? BuildPluginProjection(EveSurfaceComponent component)
{
if (NornGraphAdapter.CanProject(component))
return NornGraphAdapter.Project(component);
return null;
}
private static IReadOnlyList<EveUnitySceneEmbeddedDocumentSlot> BuildEmbeddedDocumentSlots(
IReadOnlyList<EveEmbeddedDocumentSlot> embeddedDocuments)
{
@ -109,6 +119,8 @@ namespace GameCult.Eve.UnityScene
return "empty";
if (componentKind.StartsWith("control.", StringComparison.Ordinal))
return "command-control";
if (string.Equals(componentKind, "embed.norn", StringComparison.Ordinal))
return "norn-graph-scene-projection";
if (componentKind.StartsWith("embed.", StringComparison.Ordinal))
return "plugin-placeholder";
if (string.Equals(componentKind, "surface.slot", StringComparison.Ordinal))
@ -168,6 +180,7 @@ namespace GameCult.Eve.UnityScene
int stateBindingCount,
int embeddedDocumentCount,
IReadOnlyList<EveUnitySceneEmbeddedDocumentSlot> embeddedDocuments,
EveUnityScenePluginProjection? pluginProjection,
IReadOnlyList<EveUnitySceneNode> children)
{
Id = id ?? "";
@ -179,6 +192,7 @@ namespace GameCult.Eve.UnityScene
StateBindingCount = stateBindingCount;
EmbeddedDocumentCount = embeddedDocumentCount;
EmbeddedDocuments = embeddedDocuments ?? Array.Empty<EveUnitySceneEmbeddedDocumentSlot>();
PluginProjection = pluginProjection;
Children = children ?? Array.Empty<EveUnitySceneNode>();
}
@ -200,9 +214,50 @@ namespace GameCult.Eve.UnityScene
public IReadOnlyList<EveUnitySceneEmbeddedDocumentSlot> EmbeddedDocuments { get; }
public EveUnityScenePluginProjection? PluginProjection { get; }
public IReadOnlyList<EveUnitySceneNode> Children { get; }
}
public sealed class EveUnityScenePluginProjection
{
public EveUnityScenePluginProjection(
string pluginId,
string projectionKind,
string abiSchema,
string commandBoundary,
IReadOnlyList<string> capabilities,
string command,
string documentId,
string semanticOwner)
{
PluginId = pluginId ?? "";
ProjectionKind = projectionKind ?? "";
AbiSchema = abiSchema ?? "";
CommandBoundary = commandBoundary ?? "";
Capabilities = capabilities ?? Array.Empty<string>();
Command = command ?? "";
DocumentId = documentId ?? "";
SemanticOwner = semanticOwner ?? "";
}
public string PluginId { get; }
public string ProjectionKind { get; }
public string AbiSchema { get; }
public string CommandBoundary { get; }
public IReadOnlyList<string> Capabilities { get; }
public string Command { get; }
public string DocumentId { get; }
public string SemanticOwner { get; }
}
public sealed class EveUnitySceneEmbeddedDocumentSlot
{
public EveUnitySceneEmbeddedDocumentSlot(

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using GameCult.Eve.Surface;
#nullable enable
namespace GameCult.Eve.UnityScene
{
public sealed class NornGraphUnitySceneProjectionAdapter
{
public string PluginId => "norn.graph";
public IReadOnlyList<string> Capabilities { get; } = new[]
{
"embed.norn"
};
public bool CanProject(EveSurfaceComponent component)
{
return component != null && string.Equals(component.Kind, "embed.norn", StringComparison.Ordinal);
}
public EveUnityScenePluginProjection Project(EveSurfaceComponent component)
{
if (component == null) throw new ArgumentNullException(nameof(component));
if (!CanProject(component))
{
throw new InvalidOperationException(
$"Norn scene projection adapter cannot project component kind '{component.Kind}'.");
}
return new EveUnityScenePluginProjection(
PluginId,
"norn-scene-embedded-graph-shell",
"gamecult.eve.plugin_abi.v1",
"sidecar-advertised-plugin-abi",
Capabilities,
component.GetProp(
"interaction.nodeAction",
component.GetProp("focusCommand", component.GetProp("command", "graph.focus"))),
component.GetProp("graph.document", component.GetProp("documentId", "")),
"Norn");
}
}
}

View file

@ -38,13 +38,23 @@ namespace GameCult.Eve.UnityScene.Tests
Assert.That(projection.Root.Children[0].StateBindingCount, Is.EqualTo(1));
Assert.That(projection.Root.Children[1].SceneObjectKind, Is.EqualTo("command-control"));
Assert.That(projection.Root.Children[1].Props["command"], Is.EqualTo("aetheria.daemon.focus"));
Assert.That(projection.Root.Children[2].SceneObjectKind, Is.EqualTo("plugin-placeholder"));
Assert.That(projection.Root.Children[2].EmbeddedDocumentCount, Is.EqualTo(1));
Assert.That(projection.Root.Children[2].EmbeddedDocuments.Count, Is.EqualTo(1));
Assert.That(projection.Root.Children[2].EmbeddedDocuments[0].SlotId, Is.EqualTo("norn.map"));
Assert.That(projection.Root.Children[2].EmbeddedDocuments[0].DocumentId, Is.EqualTo("cultmesh://aetheria/norn/map"));
Assert.That(projection.Root.Children[2].EmbeddedDocuments[0].SchemaId, Is.EqualTo("gamecult.eve.surface.v1"));
Assert.That(projection.Root.Children[2].EmbeddedDocuments[0].PresentationKind, Is.EqualTo("scene-overlay"));
var nornNode = projection.Root.Children[2];
Assert.That(nornNode.SceneObjectKind, Is.EqualTo("norn-graph-scene-projection"));
Assert.That(nornNode.EmbeddedDocumentCount, Is.EqualTo(1));
Assert.That(nornNode.EmbeddedDocuments.Count, Is.EqualTo(1));
Assert.That(nornNode.EmbeddedDocuments[0].SlotId, Is.EqualTo("norn.map"));
Assert.That(nornNode.EmbeddedDocuments[0].DocumentId, Is.EqualTo("cultmesh://aetheria/norn/map"));
Assert.That(nornNode.EmbeddedDocuments[0].SchemaId, Is.EqualTo("gamecult.eve.surface.v1"));
Assert.That(nornNode.EmbeddedDocuments[0].PresentationKind, Is.EqualTo("scene-overlay"));
Assert.That(nornNode.PluginProjection, Is.Not.Null);
Assert.That(nornNode.PluginProjection!.PluginId, Is.EqualTo("norn.graph"));
Assert.That(nornNode.PluginProjection.ProjectionKind, Is.EqualTo("norn-scene-embedded-graph-shell"));
Assert.That(nornNode.PluginProjection.AbiSchema, Is.EqualTo("gamecult.eve.plugin_abi.v1"));
Assert.That(nornNode.PluginProjection.CommandBoundary, Is.EqualTo("sidecar-advertised-plugin-abi"));
Assert.That(nornNode.PluginProjection.Capabilities, Does.Contain("embed.norn"));
Assert.That(nornNode.PluginProjection.Command, Is.EqualTo("graph.focus"));
Assert.That(nornNode.PluginProjection.DocumentId, Is.EqualTo("cultmesh://aetheria/norn/map"));
Assert.That(nornNode.PluginProjection.SemanticOwner, Is.EqualTo("Norn"));
}
[Test]
@ -109,7 +119,11 @@ namespace GameCult.Eve.UnityScene.Tests
new EveSurfaceComponent(
$"{surfaceId}.norn",
"embed.norn",
new Dictionary<string, string>(StringComparer.Ordinal),
new Dictionary<string, string>(StringComparer.Ordinal)
{
["graph.document"] = "cultmesh://aetheria/norn/map",
["interaction.nodeAction"] = "graph.focus"
},
Array.Empty<EveSurfaceComponent>(),
Array.Empty<CultMeshStateBindingDescriptor>(),
new[]

View file

@ -19,16 +19,20 @@
"sceneGraphProjection",
"embeddedDocuments"
],
"supportedPlugins": [],
"supportedPlugins": [
{
"pluginId": "norn.graph",
"capabilities": [
"embed.norn"
],
"projectionAdapter": "NornGraphUnitySceneProjectionAdapter"
}
],
"unsupportedPlugins": [
{
"pluginId": "sai.vn",
"reason": "Unity scene graph projection exists, but no scene adapter exists for Sai sidecar-advertised VN projection in this runtime."
},
{
"pluginId": "norn.graph",
"reason": "Unity scene graph projection exists, but no scene-space or UI overlay adapter exists for Norn sidecar-advertised graph projection in this runtime."
},
{
"pluginId": "tex.math",
"reason": "Unity scene graph projection exists, but no scene-space or UI overlay adapter exists for TeX sidecar-advertised math projection in this runtime."
@ -43,6 +47,7 @@
"ownership": "runtime-lowers-provider-world-surface-without-owning-world-state",
"evidencePaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"web/fixtures/aetheria.provider-advertisement.json"
]
@ -75,6 +80,7 @@
"runtimes/incubating/eve-unity-scene/package.json",
"runtimes/incubating/eve-unity-scene/Runtime/GameCult.Eve.UnityScene.asmdef",
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/eveunity-scene-split-handoff.json",
"scripts/run-eveunity-scene-split-handoff-smoke.ps1",
"scripts/run-eveunity-scene-release-contract-smoke.ps1",
@ -104,6 +110,7 @@
"runtimes/incubating/eve-unity-scene/package.json",
"runtimes/incubating/eve-unity-scene/Runtime/GameCult.Eve.UnityScene.asmdef",
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/GameCult.Eve.UnityScene.Tests.asmdef",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"runtimes/incubating/eve-unity-scene/eveunity-scene-split-handoff.json",

View file

@ -44,8 +44,18 @@ foreach ($feature in @("providerAdvertisements", "commandTransport", "sceneGraph
throw "EveUnity scene manifest missing provider-shell feature: $feature"
}
}
if (@($manifest.supportedPlugins).Count -ne 0) {
throw "EveUnity scene must not claim plugin projection before runtime projection adapters for sidecar-advertised capabilities exist"
if (@($manifest.supportedPlugins).Count -ne 1) {
throw "EveUnity scene must claim exactly one plugin projection adapter"
}
$nornProjection = @($manifest.supportedPlugins) | Where-Object { $_.pluginId -eq "norn.graph" } | Select-Object -First 1
if (-not $nornProjection) {
throw "EveUnity scene manifest missing supported Norn projection adapter"
}
if ($nornProjection.projectionAdapter -ne "NornGraphUnitySceneProjectionAdapter") {
throw "Unexpected EveUnity scene Norn projection adapter: $($nornProjection.projectionAdapter)"
}
if (-not (@($nornProjection.capabilities) -contains "embed.norn")) {
throw "EveUnity scene Norn projection adapter must claim embed.norn"
}
$worldSurfaceLoweringClaims = @()
if ($null -ne $manifest.worldSurfaceLowering) {
@ -71,12 +81,15 @@ foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) {
}
}
foreach ($pluginId in @("sai.vn", "norn.graph", "tex.math")) {
foreach ($pluginId in @("sai.vn", "tex.math")) {
$unsupported = @($manifest.unsupportedPlugins) | Where-Object { $_.pluginId -eq $pluginId } | Select-Object -First 1
if (-not $unsupported) {
throw "EveUnity scene manifest missing unsupported plugin declaration: $pluginId"
}
}
if (@($manifest.unsupportedPlugins) | Where-Object { $_.pluginId -eq "norn.graph" } | Select-Object -First 1) {
throw "EveUnity scene must not report norn.graph unsupported while the projection adapter is declared"
}
if ($manifest.commandTransport.schema -ne "gamecult.eve.command.v1") {
throw "Unexpected EveUnity scene command schema: $($manifest.commandTransport.schema)"

View file

@ -64,6 +64,7 @@ $expectedFiles = @(
"runtimes\incubating\eve-unity-scene\package.json",
"runtimes\incubating\eve-unity-scene\Runtime\GameCult.Eve.UnityScene.asmdef",
"runtimes\incubating\eve-unity-scene\Runtime\EveUnitySceneSurfaceLowerer.cs",
"runtimes\incubating\eve-unity-scene\Runtime\NornGraphUnitySceneProjectionAdapter.cs",
"runtimes\incubating\eve-unity-scene\Tests\Editor\GameCult.Eve.UnityScene.Tests.asmdef",
"runtimes\incubating\eve-unity-scene\Tests\Editor\EveUnitySceneSurfaceLowererTests.cs"
)
@ -76,14 +77,21 @@ foreach ($relativePath in $expectedFiles) {
}
$lowererSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Runtime\EveUnitySceneSurfaceLowerer.cs") -Raw
foreach ($symbol in @("EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "BuildSceneGraph", "EveUnitySceneNode", "SceneObjectKind", "unity-scene")) {
foreach ($symbol in @("EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "BuildSceneGraph", "BuildPluginProjection", "EveUnityScenePluginProjection", "EveUnitySceneNode", "SceneObjectKind", "unity-scene")) {
if (-not $lowererSource.Contains($symbol)) {
throw "EveUnity scene provider shell lowerer missing symbol: $symbol"
}
}
$nornAdapterSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Runtime\NornGraphUnitySceneProjectionAdapter.cs") -Raw
foreach ($symbol in @("NornGraphUnitySceneProjectionAdapter", "norn.graph", "embed.norn", "gamecult.eve.plugin_abi.v1", "sidecar-advertised-plugin-abi", "Norn")) {
if (-not $nornAdapterSource.Contains($symbol)) {
throw "EveUnity scene Norn projection adapter missing symbol: $symbol"
}
}
$testSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Tests\Editor\EveUnitySceneSurfaceLowererTests.cs") -Raw
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "plugin-placeholder", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "norn-graph-scene-projection", "norn.graph", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
if (-not $testSource.Contains($symbol)) {
throw "EveUnity scene provider shell tests missing symbol: $symbol"
}

View file

@ -93,6 +93,8 @@ node $consumerScript $consumerExport `
--expect-runtime-plugin-projection unity-uitoolkit:norn.graph:supported:EveUnity `
--expect-runtime-plugin-projection unity-uitoolkit:tex.math:unsupported:EveUnity `
--expect-runtime-plugin-projection unity-scene:sai.vn:unsupported:EveUnity `
--expect-runtime-plugin-projection unity-scene:norn.graph:supported:EveUnity `
--expect-runtime-plugin-projection unity-scene:tex.math:unsupported:EveUnity `
--expect-runtime-plugin-projection electron-shell:sai.vn:unsupported:EveElectron `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:web:sai.vn:supported:Eve `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:web:tex.math:optional-supported:Eve `
@ -103,7 +105,6 @@ node $consumerScript $consumerExport `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:ios-uikit:norn.graph:optional-unsupported-runtime-projection:EveIOS `
--expect-runtime-plugin-gap unity-uitoolkit:tex.math:EveUnity `
--expect-runtime-plugin-gap unity-scene:sai.vn:EveUnity `
--expect-runtime-plugin-gap unity-scene:norn.graph:EveUnity `
--expect-runtime-plugin-gap unity-scene:tex.math:EveUnity `
--expect-runtime-plugin-gap electron-shell:sai.vn:EveElectron `
--expect-runtime-plugin-gap electron-shell:norn.graph:EveElectron `

View file

@ -943,16 +943,18 @@
"requiredFixtures": ["aetheria-world"],
"pluginFixtures": [],
"supportedFeatures": ["providerAdvertisements", "commandTransport", "sceneGraphProjection", "embeddedDocuments"],
"supportedPlugins": [],
"supportedPlugins": [
{
"pluginId": "norn.graph",
"capabilities": ["embed.norn"],
"projectionAdapter": "NornGraphUnitySceneProjectionAdapter"
}
],
"unsupportedPlugins": [
{
"pluginId": "sai.vn",
"reason": "Unity scene graph projection exists, but no scene adapter exists for Sai sidecar-advertised VN projection in this runtime."
},
{
"pluginId": "norn.graph",
"reason": "Unity scene graph projection exists, but no scene-space or UI overlay adapter exists for Norn sidecar-advertised graph projection in this runtime."
},
{
"pluginId": "tex.math",
"reason": "Unity scene graph projection exists, but no scene-space or UI overlay adapter exists for TeX sidecar-advertised math projection in this runtime."
@ -967,6 +969,7 @@
"ownership": "runtime-lowers-provider-world-surface-without-owning-world-state",
"evidencePaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"web/fixtures/aetheria.provider-advertisement.json"
]
@ -976,6 +979,7 @@
"runtimes/incubating/eve-unity-scene/package.json",
"runtimes/incubating/eve-unity-scene/Runtime/GameCult.Eve.UnityScene.asmdef",
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/GameCult.Eve.UnityScene.Tests.asmdef",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"runtimes/incubating/eve-unity-scene/eve-runtime-capability.json",
@ -992,11 +996,15 @@
"expectedSourceSymbols": [
{
"path": "runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"contains": ["EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "BuildSceneGraph", "BuildEmbeddedDocumentSlots", "EveUnitySceneEmbeddedDocumentSlot", "EveUnitySceneNode", "SceneObjectKind", "unity-scene"]
"contains": ["EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "BuildSceneGraph", "BuildEmbeddedDocumentSlots", "BuildPluginProjection", "EveUnitySceneEmbeddedDocumentSlot", "EveUnityScenePluginProjection", "EveUnitySceneNode", "SceneObjectKind", "unity-scene"]
},
{
"path": "runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"contains": ["NornGraphUnitySceneProjectionAdapter", "norn.graph", "embed.norn", "gamecult.eve.plugin_abi.v1", "sidecar-advertised-plugin-abi", "Norn"]
},
{
"path": "runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "plugin-placeholder", "norn.map", "cultmesh://aetheria/norn/map", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "norn-graph-scene-projection", "norn.map", "cultmesh://aetheria/norn/map", "norn.graph", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
},
{
"path": "tools/eveunity/eveunity-capture-contract.test.mjs",