diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index a25d2f8..299f4dd 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -398,15 +398,15 @@ Recently cut: - Provider/runtime/plugin projection coverage is now exported as `providerRuntimePluginProjectionCoverage[]`. The runtime-owner smoke proves 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 - plugins are available, and does not let UIKit's generic embedded-document path - impersonate required Sai VN, optional Norn graph, or optional TeX math - projection. + and Android Flutter with optional independent Norn and TeX nested plugin + projection when those plugins are available, and does not let UIKit's generic + embedded-document path impersonate required Sai VN, optional Norn graph, or + optional TeX math projection. - Runtime/plugin projection gaps are now exported as - `runtimePluginProjectionGaps[]`. The runtime-owner smoke asserts remaining - device-edge plugin gaps as typed records, so missing Sai, Norn, or TeX - projection support is owned by the runtime split target and does not imply - those plugin semantics should move into Eve core or Aetheria product code. + `runtimePluginProjectionGaps[]`. Device-edge runtimes no longer consume the + Sai fixture as failed projection clients; missing Sai, Norn, or TeX support is + recorded only on runtimes that actually claim plugin projection work, so plugin + semantics do not drift into Eve core or Aetheria product code. - Split target blockers are now exported as `splitTargetBlockers[]` and as per-target `blockerRecords[]` with blocker kind, subject, owner, and source 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, runtime authority witnesses, and style tokens. Direct2D capture and runtime-owned command smoke remain the activation blockers. -- UIKit and Kotlin device-edge runtimes now declare unsupported plugin - projection explicitly for separate Sai, Norn, and TeX capabilities. They - remain generic embedded-document and device-edge proofs; plugin projection - authority belongs to EveFlutter, EveUnity, or future runtime-specific - projection adapters instead of being reported as unexplained active capability - gaps. +- UIKit and Kotlin device-edge runtimes no longer consume the Sai plugin fixture + as projection acceptance targets. They remain generic embedded-document and + device-edge proofs; plugin projection authority belongs to EveFlutter, + EveUnity, EveElectron, EveTui, or future runtime-specific adapters when those + bodies earn the claim. - The web reference no longer hardcodes the local provider list in `web/surface.js`. It loads `web/local-provider-catalog.json`, then opens advertisement-backed entries for Aetheria, Repixelizer, and Sai through the diff --git a/docs/parity-testing-harness.md b/docs/parity-testing-harness.md index ee365ad..d18d9b3 100644 --- a/docs/parity-testing-harness.md +++ b/docs/parity-testing-harness.md @@ -145,9 +145,11 @@ 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 "runtime cannot project -this plugin yet" from "plugin semantics belong in Eve core." Consumer smokes can -assert them with `--expect-runtime-plugin-gap `. +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 `. 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 @@ -510,7 +512,9 @@ The harness tracks every target runtime: `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`. + `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. Required nested-surface evidence: `cargo test -p cultnet-rs rust_preserves_cultui_embedded_surface_slots_through_typed_document_sync` diff --git a/docs/renderer-parity.md b/docs/renderer-parity.md index 19af8e6..4adc471 100644 --- a/docs/renderer-parity.md +++ b/docs/renderer-parity.md @@ -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 | | 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 | -| 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 | -| 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 | +| 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 | 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 | | 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 | diff --git a/schemas/gamecult.eve.conformance_fixture.v1.schema.json b/schemas/gamecult.eve.conformance_fixture.v1.schema.json index 0fb6db8..39050b0 100644 --- a/schemas/gamecult.eve.conformance_fixture.v1.schema.json +++ b/schemas/gamecult.eve.conformance_fixture.v1.schema.json @@ -71,6 +71,13 @@ "minLength": 1 } }, + "optionalNestedPlugins": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + }, "splitTarget": { "type": "string" } diff --git a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 index 29d42bb..e1b6b17 100644 --- a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 @@ -105,6 +105,9 @@ node $consumerScript $consumerExport ` --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: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:norn.graph: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: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: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-command-schema web:gamecult.eve.command.v1 ` --expect-runtime-command-schema windows-flutter:gamecult.eve.command.v1 ` diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index 4604f3d..a95ac7f 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -156,7 +156,9 @@ { "pluginId": "sai.vn", "capabilities": ["vn.stage", "story.choose", "story.continue", "story.jump"] - }, + } + ], + "optionalNestedPlugins": [ { "pluginId": "norn.graph", "capabilities": ["embed.norn"] @@ -1301,22 +1303,9 @@ "splitTarget": "EveIOS", "graduationTrigger": "Split when UIKit renderer has generic surface lowering, sensor edge release flow, and device CI independent of Eve core.", "requiredFixtures": ["embedded-surface"], - "pluginFixtures": ["sai-vn"], + "pluginFixtures": [], "supportedFeatures": ["embeddedDocuments"], - "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." - } - ], + "unsupportedPlugins": [], "expectedPaths": ["Sources/EVEViewController.mm", "scripts/capture-eve-screenshot.ps1"], "expectedSourceSymbols": [ { @@ -1393,22 +1382,9 @@ "splitTarget": "EveAndroid", "graduationTrigger": "Split when Kotlin device edge has generic surface traversal, sensor release flow, and Android-specific CI.", "requiredFixtures": ["embedded-surface"], - "pluginFixtures": ["sai-vn"], + "pluginFixtures": [], "supportedFeatures": ["cultmesh-dashboard-documents", "sensor-uplink", "embeddedDocuments"], - "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." - } - ], + "unsupportedPlugins": [], "expectedPaths": ["android/app/src/main/java/org/gamecult/eve/MainActivity.kt", "scripts/build-android.ps1"], "expectedSourceSymbols": [ { diff --git a/tools/parity/run-parity.mjs b/tools/parity/run-parity.mjs index c7979bb..6ec55fe 100644 --- a/tools/parity/run-parity.mjs +++ b/tools/parity/run-parity.mjs @@ -235,6 +235,7 @@ async function evaluateFixture(fixture) { ownerRepo: fixture.ownerRepo || "", surface: fixture.surface || {}, requiredPlugins: fixture.requiredPlugins || [], + optionalNestedPlugins: fixture.optionalNestedPlugins || [], status: checks.every(check => check.pass) ? "pass" : "fail", durationMs: Date.now() - startedAt, providerId: state.providerId, @@ -1899,6 +1900,7 @@ function buildConformanceExport(report) { exitCriteria: fixture.metadata?.exitCriteria || "", asserts: fixture.metadata?.asserts || [], requiredPlugins: fixture.requiredPlugins || [], + optionalNestedPlugins: fixture.optionalNestedPlugins || fixture.metadata?.optionalNestedPlugins || [], })); const runtimeTargets = pack.id === "runtime" ? (report.runtimes || []).map(runtime => ({ diff --git a/web/fixtures/sai-vn-surface.conformance.json b/web/fixtures/sai-vn-surface.conformance.json index 4f8d2e6..78b768f 100644 --- a/web/fixtures/sai-vn-surface.conformance.json +++ b/web/fixtures/sai-vn-surface.conformance.json @@ -15,10 +15,13 @@ "embed.norn component", "embed.tex component", "story command descriptors", - "plugin capability requirements" + "required Sai plugin capability", + "optional nested plugin composition" ], "requiredPlugins": [ - "sai.vn", + "sai.vn" + ], + "optionalNestedPlugins": [ "norn.graph", "tex.math" ],