Add Unity scene graph lowering claim

This commit is contained in:
Meta Vens 2026-07-09 10:59:31 +01:00
commit 4861b61ad3
20 changed files with 317 additions and 79 deletions

View file

@ -294,8 +294,8 @@ Recently cut:
lower provider-owned world state without owning it. Parity compares those
claims against the ledger, exports them through runtime records and
`packs/runtime.json`, the runtime-owner smoke asserts them, and the generic
conformance smoke now reports the advertised but unclaimed `unity-scene`
lowering target as an explicit capability gap.
conformance smoke now treats `unity-scene` as a narrow Unity scene graph
command-surface claim while capture and release remain split blockers.
- Missing provider-advertised world-surface lowering targets are now assigned
to their pending runtime owner when one exists. `unity-scene` gaps point at
EveUnity's pending `unity-scene` runtime, and `tui` gaps point at EveTui's
@ -308,14 +308,14 @@ Recently cut:
- The conformance export also carries `worldSurfaceLoweringCoverage[]`, a full
provider-surface-to-target ledger that marks each advertised lowering target
as `claimed`, `missing-claim`, or `missing-runtime`. The generic conformance
consumer now asserts Aetheria's claimed web/UI Toolkit targets and missing
Unity scene/TUI targets from the same typed surface.
consumer now asserts Aetheria's claimed web, UI Toolkit, and Unity scene graph
targets plus the missing TUI targets from the same typed surface.
- The conformance export carries `commandBoundaryCoverage[]`, joining each
provider-owned interactive world surface target to its runtime owner,
provider command boundary, receipt schema, and runtime command envelope. Web
and Unity UI Toolkit are `covered` because they advertise
`gamecult.eve.command.v1`; Unity scene and TUI stay visible as
`missing-runtime-claim` until their generic lowerers exist.
Unity UI Toolkit, and Unity scene are `covered` because they advertise
`gamecult.eve.command.v1`; TUI stays visible as `missing-runtime-claim`
until its generic terminal lowerer exists.
- The browser reference lowerer now carries the active provider surface's
advertised `worldInteraction.commandBoundary` and
`worldInteraction.receiptSchema` into each `gamecult.eve.command.v1` intent.
@ -329,8 +329,10 @@ Recently cut:
- Unity scene now has a provider-shell contract skeleton under
`runtimes/incubating/eve-unity-scene`. The skeleton consumes an advertised
`worldInteraction` boundary, creates `gamecult.eve.command.v1` requests with
command boundary and receipt schema fields, and has a runnable smoke without
claiming full `unity-scene` world lowering or capture evidence.
command boundary and receipt schema fields, builds a provider-agnostic Unity
scene graph DTO from the surface tree, and claims only the `unity-scene`
graph command-surface target. It still does not own provider simulation,
plugin projection adapters, release, or capture evidence.
- EveElectron now has a provider-shell contract skeleton under
`runtimes/incubating/eve-electron`. The shell selects advertised provider
surfaces, emits `gamecult.eve.command.v1` intents with provider command
@ -346,8 +348,9 @@ Recently cut:
split handoff move sets to source path status. EveElectron now exposes the
existing Aetheria `Aetheria.Rts.Web/Electron` and command transport paths as
`observed-provider` sources that must be replaced by a provider-agnostic
shell; Unity scene exposes `replacement-required` move sets because no
generic scene body or command transport source exists yet.
shell; Unity scene now exposes current incubation paths for its generic scene
graph body, world-surface lowering claim, and command transport, while scene
capture remains replacement-required.
- The conformance export schema and consumer smoke now require minimum typed
item shapes for plugins, providers, runtimes, and split targets. Owner repos
can rely on exported ids, owners, statuses, split targets, manifest or
@ -393,22 +396,23 @@ Recently cut:
`runtimes/incubating/eve-unity-scene/eveunity-scene-split-handoff.json`.
The active `unity-uitoolkit` runtime remains a semantic UI surface lowerer;
it is not treated as full scene/world projection. The pending `unity-scene`
runtime keeps the missing provider-agnostic scene body, command transport,
scene capture, and advertised `unity-scene` lowering proof visible as
EveUnity blockers.
runtime now names current scene graph and command-transport source paths,
while release, capture, non-Aetheria provider proof, and runtime graduation
remain EveUnity blockers.
- Unity scene now has a pending runtime capability manifest at
`runtimes/incubating/eve-unity-scene/eve-runtime-capability.json` and a
lifecycle smoke at `scripts/run-eveunity-scene-lifecycle-smoke.ps1`. The
manifest does not claim a scene lowerer yet; it types the package release,
provider-advertisement scene smoke, command boundary, and scene capture
contracts so EveUnity can consume the gap without importing Aetheria product
code or pretending UI Toolkit is full world projection.
manifest claims a provider-agnostic scene graph command surface for
`unity-scene`, types the package release, provider-advertisement scene smoke,
command boundary, and scene capture contracts, and keeps plugin projection
adapters unsupported until Sai, Norn, or TeX sidecar projection support exists
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 owns no current Eve source paths, does not treat Aetheria
product paths as generic runtime source, names the required Eve contracts,
and keeps the scene body, command transport, lowering claim, and capture as
external proofs until EveUnity owns them.
scene runtime's current source paths for runtime body, scene graph lowering,
and command transport, does not treat Aetheria product paths as generic
runtime source, names the required Eve contracts, and keeps capture as an
external proof until EveUnity owns it.
- EveElectron now has a pending split target and handoff at
`runtimes/incubating/eve-electron/eveelectron-split-handoff.json`. It does
not claim an Electron runtime body yet. The handoff draws the line between a

