Add Unity scene provider session boundary

This commit is contained in:
Meta Vens 2026-07-09 18:03:11 +01:00
commit 84e7195588
11 changed files with 294 additions and 30 deletions

View file

@ -609,10 +609,13 @@ Recently cut:
`world.entity3d`, asset-manifest, input-profile, camera, movement, focus, and
target command affordances; `EveUnitySceneSurfaceLowerer` exposes them as a
`PlayableWorld` projection, and the JSON capture artifact exports the same
`playableWorld` shape under `gamecult.eve.unity_scene_projection.v1`. The
next blocker is the live generic Unity client loop: subscribe to the Aetheria
daemon surface over CultMesh/CultNet, instantiate the projected world, emit
`gamecult.eve.command.v1` input, and wait for provider receipts/next frames.
`playableWorld` shape under `gamecult.eve.unity_scene_projection.v1`.
`EveUnitySceneClientSession` now consumes provider surface snapshots and emits
movement/focus/target/action intents through the advertised command boundary,
so the Unity client boundary is generic before it learns live transport. The
next blocker is the live generic Unity player loop: feed that session from
CultMesh/CultNet, instantiate the projected world in Unity, and wait for
provider receipts/next frames rather than renderer-local simulation.
- EveElectron capture lifecycle now carries the same kind of structured pending
capture contract. `captureContract` names the Electron shell runtime, capture
kind, PNG artifact pattern, conformance attachment point, required Aetheria

View file

@ -477,9 +477,13 @@ and writes `artifacts/eveunity-scene-capture/latest/unity-scene-projection.json`
It records scene graph projection, embedded slots, sidecar plugin projection
metadata, and a `playableWorld` extraction for generic `world.scene3d` /
`world.entity3d` ARPG data: state pointer, asset manifest, camera/input profile,
entity transforms, asset refs, and daemon command affordances. The remaining
blocker is a live generic Unity client loop and Unity screenshot or
frame-capture PNG production from EveUnity.
entity transforms, asset refs, and daemon command affordances. The Unity scene
runtime also declares `providerSurfaceSession` and carries
`EveUnitySceneClientSession`, a provider-snapshot boundary that lowers the
active surface and emits `gamecult.eve.command.v1` intents without Aetheria
types. The remaining blocker is the live CultMesh/CultNet subscription adapter,
Unity player instantiation, and Unity screenshot or frame-capture PNG
production from EveUnity.
Runtime capture probe coverage is exported as `runtimeCaptureProbeCoverage[]`.
Each record joins runtime status, capture owner, lifecycle capture contract,

View file

@ -152,21 +152,23 @@ Toolkit, Unity scene, Electron shell, and TUI lowerers are lowering targets;
Aetheria remains the owner of world state, assets, command acceptance, and
receipts.
The Unity scene lowerer now has a first playable-world extraction proof. The
fixture carries a generic `world.scene3d` node with a daemon state pointer,
asset manifest ref, third-person input/camera profile, movement/focus/target
command names, `world.entity3d` rows, and a `field.vector3d` volume field. The
Unity scene runtime lowers that into `playableWorld` projection evidence:
entity ids, kinds, labels, positions, radii, asset refs, controllability, and
command affordances. Aetheria-specific names appear only as provider-authored
data and command ids; the Unity client code does not import Aetheria runtime
types or apply movement locally.
The Unity scene lowerer now has a playable-world extraction and client-session
proof. The fixture carries a generic `world.scene3d` node with a daemon state
pointer, asset manifest ref, third-person input/camera profile,
movement/focus/target command names, `world.entity3d` rows, and a
`field.vector3d` volume field. The Unity scene runtime lowers that into
`playableWorld` projection evidence: entity ids, kinds, labels, positions,
radii, asset refs, controllability, and command affordances. The generic
`EveUnitySceneClientSession` consumes provider surface snapshots and emits
`gamecult.eve.command.v1` intents through the advertised command boundary.
Aetheria-specific names appear only as provider-authored data and command ids;
the Unity client code does not import Aetheria runtime types or apply movement
locally.
This is not yet the final playable client. The remaining cut is a generic
EveUnity scene client that subscribes to the live Aetheria daemon surface over
CultMesh/CultNet, instantiates the projected world in a Unity player, emits
input as `gamecult.eve.command.v1`, and proves daemon receipts drive the next
frame rather than renderer-local state.
This is not yet the final playable client. The remaining cut is a live
CultMesh/CultNet provider subscription adapter feeding `EveUnitySceneClientSession`,
Unity player instantiation of the projected world, and proof that daemon
receipts drive the next frame rather than renderer-local state.
## Non-Goals

