diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index bed549f..1653fcb 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -194,6 +194,10 @@ Work: conformance fixtures are stable. - Move `tex.math` to EvePlugins when TeX source, macro, baseline, cached render, and fallback fixtures are stable. +- Treat nested plugin placement as composition, not custody. A Sai surface may + deploy with nested Norn or TeX surfaces when those plugin sidecars are + available, but Norn and TeX remain independent plugin owners with their own + ABI manifests, capability claims, and conformance packs. Exit criteria: @@ -201,6 +205,8 @@ Exit criteria: - Providers invoke plugins through the ABI object model. - Runtimes declare plugin support through capability manifests. - Unsupported required plugin capabilities appear as visible gaps. +- Optional nested plugin gaps degrade the nested surface; they do not transfer + graph, math, or renderer semantics into the parent plugin. ## Phase 4: Graduate Runtime Bodies @@ -666,6 +672,10 @@ Recently cut: smoke asserts the provider pack, `aetheria-world` fixture, `aetheria` provider entry, and `aetheria-world-command-replay` scenario without reading Eve's parity manifest or dirtying the Aetheria worktree. +- The Aetheria consumer smoke now also asserts frontend extraction boundaries: + web and Unity UI Toolkit are covered generic lowerings, Unity scene remains a + typed EveUnity gap, and the observed Aetheria Electron shell/client paths are + split-handoff evidence to replace with a provider-agnostic EveElectron body. - The parity harness now runs a conformance consumer smoke against a copied `artifacts/conformance/latest` layout, proving the export can be consumed through `index.json` and `packs/*.json` without reading Eve's parity manifest. diff --git a/docs/plugin-architecture.md b/docs/plugin-architecture.md index 7dabf1f..f40da69 100644 --- a/docs/plugin-architecture.md +++ b/docs/plugin-architecture.md @@ -445,7 +445,9 @@ Sai does not own: ## Norn And TeX As First-Class Plugins Norn and TeX are not Sai subfeatures. Sai can place them inside a visual-novel -scene, but ownership stays with their plugins. +scene, but ownership stays with their plugins. Each plugin publishes a +renderer-independent sidecar ABI; runtimes only declare whether they can project +that plugin's advertised capabilities. Norn plugin responsibilities: @@ -497,6 +499,10 @@ briefing without Sai becoming a graph engine or a TeX engine. Sai owns the stage. Norn owns the graph. TeX owns the math. Eve owns the plugin ABI and renderer conformance. The app provider owns live state and receipts. +Fixture co-location is not semantic custody. A TeX ABI fixture may currently +use the Sai VN surface to prove nested placement, but the TeX handoff, manifest, +advertisement, and conformance pack still graduate through EvePlugins. + ## Building An App With Eve And Sai An app that wants VN functionality composes four layers. diff --git a/docs/repo-strategy.md b/docs/repo-strategy.md index 3aa75d2..00e5081 100644 --- a/docs/repo-strategy.md +++ b/docs/repo-strategy.md @@ -33,7 +33,8 @@ Anything else is guilty until it can explain why it protects a core invariant. - `Eve`: kernel contracts, specs, browser reference, and conformance incubation. - `EvePlugins`: first-party reusable plugins while young, such as fields, - world 2D/3D, and TeX. + world 2D/3D, and TeX. These plugins are independent sidecar capabilities, not + hidden features of Sai or any other provider. - `Sai`: owner for the VN/Ink plugin once `sai.vn` graduates. - `Norn`: owner for graph plugin semantics once `norn.graph` graduates. - `EveUnity`, `EveGodot`, `EveFlutter`, `EveElectron`, and similar runtime diff --git a/plugins/incubating/tex-math.plugin-handoff.json b/plugins/incubating/tex-math.plugin-handoff.json new file mode 100644 index 0000000..c4d5e8c --- /dev/null +++ b/plugins/incubating/tex-math.plugin-handoff.json @@ -0,0 +1,52 @@ +{ + "schema": "gamecult.eve.plugin_handoff.v1", + "pluginId": "tex.math", + "ownerRepo": "EvePlugins", + "currentHostRepo": "Eve", + "splitTarget": "EvePlugins/eve-plugin-tex", + "manifestPath": "plugins/incubating/tex-math.plugin.json", + "advertisementPath": "plugins/incubating/tex-math.plugin-advertisement.json", + "abiFixturePath": "plugins/incubating/tex-math.plugin-abi-fixture.json", + "authorityBoundary": "EvePlugins owns TeX source semantics, macro handling, measurement, render requests, cached render results, fallback behavior, and plugin ABI behavior. Eve owns only plugin manifest, advertisement, ABI, provider requirement, and conformance export contracts.", + "moveSets": [ + { + "id": "plugin-manifest", + "destinationOwner": "EvePlugins", + "currentPaths": [ + "plugins/incubating/tex-math.plugin.json", + "plugins/incubating/tex-math.plugin-advertisement.json" + ], + "replacementProof": "EvePlugins publishes tex.math plugin manifest and advertisement from the EvePlugins repo or sidecar daemon." + }, + { + "id": "abi-conformance", + "destinationOwner": "EvePlugins", + "currentPaths": [ + "plugins/incubating/tex-math.plugin-abi-fixture.json", + "web/fixtures/sai-vn-surface.json", + "web/fixtures/sai-vn-surface.conformance.json" + ], + "replacementProof": "EvePlugins owns embed.tex source, macro, measurement, render result, fallback, and ABI conformance cases." + } + ], + "contractInputs": [ + "gamecult.eve.plugin.v1", + "gamecult.eve.plugin_advertisement.v1", + "gamecult.eve.plugin_abi.v1", + "gamecult.eve.plugin_abi_fixture.v1", + "gamecult.eve.conformance_export.v1" + ], + "forbiddenImports": [ + "Aetheria provider state", + "Sai story session internals", + "Norn graph semantics", + "renderer-native projection internals", + "provider command acceptance or receipt authority" + ], + "requiredExternalProofs": [ + "EvePlugins publishes the tex.math sidecar ABI without depending on Eve source layout.", + "EvePlugins owns TeX source, macro, measurement, render result, fallback, and conformance fixtures.", + "Providers consume tex.math through plugin advertisements and ABI operations.", + "Runtimes declare tex.math projection support through runtime capability manifests." + ] +} diff --git a/scripts/run-aetheria-conformance-consumer-smoke.ps1 b/scripts/run-aetheria-conformance-consumer-smoke.ps1 index d3769c0..258ff58 100644 --- a/scripts/run-aetheria-conformance-consumer-smoke.ps1 +++ b/scripts/run-aetheria-conformance-consumer-smoke.ps1 @@ -55,6 +55,23 @@ try { --expect-interactive-world-surface aetheria:aetheria.daemon.game:web-reference:Aetheria ` --expect-interactive-world-surface aetheria:aetheria.daemon.game:unity-scene:Aetheria ` --expect-interactive-world-surface aetheria:aetheria.daemon.editor:unity-uitoolkit:Aetheria ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.game:web-reference:claimed:Eve:web ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-uitoolkit:claimed:EveUnity:unity-uitoolkit ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.game:unity-scene:missing-claim:EveUnity:unity-scene ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.editor:web-reference:claimed:Eve:web ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.editor:unity-uitoolkit:claimed:EveUnity:unity-uitoolkit ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.game:web-reference:covered:Eve:web ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-uitoolkit:covered:EveUnity:unity-uitoolkit ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.game:unity-scene:missing-runtime-claim:EveUnity:unity-scene ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.editor:web-reference:covered:Eve:web ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.editor:unity-uitoolkit:covered:EveUnity:unity-uitoolkit ` + --expect-world-lowering-gap aetheria:aetheria.daemon.game:unity-scene:EveUnity:unity-scene ` + --expect-split-target-blocker "EveUnity:Unity scene runtime body exists outside Aetheria product code" ` + --expect-split-target-blocker "EveElectron:Electron shell runtime body exists outside Aetheria product code" ` + --expect-split-handoff-move EveUnity:unity-scene:unity-scene-runtime-body:replacement-required:no-source-paths:none ` + --expect-split-handoff-move EveUnity:unity-scene:unity-scene-command-transport:replacement-required:no-source-paths:none ` + --expect-split-handoff-move EveElectron:electron-shell:electron-shell-runtime:observed-provider:exists:Aetheria.Rts.Web/Electron ` + --expect-split-handoff-move EveElectron:electron-shell:electron-command-transport:observed-provider:exists:Aetheria.Rts.Web/Client/app.ts ` --expect-provider-command aetheria:aetheria.daemon.commands ` --expect-provider-receipt-state aetheria:accepted ` --expect-provider-receipt-state aetheria:reconciled ` diff --git a/scripts/run-plugin-handoff-smoke.ps1 b/scripts/run-plugin-handoff-smoke.ps1 index be54634..5254d02 100644 --- a/scripts/run-plugin-handoff-smoke.ps1 +++ b/scripts/run-plugin-handoff-smoke.ps1 @@ -1,7 +1,8 @@ param( [string[]] $HandoffPaths = @( "plugins\incubating\sai-vn.plugin-handoff.json", - "plugins\incubating\norn-graph.plugin-handoff.json" + "plugins\incubating\norn-graph.plugin-handoff.json", + "plugins\incubating\tex-math.plugin-handoff.json" ) ) diff --git a/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 b/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 index 266d2dd..63f2d75 100644 --- a/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 @@ -35,8 +35,10 @@ node $consumerScript $consumerExport ` --expect-fixture sai-vn ` --expect-plugin sai.vn ` --expect-plugin norn.graph ` + --expect-plugin tex.math ` --expect-plugin-handoff sai.vn ` --expect-plugin-handoff norn.graph ` + --expect-plugin-handoff tex.math ` --expect-plugin-operation sai.vn:describe ` --expect-plugin-operation sai.vn:validate ` --expect-plugin-operation sai.vn:project ` @@ -64,6 +66,9 @@ node $consumerScript $consumerExport ` --expect-plugin-capability sai.vn:story.jump ` --expect-plugin-capability norn.graph:embed.norn ` --expect-plugin-capability norn.graph:graph.node.activate ` + --expect-plugin-capability tex.math:embed.tex ` + --expect-plugin-capability tex.math:tex.inline ` + --expect-plugin-capability tex.math:tex.block ` --expect-plugin-runtime sai.vn:executable-sidecar ` --expect-plugin-runtime-transport sai.vn:cultmesh ` --expect-plugin-runtime-authority sai.vn:no-provider-state-mutation ` @@ -83,7 +88,27 @@ node $consumerScript $consumerExport ` --expect-plugin-runtime-field norn.graph:sidecar.responseSchema:gamecult.eve.plugin_abi.response.v1 ` --expect-plugin-runtime-field norn.graph:sidecar.stateAuthority:proposes-plugin-state-only-provider-accepts ` --expect-plugin-abi-field norn.graph:lower:expect.commandEnvelope:gamecult.eve.command.v1 ` - --expect-plugin-abi-field norn.graph:apply:expect.receiptSchema:gamecult.eve.command_receipt.v1 + --expect-plugin-abi-field norn.graph:apply:expect.receiptSchema:gamecult.eve.command_receipt.v1 ` + --expect-plugin-operation tex.math:describe ` + --expect-plugin-operation tex.math:validate ` + --expect-plugin-operation tex.math:project ` + --expect-plugin-operation tex.math:lower ` + --expect-plugin-operation tex.math:measure ` + --expect-plugin-operation tex.math:apply ` + --expect-plugin-abi-operation-coverage tex.math:describe:contracted:EvePlugins ` + --expect-plugin-abi-operation-coverage tex.math:lower:contracted:EvePlugins ` + --expect-plugin-abi-operation-coverage tex.math:apply:contracted:EvePlugins ` + --expect-plugin-runtime tex.math:executable-sidecar ` + --expect-plugin-runtime-transport tex.math:cultmesh ` + --expect-plugin-runtime-authority tex.math:no-provider-state-mutation ` + --expect-plugin-runtime-field tex.math:sidecar.processKind:long-running-daemon ` + --expect-plugin-runtime-field tex.math:sidecar.protocol:cultmesh-rpc-with-stdio-dev-transport ` + --expect-plugin-runtime-field tex.math:sidecar.requestSchema:gamecult.eve.plugin_abi.request.v1 ` + --expect-plugin-runtime-field tex.math:sidecar.responseSchema:gamecult.eve.plugin_abi.response.v1 ` + --expect-plugin-runtime-field tex.math:sidecar.stateAuthority:emits-render-results-only-provider-owns-source-state ` + --expect-plugin-abi-field tex.math:lower:expect.loweringKind:typeset-fragment ` + --expect-plugin-abi-field tex.math:lower:expect.fallbackKind:source-text ` + --expect-plugin-abi-field tex.math:apply:expect.receiptSchema:gamecult.eve.plugin_receipt.v1 if ($LASTEXITCODE -ne 0) { throw "Plugin owner conformance consumer smoke failed with exit code $LASTEXITCODE" diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index decc7a4..e3ee596 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -469,12 +469,15 @@ "schemaPath": "schemas/gamecult.eve.plugin.v1.schema.json", "manifestPath": "plugins/incubating/tex-math.plugin.json", "abiFixturePath": "plugins/incubating/tex-math.plugin-abi-fixture.json", + "handoffPath": "plugins/incubating/tex-math.plugin-handoff.json", "advertisementSchemaPath": "schemas/gamecult.eve.plugin_advertisement.v1.schema.json", "advertisementPath": "plugins/incubating/tex-math.plugin-advertisement.json", "expectedPaths": [ "plugins/incubating/tex-math.plugin.json", "plugins/incubating/tex-math.plugin-abi-fixture.json", - "plugins/incubating/tex-math.plugin-advertisement.json" + "plugins/incubating/tex-math.plugin-advertisement.json", + "plugins/incubating/tex-math.plugin-handoff.json", + "scripts/run-plugin-handoff-smoke.ps1" ] } ],