From 38ff448d4c99cba5cbaea528dfdd7d62f080903c Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 15 Jun 2026 21:12:43 +0100 Subject: [PATCH] Mount Eve operations surface at runtime --- .voidbot/state/aetheria.cc | Bin 135594 -> 137593 bytes Aetheria.State.Verify/Program.cs | 45 +++++++++++++ Aetheria.State/README.md | 8 ++- .../README.md | 9 +++ .../Runtime/AetheriaEveRuntimeBootstrap.cs | 60 ++++++++++++++++++ docs/aetheria-perfect-machine-map.md | 10 ++- 6 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveRuntimeBootstrap.cs diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index 2469181a6db8d767dfd222258b4c5d67df16b0ed..ef14b14c2a087cb62a12b4013f4db9a25cc9669c 100644 GIT binary patch delta 1676 zcmZWqzi%8x6xMF+*g-<3F+u_vzx09G;m8 zzPuJZfB0Z4`0614PX&uFC75Wl+r|;LO{Sbku)U+Tv(B(IU-&n;KDl}cU5rLBPYIHV;VfzYfX)TAs!BNr9H(WB2{2H9!q8dJ{u8=Z5 zWCH}Qm19C#D1aw~OkZu5k23PEZX0aHZMkJxLhyWyk^i68k!FHRtzdC>2aNq610-L z@NtG2k#oB#!T4UeP7+TB)d(fQ*$YsU0meC|jwuq*U{WX`6imF-b=r;*(EvN&I#iZu zKKx-T78VjVB#?&K45VlXEA^P>rv{KR7q?(1b3hY`G$kqRU>9kMm`Xo6=G7-n9YXdF zRkZwlgQ&_572b9phEo9>>r8r435O}-?lMMAQ^-;}D%inTP^0uleOE%4qUOOuxH$Rx zUBtBT(UCP^L^S(?BplF8iLJH7x>Zb%EK_`3aPUg{S70@B-yH*+BBuhpL4@Re-d(xQGVCe<+VHLfigcD4PPw=XG&l~Z$*V?##yp7Stns(|5yFP8pPX1RA zzBx%hs0H(@$z$Y0znY|quj*B*ck37zZwpHc>>+4L{pwWa@|oq@`sAlAEA^mLN^rK6 zU_F2PMA)0iONPh7AvwSxc`>D*As#h!TCWLdTDUOMw3Z%UA{!O>O~+MEEcckI6r12D zHP&WW5qPDdyuPhO{zofVd}g)V?RJ(sOZ{`xJNI6^yhaah7q&7L8AgT|-j^Be7e;>H zi}O$!z&CrOPE|jt>rWs5@=^Zi&tNhC?LsiO*{18}sd$gjwM+D{^dUwq5Q@vJu$0%m zJ|A?QqEhU7g-J%R={$!U+GqV3@7vZCqvnI>8%ytUz`g+J&vxucFso+f1e9~ LI@JjGmT&$KHU?eq delta 202 zcmeyliDT7bjtz^McnvMBOw6rJ4fPC+jiM$picUVt)WMA;IQb*9_~d-%awLT&#$bgU zEb>f@xy_m^+cjAjX9qBfZa*5rxM;(4GhQYaB-Li7Al1|7@G|W|5;Zpgn~~4VHobw5 gDF?|$bC8YG`S_XYkd#}1t=ztjpJ^W_vaop+0GT&59RL6T diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index a6939c17f..5968585d6 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -9,6 +9,7 @@ var statePath = args.Length > 1 RequireGameplaySourcePurity(root); RequirePackageSerializerBoundary(root); +RequireEveRuntimeBootstrap(root); await using var node = await AetheriaStateNode.OpenAsync(statePath, "aetheria-state-verify"); @@ -447,6 +448,7 @@ Console.WriteLine($"Corporation allegiance edges: {corporationAllegianceEdges}") Console.WriteLine($"Name files: {nameFiles.Length}"); Console.WriteLine("Live gameplay source purity: no serializer or legacy database symbols in Assets/Scripts"); Console.WriteLine("Package serializer boundary: MessagePack symbols remain in named CultCache transport files only"); +Console.WriteLine("Eve runtime bootstrap: operations surface mounts through UI Toolkit presenter"); static void RequireCount(AetheriaMigrationLedger ledger, string documentType, int actual) { @@ -549,6 +551,49 @@ static void RequirePackageSerializerBoundary(string root) } } +static void RequireEveRuntimeBootstrap(string root) +{ + var bootstrapPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.eve-runtime", + "Runtime", + "AetheriaEveRuntimeBootstrap.cs"); + var presenterPath = Path.Combine( + root, + "Packages", + "org.gamecult.aetheria.eve-runtime", + "Runtime", + "AetheriaEveSurfacePresenter.cs"); + + if (!File.Exists(bootstrapPath)) + { + throw new InvalidOperationException("Aetheria Eve runtime bootstrap is missing."); + } + + if (!File.Exists(presenterPath)) + { + throw new InvalidOperationException("Aetheria Eve surface presenter is missing."); + } + + var bootstrap = File.ReadAllText(bootstrapPath); + if (!bootstrap.Contains("RuntimeInitializeOnLoadMethod", StringComparison.Ordinal) || + !bootstrap.Contains("DefaultSurfaceId = \"aetheria.operations\"", StringComparison.Ordinal) || + !bootstrap.Contains("AetheriaEveSurfacePresenter", StringComparison.Ordinal) || + !bootstrap.Contains("UIDocument", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "Aetheria Eve runtime bootstrap no longer mounts the operations surface through the UI Toolkit presenter."); + } + + var presenter = File.ReadAllText(presenterPath); + if (!presenter.Contains("AetheriaRuntimeEveCommandLog.QueueCommand", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "Aetheria Eve presenter no longer queues renderer commands through the typed Eve command log."); + } +} + static bool ContainsBehaviorValueKind(AetheriaBehaviorValue value, string kind) { return string.Equals(value.Kind, kind, StringComparison.OrdinalIgnoreCase) || diff --git a/Aetheria.State/README.md b/Aetheria.State/README.md index a060541bb..ac4c85456 100644 --- a/Aetheria.State/README.md +++ b/Aetheria.State/README.md @@ -55,6 +55,10 @@ provider-owned acceptance organ for those commands: it validates the provider, surface, and command template before running the narrow refresh handlers for the catalog and operations surfaces. Renderer callbacks do not accept commands or mutate game state locally. +`AetheriaEveRuntimeBootstrap` mounts the `aetheria.operations` surface through a +runtime-created `UIDocument` after scene load, with environment and command-line +switches for diagnostics. UI Toolkit is now a live runtime lowering path, not +only a package sample. The old `SavedGame`/`SavedZone` DTOs and `Galaxy` loader constructor have also been deleted; the new document family is live Verse run/zone state, not a bespoke save-file format. @@ -288,7 +292,9 @@ named package/import CultCache transport boundary, not gameplay state authority. The package boundary is also fenced: MessagePack symbols may only appear in the runtime catalog reader, pending CultCache envelope store, and typed runtime/Eve command document files until generated CultCache serializers replace that -temporary Unity-side codec. +temporary Unity-side codec. The verifier also checks that the Eve runtime +bootstrap exists, mounts the operations surface through the UI Toolkit presenter, +and keeps renderer commands routed through the typed Eve command log. Use it after import when `GameData/aetheria-world.cc` changes. `Aetheria.State.Unity.Smoke` opens the materialized state through the runtime diff --git a/Packages/org.gamecult.aetheria.eve-runtime/README.md b/Packages/org.gamecult.aetheria.eve-runtime/README.md index 0078d0a58..3bbc7aa66 100644 --- a/Packages/org.gamecult.aetheria.eve-runtime/README.md +++ b/Packages/org.gamecult.aetheria.eve-runtime/README.md @@ -10,6 +10,15 @@ CultCache state into Unity UI Toolkit. - it queues renderer-emitted commands as typed `.cc.eve.pending` command envelopes for Aetheria's provider-owned command bridge. +`AetheriaEveRuntimeBootstrap` mounts the first runtime surface after scene load. +By default it creates a `UIDocument` host for `aetheria.operations`, so the +provider-owned operations surface is present at runtime without a hand-wired +scene object. Set `AETHERIA_EVE_SURFACE_ID` to mount a different surface, set +`AETHERIA_EVE_STATE_PATH` to point at a non-default `.cc` state file, or disable +the automatic mount with `AETHERIA_DISABLE_EVE_RUNTIME_BOOTSTRAP=true` or +`--aetheria-disable-eve-runtime-bootstrap`. Batchmode disables the bootstrap so +compile and smoke gates do not accidentally create renderer state. + Commands are surfaced as `gamecult.eve.command.v1` requests. The presenter does not accept or apply them locally; provider acceptance still belongs to the CultMesh command bridge. Renderer-local command effects would be the wrong diff --git a/Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveRuntimeBootstrap.cs b/Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveRuntimeBootstrap.cs new file mode 100644 index 000000000..1252d4838 --- /dev/null +++ b/Packages/org.gamecult.aetheria.eve-runtime/Runtime/AetheriaEveRuntimeBootstrap.cs @@ -0,0 +1,60 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.UIElements; + +#nullable enable + +namespace GameCult.Aetheria.EveRuntime +{ + public static class AetheriaEveRuntimeBootstrap + { + public const string DefaultSurfaceId = "aetheria.operations"; + public const string DisableEnvironmentVariable = "AETHERIA_DISABLE_EVE_RUNTIME_BOOTSTRAP"; + public const string SurfaceEnvironmentVariable = "AETHERIA_EVE_SURFACE_ID"; + public const string StatePathEnvironmentVariable = "AETHERIA_EVE_STATE_PATH"; + public const string DisableCommandLineSwitch = "--aetheria-disable-eve-runtime-bootstrap"; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] + private static void MountDefaultSurface() + { + if (IsDisabled() || UnityEngine.Object.FindObjectOfType() != null) + return; + + var host = new GameObject("Aetheria Eve Runtime Surface"); + UnityEngine.Object.DontDestroyOnLoad(host); + + host.AddComponent(); + var presenter = host.AddComponent(); + presenter.SurfaceId = SurfaceId(); + presenter.StateFilePathOverride = StatePathOverride(); + } + + private static bool IsDisabled() + { + if (Application.isBatchMode) + return true; + + var environment = Environment.GetEnvironmentVariable(DisableEnvironmentVariable); + if (string.Equals(environment, "1", StringComparison.OrdinalIgnoreCase) || + string.Equals(environment, "true", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + return Environment.GetCommandLineArgs() + .Any(argument => string.Equals(argument, DisableCommandLineSwitch, StringComparison.OrdinalIgnoreCase)); + } + + private static string SurfaceId() + { + var configured = Environment.GetEnvironmentVariable(SurfaceEnvironmentVariable); + return string.IsNullOrWhiteSpace(configured) ? DefaultSurfaceId : configured; + } + + private static string StatePathOverride() + { + return Environment.GetEnvironmentVariable(StatePathEnvironmentVariable) ?? ""; + } + } +} diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 096051dba..ef2d6b99d 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -497,6 +497,11 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. surface lookup, lowering, and command emission into a typed pending queue. Provider command acceptance still belongs to the future CultMesh command bridge. +- `AetheriaEveRuntimeBootstrap` mounts the first runtime Eve surface after + scene load. The default surface is `aetheria.operations`, hosted in a + runtime-created `UIDocument`; environment variables or a command-line switch + can redirect/disable the mount for diagnostics. Batchmode disables the + bootstrap so verification runs do not create renderer state. - `GameData/aetheria-world.cc` is now materialized from the importer as the project-local typed state file for the checked-in catalog. The importer stores relative provenance in the state document, not machine-local absolute paths. @@ -1341,8 +1346,9 @@ First Aetheria surfaces to publish: serializers directly. - Extend the command bridge beyond refresh commands as gameplay/editor Eve surfaces acquire provider-owned handlers. - - Wire the presenter into a Unity scene/prefab for the first runtime surface - and replace a concrete uGUI screen. + - Done: wire the presenter into runtime through `AetheriaEveRuntimeBootstrap` + so the operations surface mounts as a UI Toolkit surface after scene load. + - Replace a concrete uGUI screen with an Eve-owned surface. - Move the staged packages into the Eve repo once its worktree is clean, then import them back into Aetheria from Eve instead of carrying a local copy. - Replace the old IMGUI DB inspector first, because it is closest to state