Clarify optional nested plugin projection boundaries

This commit is contained in:
Meta Vens 2026-07-09 13:30:40 +01:00
commit 0e2516e256
8 changed files with 47 additions and 55 deletions

View file

@ -398,15 +398,15 @@ Recently cut:
- Provider/runtime/plugin projection coverage is now exported as - Provider/runtime/plugin projection coverage is now exported as
`providerRuntimePluginProjectionCoverage[]`. The runtime-owner smoke proves `providerRuntimePluginProjectionCoverage[]`. The runtime-owner smoke proves
the Sai VN provider surface lowers fully in web, lowers in Unity UI Toolkit the Sai VN provider surface lowers fully in web, lowers in Unity UI Toolkit
with optional independent Norn and TeX nested plugin projection when those and Android Flutter with optional independent Norn and TeX nested plugin
plugins are available, and does not let UIKit's generic embedded-document path projection when those plugins are available, and does not let UIKit's generic
impersonate required Sai VN, optional Norn graph, or optional TeX math embedded-document path impersonate required Sai VN, optional Norn graph, or
projection. optional TeX math projection.
- Runtime/plugin projection gaps are now exported as - Runtime/plugin projection gaps are now exported as
`runtimePluginProjectionGaps[]`. The runtime-owner smoke asserts remaining `runtimePluginProjectionGaps[]`. Device-edge runtimes no longer consume the
device-edge plugin gaps as typed records, so missing Sai, Norn, or TeX Sai fixture as failed projection clients; missing Sai, Norn, or TeX support is
projection support is owned by the runtime split target and does not imply recorded only on runtimes that actually claim plugin projection work, so plugin
those plugin semantics should move into Eve core or Aetheria product code. semantics do not drift into Eve core or Aetheria product code.
- Split target blockers are now exported as `splitTargetBlockers[]` and as - Split target blockers are now exported as `splitTargetBlockers[]` and as
per-target `blockerRecords[]` with blocker kind, subject, owner, and source per-target `blockerRecords[]` with blocker kind, subject, owner, and source
text. The split-target consumer smoke asserts Unity scene status/plugin text. The split-target consumer smoke asserts Unity scene status/plugin
@ -761,12 +761,11 @@ Recently cut:
the parity harness validates embedded-slot preservation, command descriptors, the parity harness validates embedded-slot preservation, command descriptors,
runtime authority witnesses, and style tokens. Direct2D capture and runtime authority witnesses, and style tokens. Direct2D capture and
runtime-owned command smoke remain the activation blockers. runtime-owned command smoke remain the activation blockers.
- UIKit and Kotlin device-edge runtimes now declare unsupported plugin - UIKit and Kotlin device-edge runtimes no longer consume the Sai plugin fixture
projection explicitly for separate Sai, Norn, and TeX capabilities. They as projection acceptance targets. They remain generic embedded-document and
remain generic embedded-document and device-edge proofs; plugin projection device-edge proofs; plugin projection authority belongs to EveFlutter,
authority belongs to EveFlutter, EveUnity, or future runtime-specific EveUnity, EveElectron, EveTui, or future runtime-specific adapters when those
projection adapters instead of being reported as unexplained active capability bodies earn the claim.
gaps.
- The web reference no longer hardcodes the local provider list in - The web reference no longer hardcodes the local provider list in
`web/surface.js`. It loads `web/local-provider-catalog.json`, then opens `web/surface.js`. It loads `web/local-provider-catalog.json`, then opens
advertisement-backed entries for Aetheria, Repixelizer, and Sai through the advertisement-backed entries for Aetheria, Repixelizer, and Sai through the

View file