View file

@ -307,8 +307,9 @@ pending: Aetheria advertises `tui` as an agent-facing lowering target, but Eve
should not claim that target until a real terminal/grid lowerer and transcript
capture exist. EveUnity includes both the active `unity-uitoolkit` package proof
and the pending `unity-scene` runtime boundary; UI Toolkit support is not
treated as full Unity scene/world lowering, and `unity-scene` move sets remain
`replacement-required` until a generic scene body exists.
treated as full Unity scene/world lowering. The `unity-scene` runtime now claims
a narrow scene graph command surface, while capture, release, and plugin
projection adapters remain explicit blockers.
The Flutter widget smoke also exercises `EveProviderCatalog` and
`EveProviderPicker` against a conformance-export-shaped provider list. That is

View file

@ -5,6 +5,8 @@
"ownerRepo": "Norn",
"contract": "gamecult.eve.plugin_abi.v1",
"sourceFixture": "sai-vn",
"sourceFixtureRole": "optional-nested-placement-evidence",
"authority": "Norn owns graph semantics independently; the Sai fixture only proves a provider surface can nest embed.norn when norn.graph is available.",
"operations": [
{
"operation": "describe",

View file

@ -26,7 +26,7 @@
"web/fixtures/sai-vn-surface.json",
"web/fixtures/sai-vn-surface.conformance.json"
],
"replacementProof": "Norn owns embed.norn layout, interaction, fallback, and ABI conformance cases."
"replacementProof": "Norn owns embed.norn layout, interaction, fallback, and ABI conformance cases; the Sai fixture is only optional nested placement evidence."
}
],
"contractInputs": [
@ -38,7 +38,7 @@
],
"forbiddenImports": [
"Aetheria provider state",
"Sai story session internals",
"Sai story session internals or VN command authority",
"renderer-native projection internals",
"provider command acceptance or receipt authority"
],

View file

