Mount Eve operations surface at runtime

This commit is contained in:
Meta Vens 2026-06-15 21:12:43 +01:00
commit 38ff448d4c
6 changed files with 129 additions and 3 deletions

Binary file not shown.

View file

@ -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) ||

View file

@ -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

View file

@ -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

View file

@ -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<AetheriaEveSurfacePresenter>() != null)
return;
var host = new GameObject("Aetheria Eve Runtime Surface");
UnityEngine.Object.DontDestroyOnLoad(host);
host.AddComponent<UIDocument>();
var presenter = host.AddComponent<AetheriaEveSurfacePresenter>();
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) ?? "";
}
}
}

View file

@ -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