@ -145,9 +145,11 @@ reference probe provider source layout.
Declared runtime/plugin projection gaps are exported as Declared runtime/plugin projection gaps are exported as
`runtimePluginProjectionGaps[]`. These records carry runtime id, runtime owner, `runtimePluginProjectionGaps[]`. These records carry runtime id, runtime owner,
split target, plugin id, reason, severity, and fixture lists so EveUnity, split target, plugin id, reason, severity, and fixture lists so EveUnity,
EveElectron, Sai, Norn, and TeX owners can distinguish "runtime cannot project EveElectron, Sai, Norn, and TeX owners can distinguish "this projection runtime
this plugin yet" from "plugin semantics belong in Eve core." Consumer smokes can cannot project the plugin yet" from "plugin semantics belong in Eve core."
assert them with `--expect-runtime-plugin-gap <runtimeId:pluginId:ownerRepo>`. 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 The same claims are exported as `runtimePluginProjectionCoverage[]`, including
positive `supported` projection adapters and declared `unsupported` gaps. This positive `supported` projection adapters and declared `unsupported` gaps. This
lets runtime and plugin owners consume one ledger for "Unity UI Toolkit has lets runtime and plugin owners consume one ledger for "Unity UI Toolkit has
@ -510,7 +512,9 @@ The harness tracks every target runtime:
`android/app/src/main/java/org/gamecult/eve/MainActivity.kt` renders `android/app/src/main/java/org/gamecult/eve/MainActivity.kt` renders
`surface.slot` with a content description containing the embedded slot `surface.slot` with a content description containing the embedded slot
identity, and `node tools/parity/run-parity.mjs` reports identity, and `node tools/parity/run-parity.mjs` reports
`embeddedDocuments` support for `android-kotlin`. `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.
- Rust / CultMesh: typed document runtime rather than a CultUI renderer. - Rust / CultMesh: typed document runtime rather than a CultUI renderer.
Required nested-surface evidence: `cargo test -p cultnet-rs Required nested-surface evidence: `cargo test -p cultnet-rs
rust_preserves_cultui_embedded_surface_slots_through_typed_document_sync` rust_preserves_cultui_embedded_surface_slots_through_typed_document_sync`

View file

@ -35,8 +35,8 @@ proves the same contract at the CultMesh typed document sync layer.
| Windows / Flutter | Active shared graphical smoke target | `flutter/eve_parity` loads exported `gamecult.eve.surface.v1` fixture JSON, including `embedded-surface`, and emits phone/tablet/desktop golden PNGs through `capture-flutter-parity.ps1` | Needs native window capture and tighter text/style normalization | | Windows / Flutter | Active shared graphical smoke target | `flutter/eve_parity` loads exported `gamecult.eve.surface.v1` fixture JSON, including `embedded-surface`, and emits phone/tablet/desktop golden PNGs through `capture-flutter-parity.ps1` | Needs native window capture and tighter text/style normalization |
| Linux / Flutter | Active shared graphical smoke target | Nightwing runs the Flutter parity goldens, including embedded surface slots, over SSH and returns phone/tablet/desktop PNGs | Needs native window capture and runner health checks | | Linux / Flutter | Active shared graphical smoke target | Nightwing runs the Flutter parity goldens, including embedded surface slots, over SSH and returns phone/tablet/desktop PNGs | Needs native window capture and runner health checks |
| Android / Flutter | Active shared graphical smoke target | The same Flutter parity app is built as an APK, installed on Periwinkle, and captured at phone/tablet/desktop plus native physical-panel orientations | Needs live provider picker and command transport beyond fixture assets | | Android / Flutter | Active shared graphical smoke target | The same Flutter parity app is built as an APK, installed on Periwinkle, and captured at phone/tablet/desktop plus native physical-panel orientations | Needs live provider picker and command transport beyond fixture assets |
| iOS / UIKit | Active native screenshot target | SSH capture stages selected fixture JSON, EveCanvas renders it, and emits a PNG from `/var/mobile/Library/EveCanvas/latest-screenshot.png`; `embedded-surface` is part of the required fixture matrix | Plugin projection is explicitly unsupported until EveIOS owns adapters; still needs provider picker and command transport | | iOS / UIKit | Active native screenshot target | SSH capture stages selected fixture JSON, EveCanvas renders it, and emits a PNG from `/var/mobile/Library/EveCanvas/latest-screenshot.png`; `embedded-surface` is part of the required fixture matrix | Not a plugin projection acceptance target until EveIOS owns adapters; still needs provider picker and command transport |
| Android / Kotlin device edge | Active lightweight renderer | Native APK consumes CultMesh dashboard/sensor documents and preserves `surface.slot` / `embeddedDocuments` identity in the dashboard renderer | Plugin projection is explicitly unsupported; full graphical parity belongs to Flutter unless EveAndroid grows adapters | | Android / Kotlin device edge | Active lightweight renderer | Native APK consumes CultMesh dashboard/sensor documents and preserves `surface.slot` / `embeddedDocuments` identity in the dashboard renderer | Not a plugin projection acceptance target; Android Flutter owns full graphical/plugin parity unless EveAndroid grows adapters |
| Rust / CultMesh | Document-sync contract runtime | CultLib replicates the `gamecult.eve.surface.v1` embedded slot contract through typed document sync | Not a pixel renderer | | Rust / CultMesh | Document-sync contract runtime | CultLib replicates the `gamecult.eve.surface.v1` embedded slot contract through typed document sync | Not a pixel renderer |
| Fensalir Direct2D | External adapter spike, not active parity runtime | Fensalir has `src/Aquarium.EveSurface/EveSurfaceRuntime.cs`, reads an Eve broker, lowers into `AquariumUiDocument` / `DirectWriteOverlay`, and now has a runtime-pack `gamecult.eve.surface.v1` fixture in Eve | Needs runtime-owned command smoke, DirectWrite/Direct2D frame capture, and a clear reason to stay separate from Flutter for desktop UI | | Fensalir Direct2D | External adapter spike, not active parity runtime | Fensalir has `src/Aquarium.EveSurface/EveSurfaceRuntime.cs`, reads an Eve broker, lowers into `AquariumUiDocument` / `DirectWriteOverlay`, and now has a runtime-pack `gamecult.eve.surface.v1` fixture in Eve | Needs runtime-owned command smoke, DirectWrite/Direct2D frame capture, and a clear reason to stay separate from Flutter for desktop UI |

View file

@ -71,6 +71,13 @@
"minLength": 1 "minLength": 1
} }
}, },
"optionalNestedPlugins": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"splitTarget": { "splitTarget": {
"type": "string" "type": "string"
} }

View file

@ -105,6 +105,9 @@ node $consumerScript $consumerExport `
--expect-runtime-plugin-projection tui:tex.math:supported:EveTui ` --expect-runtime-plugin-projection tui:tex.math:supported:EveTui `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:web:sai.vn:supported:Eve ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:web:sai.vn:supported:Eve `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:web:tex.math:optional-supported:Eve ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:web:tex.math:optional-supported:Eve `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:android-flutter:sai.vn:supported:EveFlutter `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:android-flutter:norn.graph:optional-supported:EveFlutter `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:android-flutter:tex.math:optional-supported:EveFlutter `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:unity-uitoolkit:sai.vn:supported:EveUnity ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:unity-uitoolkit:sai.vn:supported:EveUnity `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:unity-uitoolkit:norn.graph:optional-supported:EveUnity ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:unity-uitoolkit:norn.graph:optional-supported:EveUnity `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:unity-uitoolkit:tex.math:optional-supported:EveUnity ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:unity-uitoolkit:tex.math:optional-supported:EveUnity `
@ -117,8 +120,6 @@ node $consumerScript $consumerExport `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:tui:sai.vn:supported:EveTui ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:tui:sai.vn:supported:EveTui `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:tui:norn.graph:optional-supported:EveTui ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:tui:norn.graph:optional-supported:EveTui `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:tui:tex.math:optional-supported:EveTui ` --expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:tui:tex.math:optional-supported:EveTui `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:ios-uikit:sai.vn:unsupported-runtime-projection:EveIOS `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:ios-uikit:norn.graph:optional-unsupported-runtime-projection:EveIOS `
--expect-runtime-handoff unity-uitoolkit ` --expect-runtime-handoff unity-uitoolkit `
--expect-runtime-command-schema web:gamecult.eve.command.v1 ` --expect-runtime-command-schema web:gamecult.eve.command.v1 `
--expect-runtime-command-schema windows-flutter:gamecult.eve.command.v1 ` --expect-runtime-command-schema windows-flutter:gamecult.eve.command.v1 `

View file

@ -156,7 +156,9 @@
{ {
"pluginId": "sai.vn", "pluginId": "sai.vn",
"capabilities": ["vn.stage", "story.choose", "story.continue", "story.jump"] "capabilities": ["vn.stage", "story.choose", "story.continue", "story.jump"]
}, }
],
"optionalNestedPlugins": [
{ {
"pluginId": "norn.graph", "pluginId": "norn.graph",
"capabilities": ["embed.norn"] "capabilities": ["embed.norn"]
@ -1301,22 +1303,9 @@
"splitTarget": "EveIOS", "splitTarget": "EveIOS",
"graduationTrigger": "Split when UIKit renderer has generic surface lowering, sensor edge release flow, and device CI independent of Eve core.", "graduationTrigger": "Split when UIKit renderer has generic surface lowering, sensor edge release flow, and device CI independent of Eve core.",
"requiredFixtures": ["embedded-surface"], "requiredFixtures": ["embedded-surface"],
"pluginFixtures": ["sai-vn"], "pluginFixtures": [],
"supportedFeatures": ["embeddedDocuments"], "supportedFeatures": ["embeddedDocuments"],
"unsupportedPlugins": [ "unsupportedPlugins": [],
{
"pluginId": "sai.vn",
"reason": "UIKit smoke proves generic embedded document lowering and capture only; Sai VN projection belongs to EveFlutter/EveUnity or a future EveIOS projection adapter."
},
{
"pluginId": "norn.graph",
"reason": "UIKit smoke preserves embed.norn as generic Eve structure; Norn graph projection is not implemented in this runtime."
},
{
"pluginId": "tex.math",
"reason": "UIKit smoke preserves embed.tex as generic Eve structure; TeX projection is not implemented in this runtime."
}
],
"expectedPaths": ["Sources/EVEViewController.mm", "scripts/capture-eve-screenshot.ps1"], "expectedPaths": ["Sources/EVEViewController.mm", "scripts/capture-eve-screenshot.ps1"],
"expectedSourceSymbols": [ "expectedSourceSymbols": [
{ {
@ -1393,22 +1382,9 @@
"splitTarget": "EveAndroid", "splitTarget": "EveAndroid",
"graduationTrigger": "Split when Kotlin device edge has generic surface traversal, sensor release flow, and Android-specific CI.", "graduationTrigger": "Split when Kotlin device edge has generic surface traversal, sensor release flow, and Android-specific CI.",
"requiredFixtures": ["embedded-surface"], "requiredFixtures": ["embedded-surface"],
"pluginFixtures": ["sai-vn"], "pluginFixtures": [],
"supportedFeatures": ["cultmesh-dashboard-documents", "sensor-uplink", "embeddedDocuments"], "supportedFeatures": ["cultmesh-dashboard-documents", "sensor-uplink", "embeddedDocuments"],
"unsupportedPlugins": [ "unsupportedPlugins": [],
{
"pluginId": "sai.vn",
"reason": "Kotlin device edge is a lightweight CultMesh/sensor dashboard proof; Sai VN projection belongs to Flutter, Unity, or a future Android projection adapter."
},
{
"pluginId": "norn.graph",
"reason": "Kotlin device edge preserves embed.norn as generic Eve structure; Norn graph projection is not implemented in this runtime."
},
{
"pluginId": "tex.math",
"reason": "Kotlin device edge preserves embed.tex as generic Eve structure; TeX projection is not implemented in this runtime."
}
],
"expectedPaths": ["android/app/src/main/java/org/gamecult/eve/MainActivity.kt", "scripts/build-android.ps1"], "expectedPaths": ["android/app/src/main/java/org/gamecult/eve/MainActivity.kt", "scripts/build-android.ps1"],
"expectedSourceSymbols": [ "expectedSourceSymbols": [
{ {

View file

@ -235,6 +235,7 @@ async function evaluateFixture(fixture) {
ownerRepo: fixture.ownerRepo || "", ownerRepo: fixture.ownerRepo || "",
surface: fixture.surface || {}, surface: fixture.surface || {},
requiredPlugins: fixture.requiredPlugins || [], requiredPlugins: fixture.requiredPlugins || [],
optionalNestedPlugins: fixture.optionalNestedPlugins || [],
status: checks.every(check => check.pass) ? "pass" : "fail", status: checks.every(check => check.pass) ? "pass" : "fail",
durationMs: Date.now() - startedAt, durationMs: Date.now() - startedAt,
providerId: state.providerId, providerId: state.providerId,
@ -1899,6 +1900,7 @@ function buildConformanceExport(report) {
exitCriteria: fixture.metadata?.exitCriteria || "", exitCriteria: fixture.metadata?.exitCriteria || "",
asserts: fixture.metadata?.asserts || [], asserts: fixture.metadata?.asserts || [],
requiredPlugins: fixture.requiredPlugins || [], requiredPlugins: fixture.requiredPlugins || [],
optionalNestedPlugins: fixture.optionalNestedPlugins || fixture.metadata?.optionalNestedPlugins || [],
})); }));
const runtimeTargets = pack.id === "runtime" const runtimeTargets = pack.id === "runtime"
? (report.runtimes || []).map(runtime => ({ ? (report.runtimes || []).map(runtime => ({

View file

@ -15,10 +15,13 @@
"embed.norn component", "embed.norn component",
"embed.tex component", "embed.tex component",
"story command descriptors", "story command descriptors",
"plugin capability requirements" "required Sai plugin capability",
"optional nested plugin composition"
], ],
"requiredPlugins": [ "requiredPlugins": [
"sai.vn", "sai.vn"
],
"optionalNestedPlugins": [
"norn.graph", "norn.graph",
"tex.math" "tex.math"
], ],