@ -53,7 +53,9 @@
{
"fixtureId": "sai-vn",
"schema": "gamecult.eve.surface.v1",
"path": "web/fixtures/sai-vn-surface.json"
"path": "web/fixtures/sai-vn-surface.json",
"role": "optional-nested-placement-evidence",
"authority": "Norn semantics remain plugin-owned; the Sai fixture only proves a surface can nest embed.norn when norn.graph is available."
}
],
"abiFixtures": [

View file

@ -5,6 +5,8 @@
"ownerRepo": "EvePlugins",
"contract": "gamecult.eve.plugin_abi.v1",
"sourceFixture": "sai-vn",
"sourceFixtureRole": "optional-nested-placement-evidence",
"authority": "EvePlugins owns TeX semantics independently; the Sai fixture only proves a provider surface can nest embed.tex when tex.math is available.",
"operations": [
{
"operation": "describe",

View file

@ -26,7 +26,7 @@
"web/fixtures/sai-vn-surface.json",
"web/fixtures/sai-vn-surface.conformance.json"
],
"replacementProof": "EvePlugins owns embed.tex source, macro, measurement, render result, fallback, and ABI conformance cases."
"replacementProof": "EvePlugins owns embed.tex source, macro, measurement, render result, fallback, and ABI conformance cases; the Sai fixture is only optional nested placement evidence."
}
],
"contractInputs": [
@ -38,7 +38,7 @@
],
"forbiddenImports": [
"Aetheria provider state",
"Sai story session internals",
"Sai story session internals or VN command authority",
"Norn graph semantics",
"renderer-native projection internals",
"provider command acceptance or receipt authority"

View file

@ -42,7 +42,9 @@
{
"fixtureId": "sai-vn",
"schema": "gamecult.eve.surface.v1",
"path": "web/fixtures/sai-vn-surface.json"
"path": "web/fixtures/sai-vn-surface.json",
"role": "optional-nested-placement-evidence",
"authority": "TeX semantics remain plugin-owned; the Sai fixture only proves a surface can nest embed.tex when tex.math is available."
}
],
"abiFixtures": [

View file

@ -27,7 +27,8 @@ namespace GameCult.Eve.UnityScene
advertisedSurface.WorldInteraction.ProjectionKind,
advertisedSurface.WorldInteraction.CommandBoundary,
advertisedSurface.WorldInteraction.ReceiptSchema,
advertisedSurface.WorldInteraction.Ownership);
advertisedSurface.WorldInteraction.Ownership,
BuildSceneGraph(document.Surface.Root));
}
public EveSurfaceCommandRequest CreateCommandIntent(
@ -65,6 +66,43 @@ namespace GameCult.Eve.UnityScene
return CultMesh.OperationInvocation(command);
}
private static EveUnitySceneNode BuildSceneGraph(EveSurfaceComponent component)
{
var children = new List<EveUnitySceneNode>(component.Children.Count);
foreach (var child in component.Children)
{
children.Add(BuildSceneGraph(child));
}
return new EveUnitySceneNode(
component.Id,
component.Kind,
SceneObjectKind(component.Kind),
component.Props,
component.Layout,
component.Style,
component.StateBindings.Count,
component.EmbeddedDocuments.Count,
children);
}
private static string SceneObjectKind(string componentKind)
{
if (string.IsNullOrWhiteSpace(componentKind))
return "empty";
if (componentKind.StartsWith("control.", StringComparison.Ordinal))
return "command-control";
if (componentKind.StartsWith("embed.", StringComparison.Ordinal))
return "plugin-placeholder";
if (string.Equals(componentKind, "surface.slot", StringComparison.Ordinal))
return "embedded-surface-slot";
if (componentKind.StartsWith("world.", StringComparison.Ordinal))
return "world-projection-node";
if (componentKind.StartsWith("text.", StringComparison.Ordinal) || string.Equals(componentKind, "label", StringComparison.Ordinal))
return "scene-label";
return "scene-node";
}
}
public sealed class EveUnitySceneProjection
@ -75,7 +113,8 @@ namespace GameCult.Eve.UnityScene
string projectionKind,
string commandBoundary,
string receiptSchema,
string ownership)
string ownership,
EveUnitySceneNode root)
{
ProviderId = providerId ?? "";
SurfaceId = surfaceId ?? "";
@ -83,6 +122,7 @@ namespace GameCult.Eve.UnityScene
CommandBoundary = commandBoundary ?? "";
ReceiptSchema = receiptSchema ?? "";
Ownership = ownership ?? "";
Root = root ?? throw new ArgumentNullException(nameof(root));
}
public string ProviderId { get; }
@ -96,6 +136,51 @@ namespace GameCult.Eve.UnityScene
public string ReceiptSchema { get; }
public string Ownership { get; }
public EveUnitySceneNode Root { get; }
}
public sealed class EveUnitySceneNode
{
public EveUnitySceneNode(
string id,
string componentKind,
string sceneObjectKind,
IReadOnlyDictionary<string, string> props,
IReadOnlyDictionary<string, string> layout,
IReadOnlyDictionary<string, string> style,
int stateBindingCount,
int embeddedDocumentCount,
IReadOnlyList<EveUnitySceneNode> children)
{
Id = id ?? "";
ComponentKind = componentKind ?? "";
SceneObjectKind = sceneObjectKind ?? "";
Props = props ?? new Dictionary<string, string>(StringComparer.Ordinal);
Layout = layout ?? new Dictionary<string, string>(StringComparer.Ordinal);
Style = style ?? new Dictionary<string, string>(StringComparer.Ordinal);
StateBindingCount = stateBindingCount;
EmbeddedDocumentCount = embeddedDocumentCount;
Children = children ?? Array.Empty<EveUnitySceneNode>();
}
public string Id { get; }
public string ComponentKind { get; }
public string SceneObjectKind { get; }
public IReadOnlyDictionary<string, string> Props { get; }
public IReadOnlyDictionary<string, string> Layout { get; }
public IReadOnlyDictionary<string, string> Style { get; }
public int StateBindingCount { get; }
public int EmbeddedDocumentCount { get; }
public IReadOnlyList<EveUnitySceneNode> Children { get; }
}
public sealed class EveUnitySceneProviderSurfaceAdvertisement

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using GameCult.Eve.Surface;
using GameCult.Mesh;
using NUnit.Framework;
#nullable enable
@ -21,6 +22,24 @@ namespace GameCult.Eve.UnityScene.Tests
Assert.That(projection.CommandBoundary, Is.EqualTo("aetheria.daemon.commands"));
Assert.That(projection.ReceiptSchema, Is.EqualTo("aetheria.eve_command_acceptance_status.v1"));
Assert.That(projection.Ownership, Is.EqualTo("provider-owns-world-state-assets-command-acceptance-and-receipts"));
Assert.That(projection.Root.Id, Is.EqualTo("aetheria.daemon.game.root"));
Assert.That(projection.Root.SceneObjectKind, Is.EqualTo("scene-node"));
}
[Test]
public void LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree()
{
var lowerer = new EveUnitySceneSurfaceLowerer();
var projection = lowerer.Lower(Document("aetheria.daemon.game"), Advertisement("aetheria.daemon.game"));
Assert.That(projection.Root.Children.Count, Is.EqualTo(3));
Assert.That(projection.Root.Children[0].SceneObjectKind, Is.EqualTo("world-projection-node"));
Assert.That(projection.Root.Children[0].Props["binding"], Is.EqualTo("cultmesh://aetheria/world/entities"));
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));
}
[Test]
@ -60,7 +79,43 @@ namespace GameCult.Eve.UnityScene.Tests
$"{surfaceId}.root",
"surface",
new Dictionary<string, string>(StringComparer.Ordinal),
Array.Empty<EveSurfaceComponent>()),
new[]
{
new EveSurfaceComponent(
$"{surfaceId}.entities",
"world.entities",
new Dictionary<string, string>(StringComparer.Ordinal)
{
["binding"] = "cultmesh://aetheria/world/entities"
},
Array.Empty<EveSurfaceComponent>(),
new[]
{
new CultMeshStateBindingDescriptor("entities", "cultmesh://aetheria/world/entities")
}),
new EveSurfaceComponent(
$"{surfaceId}.focus",
"control.button",
new Dictionary<string, string>(StringComparer.Ordinal)
{
["command"] = "aetheria.daemon.focus"
},
Array.Empty<EveSurfaceComponent>()),
new EveSurfaceComponent(
$"{surfaceId}.norn",
"embed.norn",
new Dictionary<string, string>(StringComparer.Ordinal),
Array.Empty<EveSurfaceComponent>(),
Array.Empty<CultMeshStateBindingDescriptor>(),
new[]
{
new EveEmbeddedDocumentSlot(
"norn.map",
"cultmesh://aetheria/norn/map",
"gamecult.eve.surface.v1",
"scene-overlay")
})
}),
Array.Empty<EveStyleToken>()),
Array.Empty<EveCommandTemplate>());
}