View file

@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using GameCult.Eve.Surface;
#nullable enable
namespace GameCult.Eve.UnityScene
{
public sealed class EveUnitySceneClientSession
{
public const string RuntimeClientId = "unity-scene";
private readonly EveUnitySceneSurfaceLowerer _lowerer;
private EveUnitySceneProviderSurfaceSnapshot? _activeSnapshot;
public EveUnitySceneClientSession()
: this(new EveUnitySceneSurfaceLowerer())
{
}
public EveUnitySceneClientSession(EveUnitySceneSurfaceLowerer lowerer)
{
_lowerer = lowerer ?? throw new ArgumentNullException(nameof(lowerer));
}
public EveUnitySceneProjection? ActiveProjection { get; private set; }
public string ActiveSourcePointer => _activeSnapshot?.SourcePointer ?? "";
public EveUnitySceneProjection Connect(EveUnitySceneProviderSurfaceSnapshot snapshot)
{
if (snapshot == null) throw new ArgumentNullException(nameof(snapshot));
var projection = _lowerer.Lower(snapshot.Document, snapshot.AdvertisedSurface);
_activeSnapshot = snapshot;
ActiveProjection = projection;
return projection;
}
public EveUnitySceneProjection ApplySnapshot(EveUnitySceneProviderSurfaceSnapshot snapshot)
{
return Connect(snapshot);
}
public EveSurfaceCommandRequest CreateMoveIntent(
string entityId,
float targetX,
float targetY,
float targetZ,
DateTimeOffset? issuedAt = null)
{
var playableWorld = RequirePlayableWorld();
return CreatePlayableWorldIntent(
playableWorld.MovementCommand,
new Dictionary<string, string>(StringComparer.Ordinal)
{
["entityId"] = entityId ?? "",
["targetPosition"] = FormatVector3(targetX, targetY, targetZ)
},
issuedAt);
}
public EveSurfaceCommandRequest CreateFocusIntent(
string entityId,
DateTimeOffset? issuedAt = null)
{
var playableWorld = RequirePlayableWorld();
return CreatePlayableWorldIntent(
playableWorld.FocusCommand,
new Dictionary<string, string>(StringComparer.Ordinal)
{
["entityId"] = entityId ?? ""
},
issuedAt);
}
public EveSurfaceCommandRequest CreateTargetIntent(
string sourceEntityId,
string targetEntityId,
DateTimeOffset? issuedAt = null)
{
var playableWorld = RequirePlayableWorld();
return CreatePlayableWorldIntent(
playableWorld.TargetCommand,
new Dictionary<string, string>(StringComparer.Ordinal)
{
["sourceEntityId"] = sourceEntityId ?? "",
["targetEntityId"] = targetEntityId ?? ""
},
issuedAt);
}
public EveSurfaceCommandRequest CreateActionIntent(
string entityId,
string actionId,
DateTimeOffset? issuedAt = null)
{
var playableWorld = RequirePlayableWorld();
return CreatePlayableWorldIntent(
playableWorld.ActionCommand,
new Dictionary<string, string>(StringComparer.Ordinal)
{
["entityId"] = entityId ?? "",
["actionId"] = actionId ?? ""
},
issuedAt);
}
public EveSurfaceCommandRequest CreatePlayableWorldIntent(
string commandId,
IReadOnlyDictionary<string, string>? payload = null,
DateTimeOffset? issuedAt = null)
{
if (string.IsNullOrWhiteSpace(commandId))
throw new InvalidOperationException("Playable world command id is missing from the active surface.");
var snapshot = RequireSnapshot();
var projection = RequireProjection();
var envelopePayload = new Dictionary<string, string>(StringComparer.Ordinal)
{
["commandId"] = commandId
};
if (payload != null)
{
foreach (var entry in payload)
envelopePayload[entry.Key] = entry.Value;
}
return _lowerer.CreateCommandIntent(
snapshot.Document,
snapshot.AdvertisedSurface,
projection.CommandBoundary,
envelopePayload,
issuedAt);
}
private EveUnityPlayableWorldProjection RequirePlayableWorld()
{
var projection = RequireProjection();
if (projection.PlayableWorld == null)
throw new InvalidOperationException("The active Unity scene surface does not expose a playable world projection.");
return projection.PlayableWorld;
}
private EveUnitySceneProjection RequireProjection()
{
if (ActiveProjection == null)
throw new InvalidOperationException("No provider surface snapshot has been connected to the Unity scene client session.");
return ActiveProjection;
}
private EveUnitySceneProviderSurfaceSnapshot RequireSnapshot()
{
if (_activeSnapshot == null)
throw new InvalidOperationException("No provider surface snapshot has been connected to the Unity scene client session.");
return _activeSnapshot;
}
private static string FormatVector3(float x, float y, float z)
{
return string.Join(
",",
x.ToString("R", CultureInfo.InvariantCulture),
y.ToString("R", CultureInfo.InvariantCulture),
z.ToString("R", CultureInfo.InvariantCulture));
}
}
public sealed class EveUnitySceneProviderSurfaceSnapshot
{
public EveUnitySceneProviderSurfaceSnapshot(
EveSurfaceDocument document,
EveUnitySceneProviderSurfaceAdvertisement advertisedSurface,
string sourcePointer,
long version = 0)
{
Document = document ?? throw new ArgumentNullException(nameof(document));
AdvertisedSurface = advertisedSurface ?? throw new ArgumentNullException(nameof(advertisedSurface));
SourcePointer = sourcePointer ?? "";
Version = version;
}
public EveSurfaceDocument Document { get; }
public EveUnitySceneProviderSurfaceAdvertisement AdvertisedSurface { get; }
public string SourcePointer { get; }
public long Version { get; }
}
}

