Add Electron surface tree lowering claim

This commit is contained in:
Meta Vens 2026-07-09 11:04:29 +01:00
commit bdd103090c
16 changed files with 327 additions and 48 deletions

View file

@ -294,11 +294,11 @@ 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 treats `unity-scene` as a narrow Unity scene graph
command-surface claim while capture and release remain split blockers.
conformance smoke now treats `unity-scene` and `electron-shell` as narrow
runtime-owned command-surface claims 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
to their pending runtime owner when one exists. `tui` gaps point at EveTui's
pending `tui` runtime. Eve only owns a world-lowering gap when no runtime
target has been declared.
- The conformance export now carries `worldSurfaceLoweringGaps[]` as typed
@ -308,14 +308,15 @@ 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, and Unity scene graph
targets plus the missing TUI targets from the same typed surface.
consumer now asserts Aetheria's claimed web, UI Toolkit, Unity scene graph,
and Electron shell 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
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.
provider command boundary, receipt schema, and runtime command envelope. Web,
Unity UI Toolkit, Unity scene, and Electron shell 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.
@ -415,23 +416,25 @@ Recently cut:
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
future provider-agnostic Electron shell and Aetheria's Starbridge RTS product
client, and the split-target consumer smoke keeps the missing shell,
provider-advertisement consumption, command transport, and capture proofs
visible as blockers.
claim a provider-agnostic Electron shell surface-tree projection and command
surface, but not packaged rendering, embedded document rendering, plugin
projection, or capture. The handoff draws the line between the generic shell
and Aetheria's Starbridge RTS product client, and the split-target consumer
smoke keeps release, packaged rendering, embedded document rendering, and
capture proofs visible as blockers.
- EveElectron now has a direct split handoff smoke at
`scripts/run-eveelectron-split-handoff-smoke.ps1`. The smoke verifies the
observed Aetheria Electron/client paths that must be replaced, the required
Eve contract inputs, and the pending external proofs without treating
Aetheria's product client as the generic Electron runtime.
current generic shell, command, and world-surface lowering paths, the observed
Aetheria Electron/client paths that must be replaced, the required Eve
contract inputs, and the pending external proofs without treating Aetheria's
product client as the generic Electron runtime.
- EveElectron now has a pending runtime capability manifest at
`runtimes/incubating/eve-electron/eve-runtime-capability.json` and a
lifecycle smoke at `scripts/run-eveelectron-lifecycle-smoke.ps1`. The
manifest declares no supported runtime features or plugin projection yet; it
only types the pending command boundary, package release, provider-shell
smoke, and Electron window capture contracts so EveElectron can consume the
conformance export without pretending the generic shell already exists.
manifest declares provider advertisement consumption, command transport, and
surface-tree projection, claims `electron-shell` world/editor lowering, and
still keeps package release, packaged window rendering, plugin projection,
and Electron window capture as pending EveElectron work.
- Electron and TUI pending lifecycle details now live in their runtime
capability manifests rather than being duplicated in
`tools/parity/parity-manifest.json`. The parity ledger points at the
@ -717,8 +720,8 @@ Recently cut:
provider entry, and `aetheria-world-command-replay` scenario without reading
Eve's parity manifest or dirtying the Aetheria worktree.
- The Aetheria consumer smoke now also asserts frontend extraction boundaries:
web and Unity UI Toolkit are covered generic lowerings, Unity scene remains a
typed EveUnity gap, and the observed Aetheria Electron shell/client paths are
web, Unity UI Toolkit, Unity scene, and Electron shell are covered generic
lowerings, while the observed Aetheria Electron shell/client paths remain
split-handoff evidence to replace with a provider-agnostic EveElectron body.
- The parity harness now runs a conformance consumer smoke against a copied
`artifacts/conformance/latest` layout, proving the export can be consumed

View file

@ -302,7 +302,10 @@ Starbridge RTS client remains Aetheria-owned product code until a
provider-agnostic shell exists. The same smoke asserts that the Aetheria
Electron source paths named by the handoff currently exist as
`observed-provider` sources, so the extraction pressure is visible without
turning those paths into EveElectron authority. EveTui is also intentionally
turning those paths into EveElectron authority. The Electron runtime now claims
a narrow provider-advertised surface-tree command surface, while packaged
rendering, embedded document rendering, capture, and plugin projection remain
blockers. EveTui is also intentionally
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