View file

@ -15,27 +15,42 @@
},
"supportedFeatures": [
"providerAdvertisements",
"commandTransport"
"commandTransport",
"sceneGraphProjection"
],
"supportedPlugins": [],
"unsupportedPlugins": [
{
"pluginId": "sai.vn",
"reason": "Unity scene has no generic runtime body yet; Sai projection must enter through provider/plugin advertisements once scene lowering exists."
"reason": "Unity scene graph projection exists, but no Sai VN scene projection adapter or sidecar bridge exists in this runtime."
},
{
"pluginId": "norn.graph",
"reason": "Unity scene has no generic runtime body yet; Norn graph projection needs explicit scene-space or UI overlay semantics once scene lowering exists."
"reason": "Unity scene graph projection exists, but no Norn graph scene-space or UI overlay adapter exists in this runtime."
},
{
"pluginId": "tex.math",
"reason": "Unity scene has no generic runtime body yet; TeX projection needs explicit scene-space or UI overlay semantics once scene lowering exists."
"reason": "Unity scene graph projection exists, but no TeX scene-space or UI overlay adapter exists in this runtime."
}
],
"worldSurfaceLowering": [
{
"targetId": "unity-scene",
"surfaceKinds": ["interactive-world"],
"projectionKinds": ["provider-authored-world-surface"],
"supportLevel": "unity-scene-graph-command-surface",
"ownership": "runtime-lowers-provider-world-surface-without-owning-world-state",
"evidencePaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"web/fixtures/aetheria.provider-advertisement.json"
]
}
],
"commandTransport": {
"schema": "gamecult.eve.command.v1",
"status": "provider-shell-contract-skeleton",
"emitter": "EveUnitySceneSurfaceLowerer.EmitCommand",
"emitter": "EveUnitySceneSurfaceLowerer.CreateCommandIntent",
"clientId": "unity-scene",
"authority": "Unity scene input emits command intents through provider-advertised command boundaries; providers accept, deny, and publish receipts."
},
@ -115,6 +130,6 @@
},
"capture": {
"status": "missing",
"note": "Unity scene capture is a split blocker until EveUnity owns a provider-agnostic scene lowerer."
"note": "Unity scene capture is a split blocker until EveUnity attaches provider-agnostic scene frame artifacts."
}
}

View file