View file

@ -94,6 +94,43 @@ namespace GameCult.Eve.UnityScene.Tests
Assert.That(raider.TargetCommand, Is.EqualTo("aetheria.daemon.target"));
}
[Test]
public void GenericClientSessionConsumesAetheriaPlayableWorldSnapshotWithoutAetheriaTypes()
{
var session = new EveUnitySceneClientSession();
var projection = session.Connect(new EveUnitySceneProviderSurfaceSnapshot(
PlayableArpgDocument(),
Advertisement("aetheria.daemon.game"),
"cultmesh://aetheria/eve/surfaces/aetheria.daemon.game",
42));
Assert.That(session.ActiveSourcePointer, Is.EqualTo("cultmesh://aetheria/eve/surfaces/aetheria.daemon.game"));
Assert.That(session.ActiveProjection, Is.SameAs(projection));
Assert.That(projection.ProviderId, Is.EqualTo("aetheria"));
Assert.That(projection.PlayableWorld, Is.Not.Null);
Assert.That(projection.PlayableWorld!.InputProfile, Is.EqualTo("arpg-third-person"));
Assert.That(projection.PlayableWorld.EntityCount, Is.EqualTo(3));
var moveIntent = session.CreateMoveIntent(
"player-vanguard",
12f,
0f,
8f,
DateTimeOffset.Parse("2026-07-09T00:00:00Z"));
Assert.That(moveIntent.Schema, Is.EqualTo(EveSurfaceCommandRequest.SchemaId));
Assert.That(moveIntent.ProviderId, Is.EqualTo("aetheria"));
Assert.That(moveIntent.SurfaceId, Is.EqualTo("aetheria.daemon.game"));
Assert.That(moveIntent.ClientId, Is.EqualTo("unity-scene"));
Assert.That(moveIntent.Command, Is.EqualTo("aetheria.daemon.commands"));
Assert.That(moveIntent.CommandBoundary, Is.EqualTo("aetheria.daemon.commands"));
Assert.That(moveIntent.ReceiptSchema, Is.EqualTo("aetheria.eve_command_acceptance_status.v1"));
var focusIntent = session.CreateFocusIntent("anchor-station");
Assert.That(focusIntent.Command, Is.EqualTo("aetheria.daemon.commands"));
Assert.That(focusIntent.CommandBoundary, Is.EqualTo("aetheria.daemon.commands"));
}
[Test]
public void SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState()
{

View file

@ -16,6 +16,7 @@
"supportedFeatures": [
"providerAdvertisements",
"commandTransport",
"providerSurfaceSession",
"sceneGraphProjection",
"playableWorldProjection",
"embeddedDocuments"
@ -59,6 +60,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/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/TeXMathUnitySceneProjectionAdapter.cs",
@ -105,6 +107,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/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/TeXMathUnitySceneProjectionAdapter.cs",
@ -140,6 +143,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/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/TeXMathUnitySceneProjectionAdapter.cs",
@ -150,7 +154,8 @@
"scripts/run-eveunity-scene-provider-shell-smoke.ps1"
],
"pendingProofs": [
"Unity scene provider-advertisement smoke runs from EveUnity with real Unity scene/frame objects and no Aetheria imports."
"Unity scene provider-advertisement smoke runs from EveUnity with real Unity scene/frame objects and no Aetheria imports.",
"Live CultMesh/CultNet provider subscription adapter feeds EveUnitySceneClientSession snapshots instead of Eve-local fixture documents."
]
},
"capture": {

View file

@ -16,6 +16,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/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/TeXMathUnitySceneProjectionAdapter.cs",
@ -32,6 +33,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/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/GameCult.Eve.UnityScene.Tests.asmdef",
"tools/eveunity/eveunity-release-contract.mjs",
"tools/eveunity/eveunity-release-contract.test.mjs",
@ -48,6 +50,7 @@
"stage": "world-surface-lowering",
"currentPaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/TeXMathUnitySceneProjectionAdapter.cs",
@ -55,7 +58,7 @@
"runtimes/incubating/eve-unity-scene/eve-runtime-capability.json"
],
"destinationOwner": "EveUnity",
"replacementProof": "EveUnity claims the provider-advertised unity-scene lowering target with provider-agnostic playable-world projection, scene graph projection, and command boundary evidence; live transport and capture remain separate lifecycle proofs."
"replacementProof": "EveUnity claims the provider-advertised unity-scene lowering target with provider-agnostic playable-world projection, scene graph projection, provider snapshot session, and command boundary evidence; live transport and capture remain separate lifecycle proofs."
},
{
"id": "unity-scene-sai-plugin-projection",
@ -98,11 +101,12 @@
"stage": "command",
"currentPaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"runtimes/incubating/eve-unity-scene/eve-runtime-capability.json"
],
"destinationOwner": "EveUnity",
"replacementProof": "Unity scene input emits gamecult.eve.command.v1 intents through provider-advertised command boundaries and renders provider receipts instead of mutating local world truth."
"replacementProof": "Unity scene input emits gamecult.eve.command.v1 intents through a provider-snapshot client session and advertised command boundaries, then renders provider receipts instead of mutating local world truth."
},
{
"id": "unity-scene-capture-lifecycle",
@ -140,6 +144,7 @@
"EveUnity publishes a Unity scene runtime capability manifest.",
"EveUnity builds the provider-agnostic Unity scene UPM package artifact.",
"EveUnity owns a provider-agnostic scene graph lowerer that consumes advertised worldInteraction boundaries without importing Aetheria internals.",
"EveUnity owns a provider-snapshot Unity scene client session that lowers Aetheria's surface and emits command intents without importing Aetheria project code.",
"EveUnity owns the provider-agnostic playable-world scene lowerer outside Eve incubation.",
"EveUnity owns the Unity scene Sai projection adapter outside Eve incubation without importing Sai story state or VN/Ink internals.",
"EveUnity owns the Unity scene Norn projection adapter outside Eve incubation without importing Norn implementation state.",

View file

@ -39,7 +39,7 @@ if ($manifest.incubation.splitHandoff.manifestPath -ne "runtimes/incubating/eve-
throw "EveUnity scene manifest missing split handoff path"
}
foreach ($feature in @("providerAdvertisements", "commandTransport", "sceneGraphProjection", "playableWorldProjection", "embeddedDocuments")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "providerSurfaceSession", "sceneGraphProjection", "playableWorldProjection", "embeddedDocuments")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveUnity scene manifest missing provider-shell feature: $feature"
}

