681 lines
38 KiB
Markdown
681 lines
38 KiB
Markdown
# Eve Parity Testing Harness
|
|
|
|
The parity harness is the shared evidence path for Eve runtimes. It does not
|
|
try to prove byte-identical pixels. It proves that every runtime is aiming at
|
|
the same provider-owned CultUI surface: same fixture, same retained tree, same
|
|
style-token expectations, same control anatomy, and explicit capture gaps.
|
|
|
|
## Authority
|
|
|
|
- `tools/parity/parity-manifest.json` owns the fixture matrix, runtime list, and
|
|
expectations.
|
|
- `tools/parity/run-parity.mjs` owns semantic fixture checks and report
|
|
generation.
|
|
- Runtime capture adapters own screenshots or frame capture for their platform.
|
|
- `artifacts/parity/latest.md` and `artifacts/parity/latest.json` are reports,
|
|
not source truth.
|
|
|
|
The manifest is the cut line. If a fixture or runtime is not in the manifest,
|
|
it is not part of the parity claim.
|
|
|
|
Runtime capability manifests are the runtime-owned side of that claim. When a
|
|
runtime entry has `capabilityManifest`, the harness validates the JSON document
|
|
against `gamecult.eve.runtime_capability.v1` and cross-checks runtime id,
|
|
supported features, supported and unsupported plugin declarations, command
|
|
transport schema, and incubation metadata. The central parity manifest may
|
|
coordinate split-readiness, but the runtime body must publish the capability
|
|
claim it expects other repos to consume.
|
|
|
|
The web reference and Unity UI Toolkit both publish runtime capability
|
|
manifests. Web uses `web/eve-runtime-capability.json` to make the browser oracle
|
|
explicit: it consumes provider advertisements, lowers provider-owned surfaces,
|
|
emits `gamecult.eve.command.v1` intents, and records Chrome headless capture
|
|
evidence without becoming provider truth. Unity UI Toolkit uses the same path
|
|
for its `sai.vn`, `norn.graph`, and `tex.math` plugin projection adapter proofs
|
|
while leaving Sai, Norn, and TeX semantic authority in their independent
|
|
sidecar plugin owners.
|
|
|
|
## Run
|
|
|
|
Semantic checks:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-parity-harness.ps1
|
|
```
|
|
|
|
Hard screenshot smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-parity-smoke.ps1
|
|
```
|
|
|
|
Nightwing owns the Linux Flutter capture body. If its user-local Flutter SDK is
|
|
missing, install it first:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\install-nightwing-flutter-sdk.ps1
|
|
```
|
|
|
|
The smoke expands every resizable renderer across the manifest's responsive
|
|
viewport matrix:
|
|
|
|
- `phone`: 390 x 844
|
|
- `tablet`: 768 x 1024
|
|
- `desktop`: 1280 x 720
|
|
|
|
Device runtimes also capture native physical panel cases when the platform
|
|
adapter can control orientation without overriding size. Android Flutter
|
|
currently emits:
|
|
|
|
- `native-portrait`: Periwinkle at physical portrait resolution
|
|
- `native-landscape`: Periwinkle at physical landscape resolution
|
|
|
|
The semantic runner writes:
|
|
|
|
- `artifacts/parity/latest.md`
|
|
- `artifacts/parity/latest.json`
|
|
- `artifacts/parity/<timestamp>/parity-report.md`
|
|
- `artifacts/parity/<timestamp>/parity-report.json`
|
|
- `artifacts/conformance/latest/index.md`
|
|
- `artifacts/conformance/latest/index.json`
|
|
- `artifacts/conformance/latest/packs/*.json`
|
|
- `artifacts/conformance/<timestamp>/...`
|
|
|
|
The conformance export includes `conformanceHandoffPath`, pointing at the
|
|
machine-readable EveConformance split map. That handoff is incubation evidence:
|
|
it names which runner, schema, consumer-smoke, and fixture-corpus paths move
|
|
when the conformance body leaves Eve.
|
|
|
|
Handoff documents are also copied into the export under `handoffs/*.json`.
|
|
Consumer smokes assert those exported copies, not just Eve-local source paths,
|
|
so owner repos can inspect plugin, provider, runtime, and conformance handoff
|
|
maps from the exported pack itself.
|
|
|
|
The conformance export also carries a `gamecult.eve.capability_matrix.v1`
|
|
projection. It summarizes pack health, plugin ABI/capability claims, provider
|
|
surfaces/commands/receipts, runtime feature/capture/command coverage, split
|
|
readiness, and handoff counts. This is derived evidence for consumers, not a
|
|
new source of truth.
|
|
The export schema and consumer smoke now require minimum record shapes for
|
|
plugins, providers, runtimes, and split targets. Owner repos should be able to
|
|
depend on ids, owners, statuses, split targets, manifest or advertisement paths,
|
|
feature/plugin arrays, and blocker/proof arrays without reading Eve's parity
|
|
manifest.
|
|
|
|
Capability gaps are exported as `capabilityGaps[]`. They are derived from
|
|
missing plugin/provider/runtime evidence, declared unsupported plugin
|
|
projection, capture gaps, and split blockers. Consumer smokes can assert named
|
|
gap substrings with `--expect-capability-gap`.
|
|
When a provider advertises a world-surface lowering target that no runtime
|
|
claims, the gap is assigned to the matching pending runtime owner when one
|
|
exists, such as `unity-scene` -> EveUnity or `tui` -> EveTui. Eve only owns the
|
|
gap when no runtime target has been declared at all.
|
|
The same facts are also exported as `worldSurfaceLoweringGaps[]` so runtime
|
|
owners can consume provider id, surface id, target id, owner repo, runtime id,
|
|
split target, and runtime status as typed fields instead of parsing the generic
|
|
gap text.
|
|
The full advertised-target ledger is exported as
|
|
`worldSurfaceLoweringCoverage[]`. Each record joins a provider-owned world
|
|
surface to one advertised lowering target and reports whether that target is
|
|
`claimed`, `missing-claim`, or `missing-runtime`, along with the runtime owner
|
|
and runtime id. Consumer smokes can assert complete coverage facts with
|
|
`--expect-world-lowering-coverage <providerId:surfaceId:targetId:status:ownerRepo:runtimeId>`.
|
|
Provider-owned world/editor surfaces are exported as
|
|
`interactiveWorldSurfaces[]`. These records index the provider id, owner repo,
|
|
surface id, surface kind, projection kind, state schemas, command boundary,
|
|
receipt schema, lowering targets, and ownership rule so runtime lowerers can
|
|
discover provider-authored world surfaces without importing provider source
|
|
layout. Consumer smokes can assert advertised targets with
|
|
`--expect-interactive-world-surface <providerId:surfaceId:targetId:ownerRepo>`.
|
|
The command path for those targets is exported as
|
|
`commandBoundaryCoverage[]`. Each record joins a provider-owned surface,
|
|
advertised lowering target, runtime owner, provider command boundary, receipt
|
|
schema, and runtime command envelope schema. Status is `covered` only when the
|
|
runtime has claimed the target and advertises `gamecult.eve.command.v1`;
|
|
otherwise it reports `missing-runtime`, `missing-runtime-claim`,
|
|
`missing-provider-boundary`, or `missing-command-transport`. Consumer smokes can
|
|
assert it with
|
|
`--expect-command-boundary-coverage <providerId:surfaceId:targetId:status:ownerRepo:runtimeId>`.
|
|
The browser reference lowerer also copies the active surface's advertised
|
|
`worldInteraction.commandBoundary` and `worldInteraction.receiptSchema` into
|
|
`gamecult.eve.command.v1` intents, falling back to component action metadata
|
|
only when the advertisement lacks those fields. That keeps command routing on
|
|
the provider/plugin advertisement contract instead of letting the browser
|
|
reference probe provider source layout.
|
|
Declared runtime/plugin projection gaps are exported as
|
|
`runtimePluginProjectionGaps[]`. These records carry runtime id, runtime owner,
|
|
split target, plugin id, reason, severity, and fixture lists so EveUnity,
|
|
EveElectron, Sai, Norn, and TeX owners can distinguish "this projection runtime
|
|
cannot project the plugin yet" from "plugin semantics belong in Eve core."
|
|
Device-edge dashboard proofs that do not claim plugin projection are not listed
|
|
as failed plugin clients. Consumer smokes can assert real projection gaps with
|
|
`--expect-runtime-plugin-gap <runtimeId:pluginId:ownerRepo>`.
|
|
The same claims are exported as `runtimePluginProjectionCoverage[]`, including
|
|
positive `supported` projection adapters and declared `unsupported` gaps. This
|
|
lets runtime and plugin owners consume one ledger for "Unity UI Toolkit has
|
|
projection adapters for independent Sai and Norn sidecar-advertised output,"
|
|
"Unity scene can project Norn's sidecar-advertised embedded graph shell," and
|
|
"Electron does not have generic plugin projection yet" instead of walking
|
|
nested runtime records. Consumer smokes can assert entries with
|
|
`--expect-runtime-plugin-projection <runtimeId:pluginId:status:ownerRepo>`.
|
|
Provider surface plugin requirements are also joined with runtime projection
|
|
support as `providerRuntimePluginProjectionCoverage[]`. These records answer
|
|
the real lowering question: whether a provider surface's required or
|
|
optional-nested plugin can be projected by a concrete runtime. Required plugin
|
|
failures are blockers; optional nested failures are degraded lowerings. Consumer
|
|
smokes can assert them with
|
|
`--expect-provider-runtime-plugin-projection <providerId:surfaceId:runtimeId:pluginId:status:runtimeOwnerRepo>`.
|
|
|
|
The conformance export includes runtime `capabilityManifestPath` and
|
|
`capabilityManifestErrors` fields so external consumers can distinguish a
|
|
generic projection runtime from a runtime that can project plugin-declared
|
|
capabilities.
|
|
Browser reference fallback discovery is exported as `localProviderCatalogs[]`.
|
|
Each record names the runtime, source catalog path, exported catalog copy,
|
|
schema, purpose, provider ids, advertisement paths, surface count, status, and
|
|
validation errors. This proves which local provider/plugin advertisements the
|
|
web picker is consuming without turning the fallback file into live discovery
|
|
truth. Consumer smokes can assert entries with
|
|
`--expect-local-provider-catalog <runtimeId:status:path-substring>`,
|
|
`--expect-local-provider-catalog-provider <runtimeId:providerId>`, and
|
|
`--expect-local-provider-catalog-advertisement <runtimeId:advertisement-path-substring>`.
|
|
|
|
Plugin handoff paths are exported as `plugins[].handoffPath` for owner repos
|
|
such as Sai, Norn, and EvePlugins. These paths are incubation evidence for
|
|
where plugin manifest, advertisement, ABI fixture, and conformance ownership
|
|
must move; they are not plugin runtime state.
|
|
Plugin handoff move/source coverage is exported as
|
|
`pluginHandoffMoveCoverage[]`. Each record joins plugin id, owner repo, split
|
|
target, handoff move set, destination owner, replacement proof, and current
|
|
source path status. Consumer smokes can assert them with
|
|
`--expect-plugin-handoff-move <pluginId:moveSetId:pathKind:status:path-substring>`.
|
|
Provider handoff move/source coverage is exported as
|
|
`providerHandoffMoveCoverage[]`. Each record joins provider id, owner repo,
|
|
handoff move set, destination owner, replacement proof, and current source path
|
|
status. Provider repos such as Aetheria can assert them with
|
|
`--expect-provider-handoff-move <providerId:moveSetId:pathKind:status:path-substring>`
|
|
without depending on Eve's source layout.
|
|
Plugin ABI fixture operations are exported as `plugins[].abiOperationContracts`
|
|
with `operation`, `input`, and `expect` blocks. Plugin owners can consume the
|
|
operation-level contract for `describe`, `validate`, `project`, `lower`,
|
|
`measure`, and `apply` without opening Eve-local fixture files.
|
|
The same operation set is indexed as root `pluginAbiOperationCoverage[]` records
|
|
with plugin id, owner repo, operation, status, fixture path, input keys, and
|
|
expect keys. Plugin-owner smokes can assert contracted operations with
|
|
`--expect-plugin-abi-operation-coverage <pluginId:operation:status:ownerRepo>`
|
|
without walking nested plugin records.
|
|
Provider-advertised plugin requirements are indexed as root
|
|
`providerPluginRequirementCoverage[]` records. These join provider id, surface
|
|
id, plugin id, plugin owner, plugin status, availability, required
|
|
capabilities, optional capabilities, and missing capabilities so provider and
|
|
plugin owners can consume requirement coverage without reconstructing the
|
|
provider/plugin join. `availability: optional-nested` means the parent surface
|
|
can compose that independent plugin when available; it is not a parent-plugin
|
|
dependency and it does not move nested semantics into the parent plugin.
|
|
Consumer smokes can assert them with
|
|
`--expect-provider-plugin-requirement <providerId:surfaceId:pluginId:status:pluginOwnerRepo[:availability]>`.
|
|
Plugin-owner smokes should use the optional availability field when proving that
|
|
Sai's required VN plugin is distinct from optional nested Norn or TeX surfaces.
|
|
For the parent/nested relationship itself, use
|
|
`--expect-independent-nested-plugin <providerId:surfaceId:parentPluginId:nestedPluginId:nestedOwnerRepo>`;
|
|
this checks that the parent plugin is required, the nested plugin is
|
|
`optional-nested`, the nested owner is separate, and nested capabilities remain
|
|
optional composition rather than parent-plugin dependency.
|
|
|
|
The runtime conformance pack is evidence-shaped, not fixture-shaped. Its
|
|
`packs/runtime.json` document includes `runtimeTargets` so runtime repos can
|
|
consume status, supported features, plugin support, command schema, lifecycle,
|
|
capture status, world-surface lowering claims, and missing evidence without reading Eve's local parity
|
|
manifest. The runtime-owner consumer smoke asserts EveUnity lifecycle stage
|
|
status and pending release/test/capture proofs from the exported runtime record,
|
|
plus release contract fields such as package name, artifact kind, tag pattern,
|
|
and package root, plus Unity EditMode test runner contract fields such as
|
|
runner script, package name, test assembly, and platform. It also asserts that
|
|
web and Unity UI Toolkit claim their provider-advertised world-surface lowering
|
|
targets. Split blockers are exported both as human-readable `blockers[]` and as
|
|
typed `blockerRecords[]` / root `splitTargetBlockers[]` entries. Split-target
|
|
consumers can assert blocker kind and subject with
|
|
`--expect-split-target-blocker-record <targetId:kind:subject>` instead of
|
|
scraping prose from handoff notes.
|
|
Runtime split handoff move/source coverage is exported as
|
|
`splitHandoffMoveCoverage[]`. Each record joins a split target, runtime id,
|
|
handoff move set, destination owner, replacement proof, and source path status.
|
|
`current` paths are Eve-incubated code that still needs to leave,
|
|
`observed-provider` paths are provider-owned pressure sources such as
|
|
Aetheria's current Electron client, and `replacement-required` records mark
|
|
move sets where no generic runtime source exists yet. Consumer smokes can
|
|
assert them with
|
|
`--expect-split-handoff-move <splitTarget:runtimeId:moveSetId:pathKind:status:path-substring>`.
|
|
Runtime split handoff documents themselves use
|
|
`gamecult.eve.runtime_split_handoff.v1`; the parity runner validates the
|
|
handoff document shape and exports any `splitHandoffErrors` on the runtime
|
|
record.
|
|
Plugin, provider, and EveConformance handoff documents are also schema-backed:
|
|
`gamecult.eve.plugin_handoff.v1`, `gamecult.eve.provider_handoff.v1`, and
|
|
`gamecult.eve.conformance_handoff.v1` are exported through the schema catalog.
|
|
Owner consumer smokes assert those schemas before trusting handoff paths.
|
|
Runtime lifecycle records use `gamecult.eve.runtime_lifecycle.v1`. Standalone
|
|
lifecycle documents such as `../EveFlutter/eveflutter-lifecycle.json` and
|
|
embedded runtime capability lifecycle blocks validate against the same stage
|
|
shape, and exported runtime records carry `lifecycleErrors`.
|
|
Runtime shell output contracts are schema-backed too:
|
|
`gamecult.eve.electron_shell_projection.v1` covers the Electron shell tree, and
|
|
`gamecult.eve.tui_grid.v1` covers the compact terminal grid. The Electron and
|
|
TUI runtime tests validate real lowered objects against those schemas.
|
|
|
|
After generating the parity report, `run-parity-harness.ps1` copies
|
|
`artifacts/conformance/latest` into
|
|
`artifacts/conformance-consumer-smoke/export` and runs
|
|
`tools/conformance/consume-export.mjs` against that copied layout. That smoke
|
|
proves the conformance export can be consumed through its own index and pack
|
|
files without reading `tools/parity/parity-manifest.json`.
|
|
|
|
EveConformance handoff smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-eveconformance-handoff-smoke.ps1
|
|
```
|
|
|
|
That script validates `tools/conformance/eveconformance-handoff.json` against
|
|
the parity manifest and, when present, the generated conformance export. It
|
|
checks the runner, schema, consumer-smoke, fixture-corpus move sets and the
|
|
required core/plugin/provider/runtime pack families.
|
|
|
|
Provider-owned consumer smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-aetheria-conformance-consumer-smoke.ps1
|
|
```
|
|
|
|
That script runs the same export consumer from `E:\Projects\Aetheria` and
|
|
asserts the provider pack, `aetheria-world` fixture, `aetheria` provider entry,
|
|
`aetheria-world-command-replay` scenario, daemon game/editor surface-kind
|
|
claims, and provider handoff path. It also asserts the Aetheria
|
|
`runtime.captureArtifacts[]` emitted by Unity UI Toolkit, Unity Scene,
|
|
Electron shell, and TUI, so provider consumption proves real runtime artifacts
|
|
rather than only advertised lowering targets. Generated copies remain under
|
|
Eve's `artifacts/aetheria-conformance-consumer-smoke` so the provider worktree
|
|
does not become dirty merely by proving the boundary.
|
|
Runtime capture request builders select a declared provider surface by id when
|
|
requested. Unity UI Toolkit, Electron shell, and TUI declare
|
|
`aetheria.daemon.editor` as an additional capture surface; Unity Scene does not,
|
|
because the editor advertisement does not include the `unity-scene` lowering
|
|
target.
|
|
|
|
Plugin owner smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-eveplugins-owner-smoke.ps1
|
|
```
|
|
|
|
That script runs EvePlugins tests and the retained TeX sidecar witness. Sai,
|
|
Norn, and TeX manifests are read from their owner repos and must agree with the
|
|
runtime-independent `gamecult.eve.plugin_abi.v1` boundary: renderer
|
|
independence, no provider-state mutation, provider-owned command acceptance,
|
|
and explicit `runtime.sidecar` process/protocol/schema fields. The plugin-owner
|
|
conformance smoke asserts the attached owner witnesses,
|
|
runtime boundary claims, and exported sidecar fields from the conformance
|
|
export.
|
|
|
|
Aetheria provider-pack smoke:
|
|
|
|
```powershell
|
|
node E:\Projects\Aetheria\scripts\verify-eve-conformance-pack.mjs
|
|
```
|
|
|
|
That owner script validates Aetheria's advertisement, interactive world
|
|
surface, fixture metadata, provider scenario, and asset manifest. Eve consumes
|
|
those documents through the provider entry's `sourceRoot`; it does not keep a
|
|
second product fixture corpus.
|
|
|
|
EveFlutter consumer smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-eveflutter-conformance-consumer-smoke.ps1
|
|
```
|
|
|
|
The EveFlutter owner script runs the export consumer from `EveFlutter` and asserts the
|
|
runtime pack, Sai provider fixture, Flutter runtime targets, and `EveFlutter`
|
|
split target without reading `tools/parity/parity-manifest.json`.
|
|
|
|
Split-target consumer smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-split-target-conformance-consumer-smoke.ps1
|
|
```
|
|
|
|
That script asserts that EveFlutter, EveUnity, EveElectron, and EveTui 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 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. The Electron runtime now claims
|
|
a narrow provider-advertised surface-tree command surface and exposes a typed
|
|
capture request contract plus a schema-backed JSON shell projection artifact.
|
|
It preserves embedded document slot identity in the generic shell projection,
|
|
and the split-target smoke asserts both Aetheria and `eve.world-smoke`
|
|
`runtime.captureArtifacts[]` for `electron-shell` so the generic shell proof
|
|
cannot collapse back into the Aetheria RTS client. Packaged rendering and
|
|
actual window PNG capture remain blockers.
|
|
EveUnity's UI Toolkit handoff does the same for Aetheria's Unity consumer
|
|
boundary: Aetheria's Unity `Packages/manifest.json`, generated
|
|
`GameCult.Eve.UnityUIToolkit.csproj`, assets root, daemon catalog client, and
|
|
Unity smoke are exported as `observed-provider` paths. That proves a real game
|
|
consumes the generic EveUnity package/contract while keeping product state,
|
|
assets, generated projects, scenes, and receipts in Aetheria. The same
|
|
split-target smoke now asserts `runtime.captureArtifacts[]` for both Aetheria
|
|
and the generic `eve.world-smoke` provider on `unity-uitoolkit` and
|
|
`unity-scene`, so generic Unity lowering evidence cannot collapse back into an
|
|
Aetheria-only proof.
|
|
EveTui is now an active incubating runtime: it claims a lossy
|
|
provider-advertised terminal-grid command surface, preserves embedded document
|
|
slot identity in the grid artifact, projects Sai/Norn/TeX fallback shells, and
|
|
attaches a typed JSON grid capture. The split-target smoke asserts both
|
|
Aetheria and `eve.world-smoke` `runtime.captureArtifacts[]` for `tui`, so the
|
|
terminal-grid proof stays generic instead of becoming Aetheria-only evidence.
|
|
Repo/package graduation and owner-repo capture production remain blockers.
|
|
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. The `unity-scene` runtime now claims
|
|
a narrow scene graph command surface, preserves embedded document slot identity,
|
|
and exposes a typed capture request contract plus a schema-backed JSON scene
|
|
projection artifact, while actual scene/frame PNG capture and release remain
|
|
explicit blockers.
|
|
|
|
The Flutter widget smoke also exercises `EveProviderCatalog` and
|
|
`EveProviderPicker` against a conformance-export-shaped provider list. That is
|
|
the runtime-side provider picker proof; it consumes provider entries and plugin
|
|
requirements without reading web fixture paths.
|
|
|
|
Aetheria Unity package consumer smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-aetheria-unity-package-smoke.ps1
|
|
```
|
|
|
|
That script checks that Aetheria's Unity package manifest consumes Eve's surface
|
|
and UI Toolkit packages by file reference, verifies the generated
|
|
`GameCult.Eve.UnityUIToolkit.csproj` includes all current Unity runtime source
|
|
files, then builds the package through Aetheria's Unity-generated project. It is
|
|
consumer-build evidence, not a replacement for runtime-owned Unity capture or
|
|
release CI.
|
|
|
|
Aetheria Unity EditMode test smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-aetheria-unity-editmode-tests.ps1
|
|
```
|
|
|
|
That script temporarily adds `org.gamecult.eve.unity-uitoolkit` to Aetheria's
|
|
Unity `testables`, runs `GameCult.Eve.UnityUIToolkit.Tests` in Unity batchmode,
|
|
writes XML and log artifacts under `artifacts/aetheria-unity-editmode`, and
|
|
restores `Packages/manifest.json` before returning. The test asmdef uses
|
|
Unity-style precompiled references for the Brokkr/CultMesh DLLs that Unity
|
|
needs to resolve `GameCult.Mesh`; this complements the normal CultLib
|
|
.NET/NuGet dependency story rather than replacing it. The runner proves the
|
|
incubating package test lifecycle, not final EveUnity-owned release or capture.
|
|
The exported runtime lifecycle records that runner contract so EveUnity can
|
|
inherit the Unity-specific test proof without making Eve responsible for
|
|
CultLib package distribution.
|
|
|
|
Unity scene EditMode test smoke:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-aetheria-unity-scene-editmode-tests.ps1
|
|
```
|
|
|
|
That wrapper uses the same manifest-restore runner, but selects
|
|
`org.gamecult.eve.unity-scene` and `GameCult.Eve.UnityScene.Tests`. It proves
|
|
the generic playable-world Unity client body through the Aetheria consumer
|
|
project while keeping Aetheria as provider authority.
|
|
|
|
Unity runtime lifecycle evidence:
|
|
|
|
`packages/org.gamecult.eve.unity-uitoolkit/eve-runtime-capability.json`
|
|
declares release, test, and capture lifecycle stages for the UI Toolkit runtime.
|
|
The parity harness validates those lifecycle claims against
|
|
`tools/parity/parity-manifest.json` and checks that declared evidence paths
|
|
exist. The current lifecycle proof is deliberately split:
|
|
|
|
- release: `tools/eveunity/eveunity-release-contract.mjs` builds a typed
|
|
`gamecult.eve.runtime_release_request.v1` request from the runtime capability
|
|
manifest and UPM package manifest, including required package dependency
|
|
owners. `tools/eveunity/eveunity-release-artifact.mjs` then packs the
|
|
declared package root into the declared UPM `.tgz` artifact. The tagged
|
|
EveUnity release remains a split blocker;
|
|
- test: package-owned EditMode tests run through Aetheria in Unity batchmode,
|
|
and Aetheria can build the package through Unity's generated project. The
|
|
test contract names CultLib-owned NuGet/precompiled assembly inputs without
|
|
making EveUnity own CultLib package distribution;
|
|
- capture: `tools/eveunity/eveunity-capture-contract.mjs` builds a typed
|
|
`gamecult.eve.runtime_capture_request.v1` request from the runtime capability
|
|
manifest and Aetheria provider advertisement; Unity editor or batchmode PNG
|
|
capture remains a split blocker. `tools/eveunity/eveunity-uitoolkit-capture-artifact.mjs`
|
|
also writes a schema-backed
|
|
`gamecult.eve.unity_uitoolkit_projection.v1` JSON projection artifact at
|
|
`artifacts/eveunity-uitoolkit-capture/latest/unity-uitoolkit-projection.json`.
|
|
That artifact proves provider-advertised UI Toolkit projection, embedded
|
|
slots, and sidecar plugin projection metadata without pretending to be a
|
|
rendered Unity frame.
|
|
|
|
TUI capture evidence is already typed even though EveTui remains incubating.
|
|
`tools/evetui/evetui-capture-artifact.mjs` lowers the Aetheria world surface
|
|
through `EveTuiShell` into `gamecult.eve.tui_grid.v1` and writes
|
|
`artifacts/evetui-capture/latest/tui-grid.json`. The parity export includes
|
|
that record as `runtime.captureArtifacts[]`; runtime-owner consumers can assert
|
|
it without depending on Eve's source layout. The remaining blocker is
|
|
owner-repo production of the same capture path, not absence of a cell-grid
|
|
artifact.
|
|
|
|
Electron runtime evidence is consumed from the `EveElectron` owner repo.
|
|
Eve core no longer manufactures a JSON shell projection and presents it as
|
|
runtime capture evidence. EveElectron produces native offscreen-painted PNGs
|
|
for the generic world fixture and Aetheria, emits hashed runtime witnesses, and
|
|
the parity harness attaches both witnesses to the conformance export.
|
|
|
|
Unity scene runtime evidence is now consumed from the `EveUnity` owner repo
|
|
through the parity runtime's `sourceRoot`. Eve does not generate a substitute
|
|
JSON scene capture. Until EveUnity attaches a real PlayMode PNG or frame, the
|
|
capture contract reports `contract-artifact-missing` and remains visibly
|
|
pending. The owner runtime declares `providerSurfaceSession` and carries
|
|
`EveUnitySceneClientSession`, a provider-snapshot boundary that lowers the
|
|
active surface and emits `gamecult.eve.command.v1` intents without Aetheria
|
|
types. It also declares `providerSurfaceSource` through
|
|
`EveUnitySceneProviderConnection`, `IEveUnitySceneProviderSurfaceSource`, and
|
|
`IEveUnitySceneCommandSink`, so the live CultMesh/CultNet adapter has a narrow
|
|
runtime-owned port to implement. The runtime now also declares
|
|
`providerSurfaceDocumentSource`: `IEveUnitySceneProviderSurfaceDocumentSource`,
|
|
`EveUnitySceneProviderSurfaceDocument`, and
|
|
`EveUnitySceneProviderSurfaceDocumentSource` convert provider-authored surface
|
|
documents into snapshots before lowering, so the future CultMesh/CultCache
|
|
reader can own document delivery without importing Aetheria types. The runtime
|
|
now also declares
|
|
`livePlayableWorldClient`: `EveUnityPlayableWorldLiveClient` composes the
|
|
provider connection with `EveUnityPlayableWorldPresenter`, applies every live
|
|
snapshot to the scene sink, and delegates player intent back to the advertised
|
|
provider command boundary. The runtime now also declares
|
|
`playableWorldRuntimeHost`: `EveUnityPlayableWorldRuntime` composes provider
|
|
surface documents, provider asset manifest documents, command sink, optional
|
|
receipt source, asset manifest cache, presenter, and scene sink into one generic
|
|
Unity playable-world client. `EveUnityLivePlayableWorldAssetProvider` lets a
|
|
GameObject scene resolve prefabs through the active world's provider manifest
|
|
without importing provider prefab classes. The runtime now also declares
|
|
`providerCommandReceipts`: `IEveUnitySceneCommandReceiptSource` and
|
|
`EveUnitySceneCommandReceipt` keep provider-owned pending/accepted/denied/
|
|
reconciled command status distinct from scene state; accepted or reconciled
|
|
receipts can refresh the provider snapshot, but receipts do not mutate world
|
|
entities. The runtime now also declares
|
|
`playableWorldScenePresentation`: `EveUnityPlayableWorldPresenter` maps
|
|
provider-authored entity rows and asset refs into scene sink operations while
|
|
removing entities absent from later provider snapshots. The runtime now also
|
|
declares `unityGameObjectSceneSink`: `EveUnityGameObjectPlayableWorldSceneSink`
|
|
creates or updates generic `GameObject` instances, attaches
|
|
`EveUnityPlayableWorldEntityMarker`, and resolves prefabs through a swappable
|
|
asset-provider hook. The runtime now also declares
|
|
`providerAssetManifestResolution`: `EveUnityPlayableWorldAssetManifest` and
|
|
`EveUnityManifestGameObjectAssetProvider` map provider-authored asset refs and
|
|
entity kinds to Unity resource/prefab keys through data. The runtime now also
|
|
declares `providerAssetManifestSource`: `IEveUnityPlayableWorldAssetManifestSource`
|
|
and `EveUnityPlayableWorldAssetManifestCache` key live manifest updates by the
|
|
`playableWorld.AssetManifest` pointer, giving the future CultMesh/CultCache
|
|
reader a narrow slot that does not change scene lowering. The runtime now also
|
|
declares `providerAssetManifestDocumentSource`:
|
|
`gamecult.eve.unity_playable_world_asset_manifest.v1`,
|
|
`IEveUnityPlayableWorldAssetManifestDocumentSource`, and
|
|
`EveUnityPlayableWorldAssetManifestDocumentSource` convert provider-authored
|
|
manifest documents into the runtime cache without importing Aetheria asset
|
|
classes. The remaining blocker is the live CultMesh/CultNet adapter, concrete
|
|
CultMesh/CultCache readers for provider surface and asset manifest documents,
|
|
and Unity screenshot or frame-capture PNG production from EveUnity.
|
|
|
|
Runtime capture probe coverage is exported as `runtimeCaptureProbeCoverage[]`.
|
|
Each record joins runtime status, capture owner, lifecycle capture contract,
|
|
current semantic/cell-grid artifact, pending proofs, and artifact errors. This
|
|
keeps `json-projection` evidence useful without letting it impersonate the
|
|
contracted `png` artifact for Unity or Electron. Runtime-owner consumers can
|
|
assert the ledger with
|
|
`--expect-runtime-capture-probe <runtimeId:status:contractArtifactKind:captureOwnerRepo>`.
|
|
|
|
EveUnity split handoff evidence:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\scripts\run-eveunity-split-handoff-smoke.ps1
|
|
```
|
|
|
|
That script validates
|
|
`packages/org.gamecult.eve.unity-uitoolkit/eveunity-split-handoff.json` against
|
|
the runtime capability manifest. The handoff names the package paths, lifecycle
|
|
stages, Eve contracts, forbidden imports, and external proofs that must become
|
|
EveUnity-owned before the runtime leaves incubation.
|
|
|
|
The smoke runner writes:
|
|
|
|
- `artifacts/parity-smoke/<timestamp>/parity-smoke.md`
|
|
- `artifacts/parity-smoke/<timestamp>/parity-smoke.json`
|
|
- one PNG per target that has a real capture body.
|
|
|
|
## Current Checks
|
|
|
|
The first pass is semantic and fixture-driven:
|
|
|
|
- compile local CultUI `.eve` fixtures;
|
|
- load local JSON surface fixtures;
|
|
- check provider id;
|
|
- check required component kinds;
|
|
- check minimum component counts where useful;
|
|
- check required style tokens;
|
|
- check required bindings;
|
|
- check retained slider skins and control parts.
|
|
- record the responsive viewport matrix used by screenshot smoke.
|
|
- export `screenshotComparisonMetrics[]` records for structure, color tokens,
|
|
bounding boxes, and text presence.
|
|
|
|
This already catches the most embarrassing class of parity lie: a runtime or
|
|
fixture claiming to render CultUI while the retained tree no longer contains
|
|
the partitions, bindings, tokens, or slider anatomy the renderer is supposed to
|
|
lower.
|
|
|
|
Screenshot comparison metrics are intentionally not byte-identical image
|
|
checks. Structure and color-token scores come from the authored surface
|
|
contract; text-presence scores come from authored text-bearing nodes; bounding
|
|
box records name whether authored layout boxes exist or whether a runtime still
|
|
owes a capture/layout probe. A missing Unity, Electron, TUI, or Direct2D capture
|
|
body therefore appears as `pending-capture`, not as fake visual parity.
|
|
|
|
The web reference has the first measured bounding-box probes. The harness runs
|
|
`scripts/run-web-reference-layout-probe-smoke.ps1`, which builds the browser
|
|
lowerer and uses Chrome headless to write
|
|
`artifacts/web-reference-layout-probe/latest/embedded-surface.json` and
|
|
`artifacts/web-reference-layout-probe/latest/sai-vn.json` as
|
|
`gamecult.eve.web_layout_probe.v1`. Parity consumes those artifacts and marks
|
|
`web:embedded-surface:bounding-boxes` and `web:sai-vn:bounding-boxes` as `pass`
|
|
with `evidenceLayer: runtime-layout-probe`.
|
|
|
|
The fixture matrix also includes `embedded-surface`, which proves that nested
|
|
CultMesh document slots survive the shared surface contract. The web reference,
|
|
Flutter parity body, Unity UI Toolkit lowerer, iOS UIKit renderer, and native
|
|
Android Kotlin dashboard renderer all need to understand
|
|
`surface.slot`/`embeddedDocuments`. Rust participates at the CultMesh document
|
|
sync layer: it must preserve the same `gamecult.eve.surface.v1` slot contract
|
|
through typed document replication even when it is not painting pixels.
|
|
|
|
Nested surface support is a required feature for every active GUI runtime in
|
|
`tools/parity/parity-manifest.json`. Active runtimes list
|
|
`requiredFixtures: ["embedded-surface"]` and
|
|
`supportedFeatures: ["embeddedDocuments"]`; the semantic report prints both so a
|
|
runtime cannot quietly fall out of the contract. Runtime entries also use
|
|
`expectedSourceSymbols` for the renderer files that must contain the slot
|
|
lowering path, so a runtime cannot keep a green body merely because its source
|
|
file exists. The shared fixture is `web/fixtures/cultui-embedded-surface.json`,
|
|
and renderer-specific tests should load that fixture rather than hand-authoring
|
|
a local substitute.
|
|
|
|
## Runtime Status
|
|
|
|
The harness tracks every target runtime:
|
|
|
|
- Web reference: active semantic and screenshot target through Chrome headless
|
|
using the provider query parameter. Required nested-surface evidence:
|
|
`node --test web\eve-dsl.test.mjs` plus the `embedded-surface` fixture in
|
|
`tools/parity/run-parity.mjs`.
|
|
- Web responsive layout: Chrome headless emits phone, tablet, and desktop PNGs.
|
|
- iOS / UIKit: screenshot target through SSH and EveCanvas'
|
|
`/var/mobile/Library/EveCanvas/capture-request` service. Current iOS capture
|
|
is fixed-device until a simulator or device-resize adapter exists. Required
|
|
nested-surface evidence: run `scripts/run-parity-smoke.ps1 -ProviderId
|
|
gamecult.eve.embedded-demo` against the device target.
|
|
- Windows / Flutter: screenshot target through the Flutter parity golden smoke,
|
|
with phone, tablet, and desktop goldens. Required nested-surface evidence:
|
|
`flutter test --plain-name embedded_surface_fixture_contract` plus
|
|
`E:\Projects\EveFlutter\scripts\capture-flutter-parity.ps1 -FixtureId
|
|
gamecult.eve.embedded-demo`.
|
|
- Linux / Flutter: screenshot target through Nightwing over SSH. The smoke
|
|
stages the EveFlutter owner repo, runs Flutter goldens on Nightwing, and pulls back
|
|
phone, tablet, and desktop PNGs. Required nested-surface evidence:
|
|
`E:\Projects\EveFlutter\scripts\capture-linux-flutter-parity.ps1 -FixtureId
|
|
gamecult.eve.embedded-demo`.
|
|
- Android / Flutter: screenshot target through the same Flutter renderer,
|
|
packaged as a debug APK, installed on Periwinkle through `adb`, and captured
|
|
with optional `adb shell wm size`, orientation control, and `adb exec-out
|
|
screencap`; the script restores device size and rotation after each viewport.
|
|
Required nested-surface evidence: `E:\Projects\EveFlutter\scripts\capture-android-flutter-parity.ps1
|
|
-FixtureId gamecult.eve.embedded-demo`.
|
|
- Android / Kotlin device edge: lightweight native CultMesh dashboard and
|
|
sensor host. Required nested-surface evidence:
|
|
`android/app/src/main/java/org/gamecult/eve/MainActivity.kt` renders
|
|
`surface.slot` with a content description containing the embedded slot
|
|
identity, and `node tools/parity/run-parity.mjs` reports
|
|
`embeddedDocuments` support for `android-kotlin`. It does not consume plugin
|
|
fixtures until EveAndroid grows a plugin projection adapter; Android Flutter
|
|
is the Android-side plugin projection acceptance target. Kotlin declares
|
|
`styleTokens` only after proving token-aware text roles, text-size parsing,
|
|
and `fontBody` / `fontTitle` / `fontMono` typeface mapping in
|
|
`MainActivity.kt`.
|
|
- Rust / CultMesh: typed document runtime rather than a CultUI renderer.
|
|
Required nested-surface evidence: `cargo test -p cultnet-rs
|
|
rust_preserves_cultui_embedded_surface_slots_through_typed_document_sync`
|
|
in CultLib.
|
|
- Fensalir Direct2D: specialized native target with a runtime-pack
|
|
`gamecult.eve.surface.v1` adapter fixture; runtime-owned command smoke and
|
|
Direct2D capture are still missing.
|
|
|
|
Pending runtimes are allowed. Silent fake parity is not.
|
|
|
|
## Next Cuts
|
|
|
|
1. Extend runtime-owned image/layout probes to the Unity/Electron capture
|
|
blockers with actual owner-produced image artifacts and move EveTui's JSON
|
|
grid capture path into the EveTui owner repo.
|
|
2. Normalize text scale and font loading across web, Flutter Android, Flutter
|
|
desktop, and iOS.
|
|
3. Give iOS a real `vn.stage` scene compositor instead of compact stacked
|
|
fixture lowering.
|
|
4. Replace Flutter golden screenshots with native window captures once the
|
|
Flutter app body can emit a desktop frame without test harness help.
|
|
5. Add Direct2D frame capture once the Eve-to-`AquariumUiDocument` adapter
|
|
exists.
|