diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index d695603..6511796 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -290,6 +290,13 @@ Recently cut: `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. +- 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. - Aetheria interactive world surfaces now carry a structured provider-owned `worldInteraction` contract. The provider advertisement names projection kind, provider state schemas, daemon command boundary, receipt schema, diff --git a/docs/parity-testing-harness.md b/docs/parity-testing-harness.md index 67ce540..ed4a220 100644 --- a/docs/parity-testing-harness.md +++ b/docs/parity-testing-harness.md @@ -199,11 +199,14 @@ Split-target consumer smoke: powershell -ExecutionPolicy Bypass -File .\scripts\run-split-target-conformance-consumer-smoke.ps1 ``` -That script asserts that EveFlutter and EveUnity are exported as incubating -split targets, that their current split-readiness proofs are passed, and that -their graduation blockers remain visible to consumers. A target being present -is not enough; future owner repos must be able to consume why it is or is not -ready to leave Eve incubation. +That script asserts that EveFlutter, EveUnity, and EveElectron are exported as +incubating split targets, that their current split-readiness proofs are passed, +and that their graduation blockers remain visible to consumers. A target being +present is not enough; future owner repos must be able to consume why it is or +is not ready to leave Eve incubation. EveElectron is intentionally pending: its +handoff names the generic Electron shell boundary, while the Starbridge RTS +client remains Aetheria-owned product code until a provider-agnostic shell +exists. The Flutter widget smoke also exercises `EveProviderCatalog` and `EveProviderPicker` against a conformance-export-shaped provider list. That is diff --git a/runtimes/incubating/eve-electron/eveelectron-split-handoff.json b/runtimes/incubating/eve-electron/eveelectron-split-handoff.json new file mode 100644 index 0000000..9a7fe74 --- /dev/null +++ b/runtimes/incubating/eve-electron/eveelectron-split-handoff.json @@ -0,0 +1,66 @@ +{ + "schema": "gamecult.eve.runtime_split_handoff.v1", + "splitTarget": "EveElectron", + "ownerRepo": "EveElectron", + "currentHostRepo": "Eve", + "runtimeId": "electron-shell", + "packageName": "eve-electron", + "sourcePackageRoot": "runtimes/incubating/eve-electron", + "destinationPackageRoot": "packages/eve-electron", + "authorityBoundary": "EveElectron owns generic Electron shell projection, window lifecycle, packaged app build glue, provider advertisement consumption, command transport, capture, and shell-level plugin projection adapters. Aetheria owns Starbridge state, product-specific RTS flows, assets, command authorization, receipts, and authored provider surfaces. Eve keeps the surface, command, provider advertisement, plugin advertisement, and conformance contracts.", + "moveSets": [ + { + "id": "electron-shell-runtime", + "stage": "runtime-body", + "currentPaths": [], + "observedProviderPaths": [ + "E:\\Projects\\Aetheria\\Aetheria.Rts.Web\\Electron", + "E:\\Projects\\Aetheria\\Aetheria.Rts.Web\\Client", + "E:\\Projects\\Aetheria\\Aetheria.Rts.Web\\tsconfig.electron.json" + ], + "destinationOwner": "EveElectron", + "replacementProof": "EveElectron hosts a provider-agnostic Electron shell that loads provider advertisements and lowers Eve surfaces without importing Aetheria client modules." + }, + { + "id": "electron-command-transport", + "stage": "command", + "currentPaths": [], + "observedProviderPaths": [ + "E:\\Projects\\Aetheria\\Aetheria.Rts.Web\\Client\\app.ts", + "E:\\Projects\\Aetheria\\Aetheria.Rts.Web\\Electron\\preload.cjs", + "E:\\Projects\\Aetheria\\Aetheria.Rts.Web\\Electron\\aetheria-cultmesh.ts" + ], + "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-capture-lifecycle", + "stage": "capture", + "currentPaths": [], + "destinationOwner": "EveElectron", + "replacementProof": "EveElectron attaches desktop-window capture artifacts to conformance output for at least one non-Aetheria provider and one Aetheria scenario." + } + ], + "contractInputs": [ + "gamecult.eve.surface.v1", + "gamecult.eve.command.v1", + "gamecult.eve.provider_advertisement.v1", + "gamecult.eve.plugin_advertisement.v1", + "gamecult.eve.plugin.v1", + "gamecult.eve.conformance_export.v1" + ], + "forbiddenImports": [ + "Aetheria RTS client modules as EveElectron runtime authority", + "Aetheria Starbridge state as Electron shell truth", + "provider-specific IPC contracts that bypass gamecult.eve.command.v1", + "plugin semantic internals", + "renderer-local product state as daemon truth" + ], + "requiredExternalProofs": [ + "EveElectron publishes a runtime capability manifest with provider advertisement consumption and command transport.", + "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.", + "EveElectron attaches Electron capture artifacts to conformance output." + ] +} diff --git a/scripts/run-split-target-conformance-consumer-smoke.ps1 b/scripts/run-split-target-conformance-consumer-smoke.ps1 index 87e176e..c397dce 100644 --- a/scripts/run-split-target-conformance-consumer-smoke.ps1 +++ b/scripts/run-split-target-conformance-consumer-smoke.ps1 @@ -43,7 +43,12 @@ try { --expect-split-target-proof "EveUnity:EveUnity split handoff is machine-readable" ` --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" + --expect-split-target-blocker "EveUnity:Unity batchmode or editor capture artifact" ` + --expect-split-target EveElectron ` + --expect-split-target-status EveElectron:incubating ` + --expect-split-target-proof "EveElectron:EveElectron split handoff is machine-readable" ` + --expect-split-target-blocker "EveElectron:runtime:electron-shell:status:pending" ` + --expect-split-target-blocker "EveElectron:Electron shell runtime body exists outside Aetheria product code" if ($LASTEXITCODE -ne 0) { throw "Split target conformance consumer smoke failed with exit code $LASTEXITCODE" } diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index 148b315..cb0c308 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -580,9 +580,71 @@ "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." ] + }, + { + "id": "EveElectron", + "ownerRepo": "EveElectron", + "repoRole": "runtime-target", + "status": "pending", + "runtimes": ["electron-shell"], + "requiredRuntimeStatuses": ["active"], + "requiredFeatures": ["providerAdvertisements", "embeddedDocuments"], + "requiredPlugins": [], + "proofs": [ + { + "description": "EveElectron split handoff is machine-readable.", + "status": "passed", + "evidencePaths": [ + "runtimes/incubating/eve-electron/eveelectron-split-handoff.json", + "docs/eve-migration-roadmap.md", + "docs/parity-testing-harness.md" + ] + } + ], + "pendingProofs": [ + "Electron shell runtime body exists outside Aetheria product code.", + "Electron consumes provider advertisements without Aetheria source-layout knowledge.", + "Electron emits gamecult.eve.command.v1 through provider command boundaries.", + "Electron capture artifacts are attached to conformance output." + ] } ], "runtimes": [ + { + "id": "electron-shell", + "title": "Electron shell", + "kind": "pending", + "ownerRepo": "EveElectron", + "repoRole": "runtime-target", + "splitTarget": "EveElectron", + "graduationTrigger": "Split when Electron has a provider-agnostic shell body, provider advertisement consumption, command transport, packaged app lifecycle, and capture evidence independent of Aetheria product code.", + "splitHandoffPath": "runtimes/incubating/eve-electron/eveelectron-split-handoff.json", + "requiredFixtures": ["embedded-surface", "aetheria-world"], + "pluginFixtures": [], + "supportedFeatures": [], + "supportedPlugins": [], + "unsupportedPlugins": [ + { + "pluginId": "sai.vn", + "reason": "Electron has no generic runtime body yet; Sai projection belongs behind provider/plugin advertisements once EveElectron exists." + }, + { + "pluginId": "norn.graph", + "reason": "Electron has no generic runtime body yet; Norn graph projection belongs behind provider/plugin advertisements once EveElectron exists." + }, + { + "pluginId": "tex.math", + "reason": "Electron has no generic runtime body yet; TeX projection belongs behind provider/plugin advertisements once EveElectron exists." + } + ], + "expectedPaths": [ + "runtimes/incubating/eve-electron/eveelectron-split-handoff.json" + ], + "capture": { + "status": "missing", + "note": "Electron capture is a split blocker until EveElectron owns a provider-agnostic shell." + } + }, { "id": "web", "title": "Web reference", diff --git a/tools/parity/run-parity.mjs b/tools/parity/run-parity.mjs index a24d3cc..9898dff 100644 --- a/tools/parity/run-parity.mjs +++ b/tools/parity/run-parity.mjs @@ -303,7 +303,7 @@ async function evaluateRuntime(runtime, fixtureResults) { } const commandTransportSmokeErrors = await validateRuntimeCommandTransportSmoke(runtime); const capabilityManifestErrors = await validateRuntimeCapabilityManifest(runtime); - const splitHandoffPath = await readRuntimeSplitHandoffPath(runtime.capabilityManifest); + const splitHandoffPath = await readRuntimeSplitHandoffPath(runtime); const localProviderCatalogErrors = await validateRuntimeLocalProviderCatalog(runtime); const missingIncubationFields = requiredIncubationFields(runtime).filter(field => !runtime[field]); const pluginCapabilityGaps = collectPluginCapabilityGaps(runtime, fixtureResults); @@ -407,7 +407,9 @@ async function validateRuntimeLocalProviderCatalog(runtime) { return errors; } -async function readRuntimeSplitHandoffPath(capabilityManifest) { +async function readRuntimeSplitHandoffPath(runtime) { + if (runtime?.splitHandoffPath) return runtime.splitHandoffPath; + const capabilityManifest = runtime?.capabilityManifest; if (!capabilityManifest?.manifestPath) return ""; const documentPath = path.join(repoRoot, capabilityManifest.manifestPath); if (!existsSync(documentPath)) return "";