View file

@ -54,7 +54,7 @@ foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) {
}
}
foreach ($feature in @("providerAdvertisements", "commandTransport", "sceneGraphProjection", "playableWorldProjection")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "providerSurfaceSession", "sceneGraphProjection", "playableWorldProjection")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveUnity scene provider shell missing supported feature: $feature"
}
@ -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\EveUnitySceneClientSession.cs",
"runtimes\incubating\eve-unity-scene\Runtime\SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes\incubating\eve-unity-scene\Runtime\NornGraphUnitySceneProjectionAdapter.cs",
"runtimes\incubating\eve-unity-scene\Runtime\TeXMathUnitySceneProjectionAdapter.cs",
@ -85,6 +86,13 @@ foreach ($symbol in @("EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfa
}
}
$clientSessionSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Runtime\EveUnitySceneClientSession.cs") -Raw
foreach ($symbol in @("EveUnitySceneClientSession", "EveUnitySceneProviderSurfaceSnapshot", "Connect", "ApplySnapshot", "CreateMoveIntent", "CreateFocusIntent", "CreateTargetIntent", "CreateActionIntent", "CreatePlayableWorldIntent", "commandId", "targetPosition", "unity-scene")) {
if (-not $clientSessionSource.Contains($symbol)) {
throw "EveUnity scene client session missing symbol: $symbol"
}
}
$saiAdapterSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Runtime\SaiVisualNovelUnitySceneProjectionAdapter.cs") -Raw
foreach ($symbol in @("SaiVisualNovelUnitySceneProjectionAdapter", "sai.vn", "vn.stage", "story.choose", "story.continue", "story.jump", "gamecult.eve.plugin_abi.v1", "sidecar-advertised-plugin-abi", "Sai")) {
if (-not $saiAdapterSource.Contains($symbol)) {
@ -107,7 +115,7 @@ foreach ($symbol in @("TeXMathUnitySceneProjectionAdapter", "tex.math", "embed.t
}
$testSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Tests\Editor\EveUnitySceneSurfaceLowererTests.cs") -Raw
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "GenericClientSessionConsumesAetheriaPlayableWorldSnapshotWithoutAetheriaTypes", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "cultmesh://aetheria/eve/surfaces/aetheria.daemon.game", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "sai.vn", "norn.graph", "tex.math", "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

@ -64,6 +64,7 @@ node $consumerScript $consumerExport `
--expect-runtime-feature unity-uitoolkit:embeddedDocuments `
--expect-runtime-feature unity-scene:providerAdvertisements `
--expect-runtime-feature unity-scene:commandTransport `
--expect-runtime-feature unity-scene:providerSurfaceSession `
--expect-runtime-feature unity-scene:sceneGraphProjection `
--expect-runtime-feature unity-scene:playableWorldProjection `
--expect-runtime-feature electron-shell:providerAdvertisements `

View file

@ -1040,7 +1040,7 @@
"splitHandoffPath": "runtimes/incubating/eve-unity-scene/eveunity-scene-split-handoff.json",
"requiredFixtures": ["aetheria-world", "eve-world-smoke"],
"pluginFixtures": ["sai-vn"],
"supportedFeatures": ["providerAdvertisements", "commandTransport", "sceneGraphProjection", "playableWorldProjection", "embeddedDocuments"],
"supportedFeatures": ["providerAdvertisements", "commandTransport", "providerSurfaceSession", "sceneGraphProjection", "playableWorldProjection", "embeddedDocuments"],
"supportedPlugins": [
{
"pluginId": "sai.vn",
@ -1068,6 +1068,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/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/TeXMathUnitySceneProjectionAdapter.cs",
@ -1081,6 +1082,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/EveUnitySceneClientSession.cs",
"runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/NornGraphUnitySceneProjectionAdapter.cs",
"runtimes/incubating/eve-unity-scene/Runtime/TeXMathUnitySceneProjectionAdapter.cs",
@ -1108,6 +1110,10 @@
"path": "runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"contains": ["EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "BuildSceneGraph", "BuildPlayableWorld", "EveUnityPlayableWorldProjection", "EveUnityPlayableWorldEntity", "BuildEmbeddedDocumentSlots", "BuildPluginProjection", "SaiVisualNovelUnitySceneProjectionAdapter", "TeXMathUnitySceneProjectionAdapter", "EveUnitySceneEmbeddedDocumentSlot", "EveUnityScenePluginProjection", "EveUnitySceneNode", "SceneObjectKind", "playable-world-root", "unity-scene"]
},
{
"path": "runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneClientSession.cs",
"contains": ["EveUnitySceneClientSession", "EveUnitySceneProviderSurfaceSnapshot", "Connect", "ApplySnapshot", "CreateMoveIntent", "CreateFocusIntent", "CreateTargetIntent", "CreateActionIntent", "CreatePlayableWorldIntent", "commandId", "targetPosition", "unity-scene"]
},
{
"path": "runtimes/incubating/eve-unity-scene/Runtime/SaiVisualNovelUnitySceneProjectionAdapter.cs",
"contains": ["SaiVisualNovelUnitySceneProjectionAdapter", "sai.vn", "vn.stage", "story.choose", "story.continue", "story.jump", "gamecult.eve.plugin_abi.v1", "sidecar-advertised-plugin-abi", "Sai"]
@ -1122,7 +1128,7 @@
},
{
"path": "runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "norn.map", "cultmesh://aetheria/norn/map", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "LowerExtractsPlayableArpgWorldFromGenericScene3dSurface", "GenericClientSessionConsumesAetheriaPlayableWorldSnapshotWithoutAetheriaTypes", "SaiVisualNovelLowersThroughRuntimeProjectionAdapterWithoutOwningStoryState", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "playable-world-root", "playable-world-entity", "world-field-3d", "arpg-third-person", "cultmesh://aetheria/assets/manifest", "cultmesh://aetheria/eve/surfaces/aetheria.daemon.game", "aetheria.daemon.move_intent", "sai-vn-scene-stage", "norn-graph-scene-projection", "tex-math-scene-projection", "norn.map", "cultmesh://aetheria/norn/map", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
},
{
"path": "tools/eveunity/eveunity-capture-contract.test.mjs",