View file

@ -148,8 +148,9 @@ The incubating Aetheria fixture advertises `aetheria.daemon.game` as
`interactive-world` with `worldInteraction.projectionKind:
provider-authored-world-surface`, `commandBoundary: aetheria.daemon.commands`,
and `receiptSchema: aetheria.eve_command_acceptance_status.v1`. Web, Unity UI
Toolkit, Unity scene, and TUI lowerers are lowering targets; Aetheria remains
the owner of world state, assets, command acceptance, and receipts.
Toolkit, Unity scene, Electron shell, and TUI lowerers are lowering targets;
Aetheria remains the owner of world state, assets, command acceptance, and
receipts.
## Non-Goals

View file

@ -15,7 +15,8 @@
},
"supportedFeatures": [
"providerAdvertisements",
"commandTransport"
"commandTransport",
"surfaceTreeProjection"
],
"supportedPlugins": [],
"unsupportedPlugins": [
@ -32,10 +33,24 @@
"reason": "Electron provider-shell skeleton exists, but no TeX projection adapter exists in this runtime."
}
],
"worldSurfaceLowering": [
{
"targetId": "electron-shell",
"surfaceKinds": ["interactive-world", "interactive-world-editor"],
"projectionKinds": ["provider-authored-world-surface", "provider-authored-world-editor-surface"],
"supportLevel": "electron-shell-surface-tree-command-surface",
"ownership": "runtime-lowers-provider-world-surface-without-owning-world-state",
"evidencePaths": [
"runtimes/incubating/eve-electron/src/eve-electron-shell.mjs",
"runtimes/incubating/eve-electron/test/eve-electron-shell.test.mjs",
"web/fixtures/aetheria.provider-advertisement.json"
]
}
],
"commandTransport": {
"schema": "gamecult.eve.command.v1",
"status": "provider-shell-contract-skeleton",
"emitter": "EveElectronShell.EmitCommand",
"emitter": "EveElectronShell.createCommandIntent",
"clientId": "electron-shell",
"authority": "Electron emits command intents through provider-advertised command boundaries; providers accept, deny, and publish receipts."
},
@ -112,6 +127,6 @@
},
"capture": {
"status": "missing",
"note": "Electron capture is a split blocker until EveElectron owns a provider-agnostic shell."
"note": "Electron capture is a split blocker until EveElectron attaches provider-agnostic shell window artifacts."
}
}

View file