@ -25,14 +25,22 @@
{
"id": "unity-scene-world-surface-lowering",
"stage": "world-surface-lowering",
"currentPaths": [],
"currentPaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"runtimes/incubating/eve-unity-scene/eve-runtime-capability.json"
],
"destinationOwner": "EveUnity",
"replacementProof": "EveUnity claims the provider-advertised unity-scene lowering target with scene projection evidence, command boundary evidence, and capture artifacts."
"replacementProof": "EveUnity claims the provider-advertised unity-scene lowering target with provider-agnostic scene graph projection and command boundary evidence; capture remains a separate lifecycle proof."
},
{
"id": "unity-scene-command-transport",
"stage": "command",
"currentPaths": [],
"currentPaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.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."
},
@ -60,8 +68,8 @@
],
"requiredExternalProofs": [
"EveUnity publishes a Unity scene runtime capability manifest.",
"EveUnity owns a provider-shell contract skeleton that consumes advertised worldInteraction boundaries without importing Aetheria internals.",
"EveUnity claims the unity-scene world-surface lowering target only after a real provider-agnostic scene lowerer exists.",
"EveUnity owns a provider-agnostic scene graph lowerer that consumes advertised worldInteraction boundaries without importing Aetheria internals.",
"EveUnity owns the provider-agnostic scene graph lowerer outside Eve incubation.",
"EveUnity lowers at least one non-Aetheria provider-authored world surface into Unity scene objects.",
"EveUnity lowers Aetheria's game world surface through provider advertisements without importing Aetheria internals.",
"Unity scene input emits gamecult.eve.command.v1 intents and renders provider receipts.",

View file

@ -58,17 +58,16 @@ try {
--expect-interactive-world-surface aetheria:aetheria.daemon.editor:unity-uitoolkit:Aetheria `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:web-reference:claimed:Eve:web `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-uitoolkit:claimed:EveUnity:unity-uitoolkit `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-scene:missing-claim:EveUnity:unity-scene `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-scene:claimed:EveUnity:unity-scene `
--expect-world-lowering-coverage aetheria:aetheria.daemon.editor:web-reference:claimed:Eve:web `
--expect-world-lowering-coverage aetheria:aetheria.daemon.editor:unity-uitoolkit:claimed:EveUnity:unity-uitoolkit `
--expect-world-lowering-coverage aetheria:aetheria.daemon.editor:tui:missing-claim:EveTui:tui `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:web-reference:covered:Eve:web `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-uitoolkit:covered:EveUnity:unity-uitoolkit `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-scene:missing-runtime-claim:EveUnity:unity-scene `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-scene:covered:EveUnity:unity-scene `
--expect-command-boundary-coverage aetheria:aetheria.daemon.editor:web-reference:covered:Eve:web `
--expect-command-boundary-coverage aetheria:aetheria.daemon.editor:unity-uitoolkit:covered:EveUnity:unity-uitoolkit `
--expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:missing-runtime-claim:EveTui:tui `
--expect-world-lowering-gap aetheria:aetheria.daemon.game:unity-scene:EveUnity:unity-scene `
--expect-world-lowering-gap aetheria:aetheria.daemon.editor:tui:EveTui:tui `
--expect-split-handoff-move EveTui:tui:tui-runtime-body:current:exists:eve-tui-shell.mjs `
--expect-split-handoff-move EveTui:tui:tui-command-transport:current:exists:eve-tui-shell.mjs `
@ -76,7 +75,8 @@ try {
--expect-split-target-blocker "EveElectron:Electron shell runtime body graduates to EveElectron outside Aetheria product code" `
--expect-split-target-blocker "EveTui:TUI runtime body graduates to EveTui outside provider product code" `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-runtime-body:current:exists:EveUnitySceneSurfaceLowerer.cs `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-command-transport:replacement-required:no-source-paths:none `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-world-surface-lowering:current:exists:EveUnitySceneSurfaceLowerer.cs `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-command-transport:current:exists:EveUnitySceneSurfaceLowerer.cs `
--expect-split-handoff-move EveElectron:electron-shell:electron-shell-runtime:current:exists:eve-electron-shell.mjs `
--expect-split-handoff-move EveElectron:electron-shell:electron-command-transport:current:exists:eve-electron-shell.mjs `
--expect-split-handoff-move EveElectron:electron-shell:electron-shell-runtime:observed-provider:exists:Aetheria.Rts.Web/Electron `

View file

@ -33,17 +33,15 @@ try {
node .\tools\conformance\consume-export.mjs $consumerExport `
--expect-capability-matrix `
--expect-capability-gap runtime:Fensalir:direct2d:capture:missing `
--expect-capability-gap "runtime:EveUnity:unity-scene:provider:aetheria:surface:aetheria.daemon.game:world-lowering-target:unity-scene:missing-runtime" `
--expect-capability-gap "runtime:EveTui:tui:provider:aetheria:surface:aetheria.daemon.game:world-lowering-target:tui:missing-runtime" `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:web-reference:claimed:Eve:web `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-uitoolkit:claimed:EveUnity:unity-uitoolkit `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-scene:missing-claim:EveUnity:unity-scene `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-scene:claimed:EveUnity:unity-scene `
--expect-world-lowering-coverage aetheria:aetheria.daemon.editor:tui:missing-claim:EveTui:tui `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:web-reference:covered:Eve:web `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-uitoolkit:covered:EveUnity:unity-uitoolkit `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-scene:missing-runtime-claim:EveUnity:unity-scene `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-scene:covered:EveUnity:unity-scene `
--expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:missing-runtime-claim:EveTui:tui `
--expect-world-lowering-gap aetheria:aetheria.daemon.game:unity-scene:EveUnity:unity-scene `
--expect-world-lowering-gap aetheria:aetheria.daemon.game:tui:EveTui:tui `
--expect-world-lowering-gap aetheria:aetheria.daemon.editor:tui:EveTui:tui `
--expect-capability-gap "split-target:EveUnity:EveUnity:proof:Tagged UPM release" `

View file

@ -39,17 +39,36 @@ if ($manifest.incubation.splitHandoff.manifestPath -ne "runtimes/incubating/eve-
throw "EveUnity scene manifest missing split handoff path"
}
foreach ($feature in @("providerAdvertisements", "commandTransport")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "sceneGraphProjection")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveUnity scene manifest missing provider-shell feature: $feature"
}
}
if (@($manifest.supportedPlugins).Count -ne 0) {
throw "EveUnity scene must not claim plugin projection before the generic scene lowerer exists"
throw "EveUnity scene must not claim plugin projection before runtime adapters or sidecar bridges exist"
}
$worldSurfaceLoweringClaims = if ($null -eq $manifest.worldSurfaceLowering) { @() } else { @($manifest.worldSurfaceLowering) }
if ($worldSurfaceLoweringClaims.Count -ne 0) {
throw "EveUnity scene must not claim world-surface lowering before real scene projection evidence exists"
$worldSurfaceLoweringClaims = @()
if ($null -ne $manifest.worldSurfaceLowering) {
$worldSurfaceLoweringClaims = @($manifest.worldSurfaceLowering)
}
if ($worldSurfaceLoweringClaims.Count -ne 1) {
throw "EveUnity scene must claim exactly one world-surface lowering target"
}
$worldSurfaceLoweringClaim = $worldSurfaceLoweringClaims | Where-Object { $_.targetId -eq "unity-scene" } | Select-Object -First 1
if (-not $worldSurfaceLoweringClaim) {
throw "EveUnity scene manifest missing unity-scene world-surface lowering claim"
}
if ($worldSurfaceLoweringClaim.supportLevel -ne "unity-scene-graph-command-surface") {
throw "Unexpected EveUnity scene world-surface support level: $($worldSurfaceLoweringClaim.supportLevel)"
}
if ($worldSurfaceLoweringClaim.ownership -ne "runtime-lowers-provider-world-surface-without-owning-world-state") {
throw "Unexpected EveUnity scene world-surface ownership: $($worldSurfaceLoweringClaim.ownership)"
}
foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) {
$absoluteEvidencePath = Join-Path $projectRoot $evidencePath
if (-not (Test-Path -LiteralPath $absoluteEvidencePath)) {
throw "EveUnity scene world-surface claim missing evidence path: $evidencePath"
}
}
foreach ($pluginId in @("sai.vn", "norn.graph", "tex.math")) {

View file

@ -24,12 +24,37 @@ if ($manifest.lifecycle.test.status -ne "provider-shell-contract-skeleton") {
throw "Unexpected EveUnity scene provider shell status: $($manifest.lifecycle.test.status)"
}
$worldSurfaceLoweringClaims = if ($null -eq $manifest.worldSurfaceLowering) { @() } else { @($manifest.worldSurfaceLowering) }
if ($worldSurfaceLoweringClaims.Count -ne 0) {
throw "EveUnity scene must not claim provider world-surface lowering until real scene projection and capture evidence exist"
$worldSurfaceLoweringClaims = @()
if ($null -ne $manifest.worldSurfaceLowering) {
$worldSurfaceLoweringClaims = @($manifest.worldSurfaceLowering)
}
if ($worldSurfaceLoweringClaims.Count -ne 1) {
throw "EveUnity scene must claim exactly one provider world-surface lowering target"
}
$worldSurfaceLoweringClaim = $worldSurfaceLoweringClaims | Where-Object { $_.targetId -eq "unity-scene" } | Select-Object -First 1
if (-not $worldSurfaceLoweringClaim) {
throw "EveUnity scene missing unity-scene world-surface lowering claim"
}
if (-not (@($worldSurfaceLoweringClaim.surfaceKinds) -contains "interactive-world")) {
throw "EveUnity scene world-surface claim must support interactive-world surfaces"
}
if (-not (@($worldSurfaceLoweringClaim.projectionKinds) -contains "provider-authored-world-surface")) {
throw "EveUnity scene world-surface claim must support provider-authored-world-surface projections"
}
if ($worldSurfaceLoweringClaim.supportLevel -ne "unity-scene-graph-command-surface") {
throw "Unexpected EveUnity scene support level: $($worldSurfaceLoweringClaim.supportLevel)"
}
if ($worldSurfaceLoweringClaim.ownership -ne "runtime-lowers-provider-world-surface-without-owning-world-state") {
throw "Unexpected EveUnity scene ownership: $($worldSurfaceLoweringClaim.ownership)"
}
foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) {
$absoluteEvidencePath = Join-Path $projectRoot $evidencePath
if (-not (Test-Path -LiteralPath $absoluteEvidencePath)) {
throw "EveUnity scene world-surface claim missing evidence path: $evidencePath"
}
}
foreach ($feature in @("providerAdvertisements", "commandTransport")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "sceneGraphProjection")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveUnity scene provider shell missing supported feature: $feature"
}
@ -51,14 +76,14 @@ 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", "unity-scene")) {
foreach ($symbol in @("EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "BuildSceneGraph", "EveUnitySceneNode", "SceneObjectKind", "unity-scene")) {
if (-not $lowererSource.Contains($symbol)) {
throw "EveUnity scene provider shell lowerer missing symbol: $symbol"
}
}
$testSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-unity-scene\Tests\Editor\EveUnitySceneSurfaceLowererTests.cs") -Raw
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
foreach ($symbol in @("LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "plugin-placeholder", "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

@ -65,14 +65,14 @@ foreach ($id in $expectedMoveSets.Keys) {
}
$currentPaths = if ($null -eq $moveSet.currentPaths) { @() } else { @($moveSet.currentPaths) }
$observedProviderPaths = if ($null -eq $moveSet.observedProviderPaths) { @() } else { @($moveSet.observedProviderPaths) }
if ($id -eq "unity-scene-runtime-body") {
if ($id -in @("unity-scene-runtime-body", "unity-scene-world-surface-lowering", "unity-scene-command-transport")) {
if ($currentPaths.Count -eq 0) {
throw "EveUnity scene split handoff runtime body must name the provider-shell skeleton paths"
throw "EveUnity scene split handoff move set $id must name current Eve incubation paths"
}
foreach ($relativePath in $currentPaths) {
$absolutePath = Join-Path $projectRoot $relativePath
if (-not (Test-Path -LiteralPath $absolutePath)) {
throw "EveUnity scene split handoff runtime body path missing: $relativePath"
throw "EveUnity scene split handoff move set $id path missing: $relativePath"
}
}
} elseif ($currentPaths.Count -ne 0) {

View file

@ -55,6 +55,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:sceneGraphProjection `
--expect-runtime-feature electron-shell:providerAdvertisements `
--expect-runtime-feature electron-shell:commandTransport `
--expect-runtime-feature tui:providerAdvertisements `
@ -67,6 +68,9 @@ node $consumerScript $consumerExport `
--expect-runtime-world-target unity-uitoolkit:unity-uitoolkit `
--expect-runtime-world-field unity-uitoolkit:unity-uitoolkit:supportLevel:ui-toolkit-semantic-command-surface `
--expect-runtime-world-field unity-uitoolkit:unity-uitoolkit:ownership:runtime-lowers-provider-world-surface-without-owning-world-state `
--expect-runtime-world-target unity-scene:unity-scene `
--expect-runtime-world-field unity-scene:unity-scene:supportLevel:unity-scene-graph-command-surface `
--expect-runtime-world-field unity-scene:unity-scene:ownership:runtime-lowers-provider-world-surface-without-owning-world-state `
--expect-runtime-plugin-projection unity-uitoolkit:sai.vn:supported:EveUnity `
--expect-runtime-plugin-projection unity-uitoolkit:norn.graph:supported:EveUnity `
--expect-runtime-plugin-projection unity-uitoolkit:tex.math:unsupported:EveUnity `
@ -82,6 +86,7 @@ node $consumerScript $consumerExport `
--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 `
--expect-runtime-handoff unity-uitoolkit `

View file

@ -48,7 +48,8 @@ try {
--expect-split-target-blocker-record EveUnity:runtime-plugin-projection:unity-scene:sai.vn `
--expect-split-target-blocker-record "EveUnity:pending-proof:Unity scene runtime body graduates to EveUnity outside Aetheria product code." `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-runtime-body:current:exists:EveUnitySceneSurfaceLowerer.cs `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-command-transport:replacement-required:no-source-paths:none `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-world-surface-lowering:current:exists:EveUnitySceneSurfaceLowerer.cs `
--expect-split-handoff-move EveUnity:unity-scene:unity-scene-command-transport:current:exists:EveUnitySceneSurfaceLowerer.cs `
--expect-split-target-blocker "EveUnity:Tagged UPM release" `
--expect-split-target-blocker "EveUnity:Unity batchmode EditMode runner" `
--expect-split-target-blocker "EveUnity:Unity batchmode or editor capture artifact" `

View file

@ -330,7 +330,7 @@
"graduationTrigger": "Move this advertisement-shaped VN fixture to Sai when sai-vn-plugin owns VN/Ink semantics and conformance packs.",
"schemaPath": "schemas/gamecult.eve.provider_advertisement.v1.schema.json",
"advertisementPath": "web/fixtures/sai-vn.provider-advertisement.json",
"requiredFixtures": ["sai-vn"],
"requiredFixtures": [],
"expectedSchemas": ["gamecult.eve.surface.v1", "gamecult.eve.command.v1", "sai.vn.story_session.v1"],
"expectedSurfaces": ["sai.visual_novel.surface"],
"expectedCommands": ["story.continue", "story.choose", "story.jump", "style.patch"]
@ -426,7 +426,7 @@
"stateAuthority": "proposes-plugin-state-only-provider-accepts"
}
},
"requiredFixtures": ["sai-vn"],
"requiredFixtures": [],
"schemaPath": "schemas/gamecult.eve.plugin.v1.schema.json",
"manifestPath": "plugins/incubating/norn-graph.plugin.json",
"abiFixturePath": "plugins/incubating/norn-graph.plugin-abi-fixture.json",
@ -465,7 +465,7 @@
"stateAuthority": "emits-render-results-only-provider-owns-source-state"
}
},
"requiredFixtures": ["sai-vn"],
"requiredFixtures": [],
"schemaPath": "schemas/gamecult.eve.plugin.v1.schema.json",
"manifestPath": "plugins/incubating/tex-math.plugin.json",
"abiFixturePath": "plugins/incubating/tex-math.plugin-abi-fixture.json",
@ -595,7 +595,7 @@
]
},
{
"description": "Unity scene provider-shell skeleton exists without claiming full world-surface lowering.",
"description": "Unity scene graph projection lowerer exists without claiming provider simulation, plugin projection, or capture ownership.",
"status": "passed",
"evidencePaths": [
"runtimes/incubating/eve-unity-scene/package.json",
@ -610,7 +610,7 @@
"Unity batchmode EditMode runner is owned by EveUnity rather than Eve incubation.",
"Unity batchmode or editor capture artifact is attached to the runtime conformance report.",
"Unity scene runtime body graduates to EveUnity outside Aetheria product code.",
"Unity scene claims provider-advertised unity-scene world-surface lowering with real scene capture evidence."
"Unity scene screenshot or frame-capture artifact is attached to the runtime conformance report."
]
},
{
@ -833,20 +833,34 @@
"splitHandoffPath": "runtimes/incubating/eve-unity-scene/eveunity-scene-split-handoff.json",
"requiredFixtures": ["aetheria-world"],
"pluginFixtures": [],
"supportedFeatures": ["providerAdvertisements", "commandTransport"],
"supportedFeatures": ["providerAdvertisements", "commandTransport", "sceneGraphProjection"],
"supportedPlugins": [],
"unsupportedPlugins": [
{
"pluginId": "sai.vn",
"reason": "Unity scene has no generic runtime body yet; Sai projection must enter through provider/plugin advertisements once scene lowering exists."
"reason": "Unity scene graph projection exists, but no Sai VN scene projection adapter or sidecar bridge exists in this runtime."
},
{
"pluginId": "norn.graph",
"reason": "Unity scene has no generic runtime body yet; Norn graph projection needs explicit scene-space or UI overlay semantics once scene lowering exists."
"reason": "Unity scene graph projection exists, but no Norn graph scene-space or UI overlay adapter exists in this runtime."
},
{
"pluginId": "tex.math",
"reason": "Unity scene has no generic runtime body yet; TeX projection needs explicit scene-space or UI overlay semantics once scene lowering exists."
"reason": "Unity scene graph projection exists, but no TeX scene-space or UI overlay adapter exists in this runtime."
}
],
"worldSurfaceLowering": [
{
"targetId": "unity-scene",
"surfaceKinds": ["interactive-world"],
"projectionKinds": ["provider-authored-world-surface"],
"supportLevel": "unity-scene-graph-command-surface",
"ownership": "runtime-lowers-provider-world-surface-without-owning-world-state",
"evidencePaths": [
"runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"web/fixtures/aetheria.provider-advertisement.json"
]
}
],
"expectedPaths": [
@ -863,16 +877,16 @@
"expectedSourceSymbols": [
{
"path": "runtimes/incubating/eve-unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs",
"contains": ["EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "unity-scene"]
"contains": ["EveUnitySceneSurfaceLowerer", "EveUnitySceneProviderSurfaceAdvertisement", "WorldInteraction", "CommandBoundary", "ReceiptSchema", "EveSurfaceCommandRequest", "BuildSceneGraph", "EveUnitySceneNode", "SceneObjectKind", "unity-scene"]
},
{
"path": "runtimes/incubating/eve-unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs",
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
"contains": ["LowerCarriesProviderAdvertisedWorldBoundary", "LowerBuildsProviderAgnosticSceneGraphFromSurfaceTree", "CommandIntentCarriesAdvertisedBoundaryWithoutOwningReceipts", "world-projection-node", "plugin-placeholder", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
}
],
"capture": {
"status": "missing",
"note": "Unity scene capture is a split blocker until EveUnity owns a provider-agnostic scene lowerer."
"note": "Unity scene capture is a split blocker until EveUnity attaches provider-agnostic scene frame artifacts."
}
},
{