@ -40,6 +40,20 @@
"destinationOwner": "EveElectron",
"replacementProof": "Electron emits gamecult.eve.command.v1 intents through the provider-advertised command boundary and receives provider receipts instead of mutating local product state."
},
{
"id": "electron-world-surface-lowering",
"stage": "world-surface-lowering",
"currentPaths": [
"runtimes/incubating/eve-electron/src/eve-electron-shell.mjs",
"runtimes/incubating/eve-electron/test/eve-electron-shell.test.mjs",
"runtimes/incubating/eve-electron/eve-runtime-capability.json"
],
"observedProviderPaths": [
"E:\\Projects\\Aetheria\\Aetheria.Rts.Web\\Client"
],
"destinationOwner": "EveElectron",
"replacementProof": "Electron claims provider-advertised world/editor surface targets with provider-agnostic surface-tree projection and command boundary evidence; packaged rendering and capture remain separate lifecycle proofs."
},
{
"id": "electron-capture-lifecycle",
"stage": "capture",
@ -65,7 +79,7 @@
],
"requiredExternalProofs": [
"EveElectron publishes a runtime capability manifest with provider advertisement consumption and command transport.",
"EveElectron owns a provider-shell contract skeleton that selects advertised provider surfaces and emits gamecult.eve.command.v1 intents.",
"EveElectron owns a provider-shell contract skeleton that selects advertised provider surfaces, projects Eve surface trees, and emits gamecult.eve.command.v1 intents.",
"EveElectron lowers at least one generic Eve provider surface that is not Aetheria.",
"EveElectron lowers Aetheria world/editor surfaces through provider advertisements without importing Aetheria internals.",
"Aetheria keeps Starbridge-specific UI, assets, authored flows, and receipts in the Aetheria repo.",

View file

@ -23,6 +23,26 @@ export class EveElectronShell {
};
}
lowerSurface(surfaceDocument, providerAdvertisement, requestedSurfaceId = "") {
const selected = this.selectSurface(providerAdvertisement, requestedSurfaceId);
const document = normalizeSurfaceDocument(surfaceDocument);
if (document.surfaceId !== selected.surfaceId) {
throw new Error(`Surface document ${document.surfaceId} does not match advertised Electron surface ${selected.surfaceId}.`);
}
return {
type: "electron-shell-projection",
schema: "gamecult.eve.electron_shell_projection.v1",
providerId: selected.providerId,
surfaceId: selected.surfaceId,
projectionKind: selected.worldInteraction.projectionKind,
commandBoundary: selected.worldInteraction.commandBoundary,
receiptSchema: selected.worldInteraction.receiptSchema,
ownership: selected.worldInteraction.ownership,
root: buildShellNode(document.root),
};
}
createCommandIntent(providerAdvertisement, requestedSurfaceId, command, payload = {}) {
if (!command) throw new Error("Command is required.");
const selected = this.selectSurface(providerAdvertisement, requestedSurfaceId);
@ -77,6 +97,47 @@ export function normalizeProviderAdvertisement(providerAdvertisement) {
return { ...providerAdvertisement, providerId, surfaces };
}
export function normalizeSurfaceDocument(surfaceDocument) {
if (!surfaceDocument || typeof surfaceDocument !== "object") {
throw new Error("Surface document is required.");
}
if (surfaceDocument.schema !== "gamecult.eve.surface.v1") {
throw new Error(`Unexpected surface schema: ${surfaceDocument.schema || ""}`);
}
const surface = objectValue(surfaceDocument.surface);
const surfaceId = firstString(surface.id);
if (!surfaceId) throw new Error("Surface document missing surface.id.");
const root = objectValue(surface.root);
if (!root.id) throw new Error(`Surface document ${surfaceId} missing surface.root.`);
return { ...surfaceDocument, surfaceId, root };
}
function buildShellNode(component) {
const source = objectValue(component);
const children = Array.isArray(source.children) ? source.children.map(buildShellNode) : [];
return {
id: firstString(source.id),
componentKind: firstString(source.kind),
shellElementKind: shellElementKind(firstString(source.kind)),
props: objectValue(source.props),
layout: objectValue(source.layout),
style: objectValue(source.style),
stateBindingCount: Array.isArray(source.stateBindings) ? source.stateBindings.length : 0,
embeddedDocumentCount: Array.isArray(source.embeddedDocuments) ? source.embeddedDocuments.length : 0,
children,
};
}
function shellElementKind(componentKind) {
if (!componentKind) return "empty";
if (componentKind.startsWith("control.")) return "command-control";
if (componentKind.startsWith("embed.")) return "plugin-placeholder";
if (componentKind === "surface.slot") return "embedded-surface-slot";
if (componentKind.startsWith("field.") || componentKind.startsWith("world.")) return "world-projection-node";
if (componentKind.startsWith("text.") || componentKind === "text" || componentKind === "label") return "text";
return "shell-node";
}
function normalizeWorldInteraction(value) {
const source = objectValue(value);
return {

View file

@ -36,6 +36,35 @@ test("command intents carry provider-advertised boundaries over component fallba
assert.equal(intent.clientId, "electron-shell");
});
test("lowers provider surface trees into an Electron shell projection", () => {
const shell = new EveElectronShell();
const projection = shell.lowerSurface(surfaceDocument(), advertisement(), "aetheria.daemon.game");
assert.equal(projection.schema, "gamecult.eve.electron_shell_projection.v1");
assert.equal(projection.providerId, "aetheria");
assert.equal(projection.surfaceId, "aetheria.daemon.game");
assert.equal(projection.projectionKind, "provider-authored-world-surface");
assert.equal(projection.commandBoundary, "aetheria.daemon.commands");
assert.equal(projection.receiptSchema, "aetheria.eve_command_acceptance_status.v1");
assert.equal(projection.root.id, "aetheria.daemon.game.root");
assert.equal(projection.root.children.length, 3);
assert.equal(projection.root.children[0].shellElementKind, "world-projection-node");
assert.equal(projection.root.children[0].props.binding, "cultmesh://aetheria/world/entities");
assert.equal(projection.root.children[0].stateBindingCount, 1);
assert.equal(projection.root.children[1].shellElementKind, "command-control");
assert.equal(projection.root.children[1].props.command, "aetheria.daemon.commands");
assert.equal(projection.root.children[2].shellElementKind, "plugin-placeholder");
assert.equal(projection.root.children[2].embeddedDocumentCount, 1);
});
test("rejects surface documents that do not match the advertised target", () => {
const shell = new EveElectronShell();
assert.throws(
() => shell.lowerSurface(surfaceDocument("aetheria.daemon.game"), advertisement(), "aetheria.daemon.editor"),
/does not match advertised Electron surface/,
);
});
function advertisement() {
return {
schema: "gamecult.eve.provider_advertisement.v1",
@ -66,3 +95,64 @@ function advertisement() {
],
};
}
function surfaceDocument(surfaceId = "aetheria.daemon.game") {
return {
type: "surface-state",
schema: "gamecult.eve.surface.v1",
providerId: "aetheria",
providerKind: "game.runtime",
title: "Aetheria world",
version: 1,
updatedAtUtc: "2026-07-09T00:00:00Z",
surface: {
id: surfaceId,
root: {
id: `${surfaceId}.root`,
kind: "surface",
props: {},
children: [
{
id: `${surfaceId}.entities`,
kind: "field.surface2d",
props: {
binding: "cultmesh://aetheria/world/entities",
},
stateBindings: [
{
target: "entities",
pointerId: "cultmesh://aetheria/world/entities",
},
],
children: [],
},
{
id: `${surfaceId}.focus`,
kind: "control.button",
props: {
command: "aetheria.daemon.commands",
commandId: "aetheria.daemon.focus",
},
children: [],
},
{
id: `${surfaceId}.norn`,
kind: "embed.norn",
props: {},
embeddedDocuments: [
{
slotId: "norn.map",
documentId: "cultmesh://aetheria/norn/map",
schemaId: "gamecult.eve.surface.v1",
presentationKind: "electron-overlay",
},
],
children: [],
},
],
},
styles: [],
},
commands: [],
};
}

View file

@ -55,18 +55,24 @@ try {
--expect-provider-surface-field aetheria:aetheria.daemon.editor:worldInteraction.ownership:provider-owns-editor-state-assets-command-acceptance-and-receipts `
--expect-interactive-world-surface aetheria:aetheria.daemon.game:web-reference:Aetheria `
--expect-interactive-world-surface aetheria:aetheria.daemon.game:unity-scene:Aetheria `
--expect-interactive-world-surface aetheria:aetheria.daemon.game:electron-shell:Aetheria `
--expect-interactive-world-surface aetheria:aetheria.daemon.editor:unity-uitoolkit:Aetheria `
--expect-interactive-world-surface aetheria:aetheria.daemon.editor:electron-shell: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:claimed:EveUnity:unity-scene `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:electron-shell:claimed:EveElectron:electron-shell `
--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:electron-shell:claimed:EveElectron:electron-shell `
--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:covered:EveUnity:unity-scene `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:electron-shell:covered:EveElectron:electron-shell `
--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:electron-shell:covered:EveElectron:electron-shell `
--expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:missing-runtime-claim:EveTui:tui `
--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 `
@ -79,8 +85,10 @@ try {
--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-world-surface-lowering:current:exists:eve-electron-shell.mjs `
--expect-split-handoff-move EveElectron:electron-shell:electron-shell-runtime:observed-provider:exists:Aetheria.Rts.Web/Electron `
--expect-split-handoff-move EveElectron:electron-shell:electron-command-transport:observed-provider:exists:Aetheria.Rts.Web/Client/app.ts `
--expect-split-handoff-move EveElectron:electron-shell:electron-world-surface-lowering:observed-provider:exists:Aetheria.Rts.Web/Client `
--expect-provider-command aetheria:aetheria.daemon.commands `
--expect-provider-receipt-state aetheria:accepted `
--expect-provider-receipt-state aetheria:pending `

View file

@ -37,10 +37,14 @@ try {
--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:claimed:EveUnity:unity-scene `
--expect-world-lowering-coverage aetheria:aetheria.daemon.game:electron-shell:claimed:EveElectron:electron-shell `
--expect-world-lowering-coverage aetheria:aetheria.daemon.editor:electron-shell:claimed:EveElectron:electron-shell `
--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:covered:EveUnity:unity-scene `
--expect-command-boundary-coverage aetheria:aetheria.daemon.game:electron-shell:covered:EveElectron:electron-shell `
--expect-command-boundary-coverage aetheria:aetheria.daemon.editor:electron-shell:covered:EveElectron:electron-shell `
--expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:missing-runtime-claim:EveTui:tui `
--expect-world-lowering-gap aetheria:aetheria.daemon.game:tui:EveTui:tui `
--expect-world-lowering-gap aetheria:aetheria.daemon.editor:tui:EveTui:tui `

View file

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

View file

@ -24,12 +24,46 @@ if ($manifest.lifecycle.test.status -ne "provider-shell-contract-skeleton") {
throw "Unexpected EveElectron provider shell status: $($manifest.lifecycle.test.status)"
}
foreach ($feature in @("providerAdvertisements", "commandTransport")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "surfaceTreeProjection")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveElectron provider shell missing supported feature: $feature"
}
}
$worldSurfaceLoweringClaims = @()
if ($null -ne $manifest.worldSurfaceLowering) {
$worldSurfaceLoweringClaims = @($manifest.worldSurfaceLowering)
}
if ($worldSurfaceLoweringClaims.Count -ne 1) {
throw "EveElectron must claim exactly one provider world-surface lowering target"
}
$worldSurfaceLoweringClaim = $worldSurfaceLoweringClaims | Where-Object { $_.targetId -eq "electron-shell" } | Select-Object -First 1
if (-not $worldSurfaceLoweringClaim) {
throw "EveElectron missing electron-shell world-surface lowering claim"
}
foreach ($surfaceKind in @("interactive-world", "interactive-world-editor")) {
if (-not (@($worldSurfaceLoweringClaim.surfaceKinds) -contains $surfaceKind)) {
throw "EveElectron world-surface claim missing surface kind: $surfaceKind"
}
}
foreach ($projectionKind in @("provider-authored-world-surface", "provider-authored-world-editor-surface")) {
if (-not (@($worldSurfaceLoweringClaim.projectionKinds) -contains $projectionKind)) {
throw "EveElectron world-surface claim missing projection kind: $projectionKind"
}
}
if ($worldSurfaceLoweringClaim.supportLevel -ne "electron-shell-surface-tree-command-surface") {
throw "Unexpected EveElectron support level: $($worldSurfaceLoweringClaim.supportLevel)"
}
if ($worldSurfaceLoweringClaim.ownership -ne "runtime-lowers-provider-world-surface-without-owning-world-state") {
throw "Unexpected EveElectron ownership: $($worldSurfaceLoweringClaim.ownership)"
}
foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) {
$absoluteEvidencePath = Join-Path $projectRoot $evidencePath
if (-not (Test-Path -LiteralPath $absoluteEvidencePath)) {
throw "EveElectron world-surface claim missing evidence path: $evidencePath"
}
}
$expectedFiles = @(
"runtimes\incubating\eve-electron\package.json",
"runtimes\incubating\eve-electron\src\eve-electron-shell.mjs",
@ -44,14 +78,14 @@ foreach ($relativePath in $expectedFiles) {
}
$shellSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-electron\src\eve-electron-shell.mjs") -Raw
foreach ($symbol in @("EveElectronShell", "selectSurface", "createCommandIntent", "worldInteraction", "commandBoundary", "receiptSchema", "electron-shell")) {
foreach ($symbol in @("EveElectronShell", "selectSurface", "lowerSurface", "createCommandIntent", "normalizeSurfaceDocument", "buildShellNode", "shellElementKind", "worldInteraction", "commandBoundary", "receiptSchema", "electron-shell")) {
if (-not $shellSource.Contains($symbol)) {
throw "EveElectron provider shell source missing symbol: $symbol"
}
}
$testSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-electron\test\eve-electron-shell.test.mjs") -Raw
foreach ($symbol in @("selects the active advertised provider surface", "command intents carry provider-advertised boundaries", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
foreach ($symbol in @("selects the active advertised provider surface", "lowers provider surface trees into an Electron shell projection", "rejects surface documents that do not match the advertised target", "command intents carry provider-advertised boundaries", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1")) {
if (-not $testSource.Contains($symbol)) {
throw "EveElectron provider shell test missing symbol: $symbol"
}

View file

@ -34,7 +34,7 @@ if ($handoff.runtimeId -ne "electron-shell") {
}
$moveSets = @($handoff.moveSets)
foreach ($stage in @("runtime-body", "command", "capture")) {
foreach ($stage in @("runtime-body", "command", "world-surface-lowering", "capture")) {
$moveSet = $moveSets | Where-Object { $_.stage -eq $stage } | Select-Object -First 1
if (-not $moveSet) {
throw "EveElectron split handoff missing move set for stage: $stage"
@ -53,7 +53,7 @@ foreach ($stage in @("runtime-body", "command", "capture")) {
}
}
foreach ($id in @("electron-shell-runtime", "electron-command-transport")) {
foreach ($id in @("electron-shell-runtime", "electron-command-transport", "electron-world-surface-lowering")) {
$moveSet = $moveSets | Where-Object { $_.id -eq $id } | Select-Object -First 1
if (-not $moveSet) {
throw "EveElectron split handoff missing move set: $id"

View file

@ -58,6 +58,7 @@ node $consumerScript $consumerExport `
--expect-runtime-feature unity-scene:sceneGraphProjection `
--expect-runtime-feature electron-shell:providerAdvertisements `
--expect-runtime-feature electron-shell:commandTransport `
--expect-runtime-feature electron-shell:surfaceTreeProjection `
--expect-runtime-feature tui:providerAdvertisements `
--expect-runtime-feature tui:commandTransport `
--expect-runtime-feature tui:terminalGridSummary `
@ -71,6 +72,9 @@ node $consumerScript $consumerExport `
--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-world-target electron-shell:electron-shell `
--expect-runtime-world-field electron-shell:electron-shell:supportLevel:electron-shell-surface-tree-command-surface `
--expect-runtime-world-field electron-shell:electron-shell: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 `
@ -89,6 +93,7 @@ node $consumerScript $consumerExport `
--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-plugin-gap electron-shell:tex.math:EveElectron `
--expect-runtime-handoff unity-uitoolkit `
--expect-runtime-command-schema web:gamecult.eve.command.v1 `
--expect-runtime-command-schema windows-flutter:gamecult.eve.command.v1 `

View file

@ -63,8 +63,10 @@ try {
--expect-split-target-blocker-record EveElectron:runtime-feature:electron-shell:embeddedDocuments `
--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-world-surface-lowering:current:exists:eve-electron-shell.mjs `
--expect-split-handoff-move EveElectron:electron-shell:electron-shell-runtime:observed-provider:exists:Aetheria.Rts.Web/Electron `
--expect-split-handoff-move EveElectron:electron-shell:electron-command-transport:observed-provider:exists:Aetheria.Rts.Web/Client/app.ts `
--expect-split-handoff-move EveElectron:electron-shell:electron-world-surface-lowering:observed-provider:exists:Aetheria.Rts.Web/Client `
--expect-split-target-blocker "EveElectron:Electron shell runtime body graduates to EveElectron outside Aetheria product code" `
--expect-split-target EveTui `
--expect-split-target-status EveTui:incubating `

View file

@ -620,7 +620,7 @@
"status": "pending",
"runtimes": ["electron-shell"],
"requiredRuntimeStatuses": ["active"],
"requiredFeatures": ["providerAdvertisements", "embeddedDocuments"],
"requiredFeatures": ["providerAdvertisements", "surfaceTreeProjection", "embeddedDocuments"],
"requiredPlugins": [],
"proofs": [
{
@ -643,7 +643,7 @@
]
},
{
"description": "EveElectron provider-shell skeleton selects advertised surfaces and emits Eve command intents.",
"description": "EveElectron provider-shell skeleton selects advertised surfaces, projects Eve surface trees, and emits Eve command intents.",
"status": "passed",
"evidencePaths": [
"runtimes/incubating/eve-electron/package.json",
@ -722,7 +722,7 @@
"splitHandoffPath": "runtimes/incubating/eve-electron/eveelectron-split-handoff.json",
"requiredFixtures": ["embedded-surface", "aetheria-world"],
"pluginFixtures": [],
"supportedFeatures": ["providerAdvertisements", "commandTransport"],
"supportedFeatures": ["providerAdvertisements", "commandTransport", "surfaceTreeProjection"],
"supportedPlugins": [],
"unsupportedPlugins": [
{
@ -738,6 +738,20 @@
"reason": "Electron provider-shell skeleton exists, but no TeX projection adapter exists in this runtime."
}
],
"worldSurfaceLowering": [
{
"targetId": "electron-shell",
"surfaceKinds": ["interactive-world", "interactive-world-editor"],
"projectionKinds": ["provider-authored-world-surface", "provider-authored-world-editor-surface"],
"supportLevel": "electron-shell-surface-tree-command-surface",
"ownership": "runtime-lowers-provider-world-surface-without-owning-world-state",
"evidencePaths": [
"runtimes/incubating/eve-electron/src/eve-electron-shell.mjs",
"runtimes/incubating/eve-electron/test/eve-electron-shell.test.mjs",
"web/fixtures/aetheria.provider-advertisement.json"
]
}
],
"expectedPaths": [
"runtimes/incubating/eve-electron/package.json",
"runtimes/incubating/eve-electron/src/eve-electron-shell.mjs",
@ -750,16 +764,16 @@
"expectedSourceSymbols": [
{
"path": "runtimes/incubating/eve-electron/src/eve-electron-shell.mjs",
"contains": ["EveElectronShell", "selectSurface", "createCommandIntent", "worldInteraction", "commandBoundary", "receiptSchema", "electron-shell"]
"contains": ["EveElectronShell", "selectSurface", "lowerSurface", "createCommandIntent", "normalizeSurfaceDocument", "buildShellNode", "shellElementKind", "worldInteraction", "commandBoundary", "receiptSchema", "electron-shell"]
},
{
"path": "runtimes/incubating/eve-electron/test/eve-electron-shell.test.mjs",
"contains": ["selects the active advertised provider surface", "command intents carry provider-advertised boundaries", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
"contains": ["selects the active advertised provider surface", "lowers provider surface trees into an Electron shell projection", "rejects surface documents that do not match the advertised target", "command intents carry provider-advertised boundaries", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
}
],
"capture": {
"status": "missing",
"note": "Electron capture is a split blocker until EveElectron owns a provider-agnostic shell."
"note": "Electron capture is a split blocker until EveElectron attaches provider-agnostic shell window artifacts."
}
},
{

View file

@ -105,10 +105,10 @@
],
"commandBoundary": "aetheria.daemon.commands",
"receiptSchema": "aetheria.eve_command_acceptance_status.v1",
"loweringTargets": ["web-reference", "unity-uitoolkit", "unity-scene", "tui"],
"loweringTargets": ["web-reference", "unity-uitoolkit", "unity-scene", "electron-shell", "tui"],
"ownership": "provider-owns-world-state-assets-command-acceptance-and-receipts"
},
"summary": "Authoritative daemon game surface consumed by Unity and web lowerers."
"summary": "Authoritative daemon game surface consumed by Unity, Electron, and web lowerers."
},
{
"schema": "gamecult.eve.surface.v1",
@ -138,7 +138,7 @@
],
"commandBoundary": "aetheria.daemon.commands",
"receiptSchema": "aetheria.eve_command_acceptance_status.v1",
"loweringTargets": ["web-reference", "unity-uitoolkit", "tui"],
"loweringTargets": ["web-reference", "unity-uitoolkit", "electron-shell", "tui"],
"ownership": "provider-owns-editor-state-assets-command-acceptance-and-receipts"
}
}
@ -176,10 +176,11 @@
"styleCapabilities": [
{
"styleProfile": "aetheria.daemon.world",
"preferredLowerings": ["unity-uitoolkit", "web-reference", "tui"],
"preferredLowerings": ["unity-uitoolkit", "web-reference", "electron-shell", "tui"],
"tokenGroups": ["aetheria.world", "aetheria.daemon", "aetheria.commandBoundary"],
"lossiness": {
"web-reference": "proves generic Eve lowering and command/binding shape; does not own Aetheria assets or simulation truth",
"electron-shell": "projects the same Eve surface tree inside a generic Electron shell; does not own Aetheria assets, IPC truth, or simulation truth",
"tui": "dense command/state inspection only"
}
}