From 41267fbd0cdc531b597a01f75820ea92dd2018cd Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 09:47:25 +0100 Subject: [PATCH] Graduate TeX semantics to EvePlugins --- docs/eve-migration-roadmap.md | 79 +++++---- docs/parity-testing-harness.md | 17 +- .../tex-math.plugin-abi-fixture.json | 87 ---------- .../tex-math.plugin-advertisement.json | 39 ----- .../incubating/tex-math.plugin-handoff.json | 54 ------ plugins/incubating/tex-math.plugin.json | 63 ------- scripts/run-eveplugins-owner-smoke.ps1 | 30 ++++ scripts/run-parity-harness.ps1 | 5 +- scripts/run-plugin-handoff-smoke.ps1 | 156 ------------------ ...lugin-owner-conformance-consumer-smoke.ps1 | 10 +- tools/parity/parity-manifest.json | 26 ++- 11 files changed, 95 insertions(+), 471 deletions(-) delete mode 100644 plugins/incubating/tex-math.plugin-abi-fixture.json delete mode 100644 plugins/incubating/tex-math.plugin-advertisement.json delete mode 100644 plugins/incubating/tex-math.plugin-handoff.json delete mode 100644 plugins/incubating/tex-math.plugin.json create mode 100644 scripts/run-eveplugins-owner-smoke.ps1 delete mode 100644 scripts/run-plugin-handoff-smoke.ps1 diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index 4add64c..28f0eb4 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -179,9 +179,9 @@ Purpose: move semantic ownership out of Eve core. Work: -- Keep `plugins/incubating/sai-vn.plugin.json`, - `plugins/incubating/norn-graph.plugin.json`, and - `plugins/incubating/tex-math.plugin.json` as temporary manifests. +- Consume Sai, Norn, and TeX manifests, advertisements, ABI fixtures, and + executable witnesses from their owner repos. Eve keeps only the ABI schemas, + provider composition fixtures, and capability-gap policy. - Define `gamecult.eve.plugin.v1` and `gamecult.eve.plugin_advertisement.v1` as explicit schemas. First-cut JSON schemas live under `schemas/` and the parity harness validates incubating @@ -192,8 +192,9 @@ Work: and projection fixtures are stable. - Move `norn.graph` to Norn when graph layout, interaction, fallback, and conformance fixtures are stable. -- Move `tex.math` to EvePlugins when TeX source, macro, baseline, cached render, - and fallback fixtures are stable. +- Keep `tex.math` in EvePlugins. Its retained sidecar owns KaTeX parsing, + typeset render results, cache behavior, and source fallback while providers + retain source-state authority. - Treat nested plugin placement as composition, not custody. A Sai surface may deploy with nested Norn or TeX surfaces when those independent plugin sidecars are available, but Sai does not depend on them for VN authority and @@ -285,11 +286,31 @@ Exit criteria: ## Active Work Queue -1. Audit the migration against the target ownership rule and remove any - remaining runtime, plugin-semantic, or provider-product authority from Eve. +1. Graduate the Flutter runtime body into `EveFlutter`; it is now the largest + native projection/build/capture lifecycle still sharing Eve's worktree. +2. Move Aetheria product fixtures and scenarios behind an owner-repo + conformance pack while retaining only the minimal generic world oracle in + Eve. +3. Split `EveConformance` when owner runtimes can consume its schema catalog, + packs, witness attachments, and runner without Eve source-layout knowledge. Recently cut: +- `GameCult/EvePlugins` now owns `tex.math`. The owner sidecar uses KaTeX for + parsing and typesetting and implements `describe`, `validate`, `project`, + `lower`, `measure`, and `apply` over one retained `stdio-ndjson` process. + Its conformance witness proves render-result caching does not mutate provider + source state. Eve consumes the owner manifest, advertisement, ABI fixture, + executable, and witness; the incubating copies and handoff machinery are + deleted. + +- EveUnity now owns `org.gamecult.eve.surface`, + `org.gamecult.eve.unity-uitoolkit`, and `org.gamecult.eve.unity-scene` along + with their package build, test, and capture-request entry points. Aetheria + consumes all three directly from EveUnity. Eve's duplicate package bodies, + split handoff, release proxies, and semantic JSON capture proxy are deleted; + native UI Toolkit PNG capture remains an explicit owner-repo lifecycle gap. + - EveElectron now produces native offscreen-painted 1280x800 PNG captures for both `eve.world-smoke.surface` and `aetheria.daemon.game`. The owner runner emits generic runtime witnesses with dimensions, byte counts, SHA-256 hashes, @@ -995,15 +1016,10 @@ Recently cut: graduates. The conformance export carries `conformanceHandoffPath`, and the generic consumer smoke asserts it so EveConformance split readiness is not trapped in Eve's parity manifest. -- Sai and TeX have plugin handoff manifests at - `plugins/incubating/sai-vn.plugin-handoff.json`, - `plugins/incubating/tex-math.plugin-handoff.json`, plus a shared verifier at - `scripts/run-plugin-handoff-smoke.ps1`. The handoffs name the manifest, - advertisement, ABI fixture, move sets, contract inputs, forbidden imports, - and external proofs that must move to the owner repos. The conformance export - carries plugin `handoffPath` and `pluginHandoffMoveCoverage[]`, and the - plugin-owner smoke asserts them so Sai, Norn, and EvePlugins can consume the - plugin boundary without reading Eve's parity manifest. +- Sai, Norn, and TeX have crossed their handoff boundaries. Eve consumes each + owner manifest, advertisement, ABI fixture, and executable sidecar directly; + conformance attaches owner-produced witnesses instead of exporting migration + handoff documents as if migration were still pending. - Norn has crossed that handoff boundary. `Norn/plugins` now publishes the `norn.graph` manifest, advertisement, and ABI fixture, while `Norn/crates/norn-eve-plugin` runs the first executable sidecar over bounded @@ -1200,32 +1216,11 @@ Recently cut: the split-target plus Aetheria consumer smokes assert it from the conformance export. The remaining blocker is owner-repo PNG/frame capture from the future EveUnity repo, not whether the Unity client is generic. -- Aetheria now has repeatable Unity package consumer-build evidence for the - Eve UI Toolkit runtime. `scripts/run-aetheria-unity-package-smoke.ps1` - verifies Aetheria's Unity `Packages/manifest.json` consumes Eve's surface, - Unity scene, and UI Toolkit packages by file reference, checks the generated - Unity projects include all current runtime files, asserts the Aetheria Unity - bridge reads `runtimeState.AssetManifest.Latest()` from client state - `AssetManifest` and publishes the - `AetheriaRuntimeVerseRecordKeys.DaemonAssetManifest` pointer, then builds the - packages through Aetheria's Unity-generated projects. -- The EveUnity UI Toolkit split handoff now records Aetheria's Unity consumer - boundary as `observed-provider` evidence. The handoff names Aetheria's - package manifest, generated Unity project, assets root, daemon catalog - client, and Unity smoke as provider-owned pressure sources that prove a real - game consumes EveUnity without making those Aetheria paths EveUnity source. - `scripts/run-eveunity-split-handoff-smoke.ps1`, - `scripts/run-split-target-conformance-consumer-smoke.ps1`, and - `scripts/run-aetheria-conformance-consumer-smoke.ps1` assert that boundary - from the manifest/export. -- Unity UI Toolkit now attaches a schema-backed semantic projection capture - artifact at - `artifacts/eveunity-uitoolkit-capture/latest/unity-uitoolkit-projection.json`. - Parity validates it against - `gamecult.eve.unity_uitoolkit_projection.v1`, exports it as - `runtime.captureArtifacts[]`, and the runtime-owner consumer smoke asserts it. - This proves the UI Toolkit command-surface projection is typed evidence while - leaving real Unity editor or batchmode PNG capture as the EveUnity blocker. +- Aetheria's Unity package manifest consumes the surface, UI Toolkit, and scene + packages from EveUnity. Eve's owner smoke verifies those references and asks + EveUnity to build the UI Toolkit package. UI Toolkit capture is reported as + missing until EveUnity emits a native PNG; an Eve-generated semantic JSON + projection is no longer allowed to impersonate runtime evidence. - Unity UI Toolkit now has a first-party `norn.graph` projection-adapter proof for `embed.norn`. `NornGraphUiToolkitProjectionAdapter` owns the native embedded graph shell and graph command emission path, while the Norn sidecar diff --git a/docs/parity-testing-harness.md b/docs/parity-testing-harness.md index 3406bab..357a17a 100644 --- a/docs/parity-testing-harness.md +++ b/docs/parity-testing-harness.md @@ -302,19 +302,18 @@ requested. Unity UI Toolkit, Electron shell, and TUI declare because the editor advertisement does not include the `unity-scene` lowering target. -Plugin owner handoff smoke: +Plugin owner smoke: ```powershell -powershell -ExecutionPolicy Bypass -File .\scripts\run-plugin-handoff-smoke.ps1 +powershell -ExecutionPolicy Bypass -File .\scripts\run-eveplugins-owner-smoke.ps1 ``` -That script validates the Sai and Norn handoff manifests against their plugin -manifests, advertisements, ABI fixtures, move-set paths, contract inputs, and -external proofs. It also checks that the manifest and advertisement agree on -the runtime-independent executable sidecar boundary: `gamecult.eve.plugin_abi.v1`, -CultMesh/stdio transport, renderer independence, no provider-state mutation, -provider-owned command acceptance, and `runtime.sidecar` process/protocol/schema -fields. The plugin-owner conformance smoke also asserts those handoff paths, +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. diff --git a/plugins/incubating/tex-math.plugin-abi-fixture.json b/plugins/incubating/tex-math.plugin-abi-fixture.json deleted file mode 100644 index a59abfe..0000000 --- a/plugins/incubating/tex-math.plugin-abi-fixture.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "schema": "gamecult.eve.plugin_abi_fixture.v1", - "fixtureId": "tex-math-plugin-abi", - "pluginId": "tex.math", - "ownerRepo": "EvePlugins", - "contract": "gamecult.eve.plugin_abi.v1", - "requestSchema": "gamecult.eve.plugin_abi.request.v1", - "responseSchema": "gamecult.eve.plugin_abi.response.v1", - "sourceFixture": "sai-vn", - "sourceFixtureRole": "optional-nested-placement-evidence", - "authority": "EvePlugins owns TeX semantics independently; the Sai fixture only proves a provider surface can nest embed.tex when tex.math is available.", - "operations": [ - { - "operation": "describe", - "input": { - "manifest": "plugins/incubating/tex-math.plugin.json", - "advertisement": "plugins/incubating/tex-math.plugin-advertisement.json" - }, - "expect": { - "pluginId": "tex.math", - "componentKinds": ["embed.tex"], - "commands": [], - "capabilities": ["embed.tex", "tex.inline", "tex.block"] - } - }, - { - "operation": "validate", - "input": { - "surface": "web/fixtures/sai-vn-surface.json", - "componentKinds": ["embed.tex"] - }, - "expect": { - "acceptedComponentKinds": ["embed.tex"], - "rejectedComponentKinds": ["embed.norn", "vn.stage"], - "requiredCapabilities": ["embed.tex"] - } - }, - { - "operation": "project", - "input": { - "surface": "web/fixtures/sai-vn-surface.json", - "nodeKind": "embed.tex" - }, - "expect": { - "projectionKind": "render-request", - "ownedComponentKinds": ["embed.tex"], - "outputSchemas": ["tex.math.render_request.v1", "tex.math.render_result.v1"] - } - }, - { - "operation": "lower", - "input": { - "projection": "render-request", - "targetRuntimes": ["web"], - "componentKinds": ["embed.tex"] - }, - "expect": { - "loweringKind": "typeset-fragment", - "preservedComponentKinds": ["embed.tex"], - "requiredSchemas": ["tex.math.render_request.v1", "tex.math.render_result.v1"], - "fallbackKind": "source-text" - } - }, - { - "operation": "measure", - "input": { - "projection": "render-request", - "sourceSchema": "tex.math.source.v1" - }, - "expect": { - "measurementKind": "typeset-baseline-metrics", - "measurementOutputs": ["baseline", "advance", "inkBounds", "fallbackBounds"], - "preservesProviderAuthority": true - } - }, - { - "operation": "apply", - "input": { - "stateSchemas": ["tex.math.source.v1", "tex.math.render_request.v1", "tex.math.render_result.v1"] - }, - "expect": { - "stateEffects": ["cache-render-result", "emit-fallback-on-render-failure"], - "receiptSchema": "gamecult.eve.plugin_receipt.v1" - } - } - ] -} diff --git a/plugins/incubating/tex-math.plugin-advertisement.json b/plugins/incubating/tex-math.plugin-advertisement.json deleted file mode 100644 index 5baee6f..0000000 --- a/plugins/incubating/tex-math.plugin-advertisement.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "schema": "gamecult.eve.plugin_advertisement.v1", - "pluginId": "tex.math", - "ownerService": "eveplugins", - "version": "0.1.0-incubating", - "manifestAddress": "file://plugins/incubating/tex-math.plugin.json", - "runtime": { - "invocationModel": "executable-sidecar", - "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["cultmesh", "stdio"], - "authority": [ - "renderer-independent", - "no-provider-state-mutation", - "provider-accepts-or-denies-commands" - ], - "sidecar": { - "processKind": "long-running-daemon", - "protocol": "cultmesh-rpc-with-stdio-dev-transport", - "requestSchema": "gamecult.eve.plugin_abi.request.v1", - "responseSchema": "gamecult.eve.plugin_abi.response.v1", - "operations": ["describe", "validate", "project", "lower", "measure", "apply"], - "commandEnvelope": "gamecult.eve.command_invocation.v1", - "receiptSchema": "gamecult.eve.plugin_receipt.v1", - "stateAuthority": "emits-render-results-only-provider-owns-source-state" - } - }, - "schemas": [ - "tex.math.source.v1", - "tex.math.render_request.v1", - "tex.math.render_result.v1" - ], - "componentKinds": [ - "embed.tex" - ], - "commands": [], - "fixtures": [ - "sai-vn" - ] -} diff --git a/plugins/incubating/tex-math.plugin-handoff.json b/plugins/incubating/tex-math.plugin-handoff.json deleted file mode 100644 index e06b536..0000000 --- a/plugins/incubating/tex-math.plugin-handoff.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "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; the Sai fixture is only optional nested placement evidence." - } - ], - "contractInputs": [ - "gamecult.eve.plugin.v1", - "gamecult.eve.plugin_advertisement.v1", - "gamecult.eve.plugin_abi.v1", - "gamecult.eve.plugin_abi.request.v1", - "gamecult.eve.plugin_abi.response.v1", - "gamecult.eve.plugin_abi_fixture.v1", - "gamecult.eve.conformance_export.v1" - ], - "forbiddenImports": [ - "Aetheria provider state", - "Sai story session internals or VN command authority", - "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/plugins/incubating/tex-math.plugin.json b/plugins/incubating/tex-math.plugin.json deleted file mode 100644 index 645ed32..0000000 --- a/plugins/incubating/tex-math.plugin.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "schema": "gamecult.eve.plugin.v1", - "pluginId": "tex.math", - "title": "TeX Math", - "owner": "EvePlugins", - "incubation": { - "ownerRepo": "EvePlugins", - "currentHostRepo": "Eve", - "splitTarget": "EvePlugins/eve-plugin-tex", - "graduationTrigger": "Split when TeX source, macro, baseline, cached render, and fallback fixtures are stable." - }, - "componentKinds": [ - "embed.tex" - ], - "commands": [], - "runtime": { - "invocationModel": "executable-sidecar", - "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["cultmesh", "stdio"], - "authority": [ - "renderer-independent", - "no-provider-state-mutation", - "provider-accepts-or-denies-commands" - ], - "sidecar": { - "processKind": "long-running-daemon", - "protocol": "cultmesh-rpc-with-stdio-dev-transport", - "requestSchema": "gamecult.eve.plugin_abi.request.v1", - "responseSchema": "gamecult.eve.plugin_abi.response.v1", - "operations": ["describe", "validate", "project", "lower", "measure", "apply"], - "commandEnvelope": "gamecult.eve.command_invocation.v1", - "receiptSchema": "gamecult.eve.plugin_receipt.v1", - "stateAuthority": "emits-render-results-only-provider-owns-source-state" - } - }, - "stateSchemas": [ - "tex.math.source.v1", - "tex.math.render_request.v1", - "tex.math.render_result.v1" - ], - "fixtures": [ - { - "fixtureId": "sai-vn", - "schema": "gamecult.eve.surface.v1", - "path": "web/fixtures/sai-vn-surface.json", - "role": "optional-nested-placement-evidence", - "authority": "TeX semantics remain plugin-owned; the Sai fixture only proves a surface can nest embed.tex when tex.math is available." - } - ], - "abiFixtures": [ - "plugins/incubating/tex-math.plugin-abi-fixture.json" - ], - "capabilities": { - "requires": [ - "embed.tex" - ], - "optionalCapabilities": [ - "tex.inline", - "tex.block", - "tex.scene-placement" - ] - } -} diff --git a/scripts/run-eveplugins-owner-smoke.ps1 b/scripts/run-eveplugins-owner-smoke.ps1 new file mode 100644 index 0000000..568f05b --- /dev/null +++ b/scripts/run-eveplugins-owner-smoke.ps1 @@ -0,0 +1,30 @@ +param([string] $EvePluginsRoot = "E:\Projects\EvePlugins") + +$ErrorActionPreference = "Stop" + +$requiredPaths = @( + "plugins\eve-plugin-tex\plugin.json", + "plugins\eve-plugin-tex\advertisement.json", + "plugins\eve-plugin-tex\plugin-abi-fixture.json", + "plugins\eve-plugin-tex\src\sidecar.mjs", + "scripts\run-tex-witness.mjs" +) + +foreach ($relativePath in $requiredPaths) { + $path = Join-Path $EvePluginsRoot $relativePath + if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { + throw "EvePlugins owner path is missing: $path" + } +} + +Push-Location $EvePluginsRoot +try { + npm test + if ($LASTEXITCODE -ne 0) { throw "EvePlugins tests failed." } + npm run witness:tex + if ($LASTEXITCODE -ne 0) { throw "EvePlugins TeX witness failed." } +} finally { + Pop-Location +} + +Write-Host "EvePlugins TeX owner smoke passed: $EvePluginsRoot" diff --git a/scripts/run-parity-harness.ps1 b/scripts/run-parity-harness.ps1 index 1a0e836..5397f19 100644 --- a/scripts/run-parity-harness.ps1 +++ b/scripts/run-parity-harness.ps1 @@ -27,6 +27,7 @@ try { -Port 8894 ` -SkipBuild & (Join-Path $PSScriptRoot "run-eveunity-owner-smoke.ps1") + & (Join-Path $PSScriptRoot "run-eveplugins-owner-smoke.ps1") & (Join-Path $PSScriptRoot "run-evetui-capture-smoke.ps1") & (Join-Path $PSScriptRoot "run-evetui-capture-smoke.ps1") ` -AdvertisementPath "web\fixtures\eve-world-smoke.provider-advertisement.json" ` @@ -44,8 +45,10 @@ try { node .\tools\conformance\attach-runtime-witness.mjs ` "E:\Projects\EveElectron\artifacts\capture\aetheria-world\runtime-witness.json" ` ".\artifacts\conformance\latest" + node .\tools\conformance\attach-plugin-witness.mjs ` + "E:\Projects\EvePlugins\artifacts\tex-math\runtime-witness.json" ` + ".\artifacts\conformance\latest" & (Join-Path $PSScriptRoot "run-eveconformance-handoff-smoke.ps1") - & (Join-Path $PSScriptRoot "run-plugin-handoff-smoke.ps1") & (Join-Path $PSScriptRoot "run-aetheria-provider-handoff-smoke.ps1") & (Join-Path $PSScriptRoot "run-eveelectron-owner-smoke.ps1") & (Join-Path $PSScriptRoot "run-evetui-split-handoff-smoke.ps1") diff --git a/scripts/run-plugin-handoff-smoke.ps1 b/scripts/run-plugin-handoff-smoke.ps1 deleted file mode 100644 index b3f9929..0000000 --- a/scripts/run-plugin-handoff-smoke.ps1 +++ /dev/null @@ -1,156 +0,0 @@ -param( - [string[]] $HandoffPaths = @( - "plugins\incubating\tex-math.plugin-handoff.json" - ) -) - -$ErrorActionPreference = "Stop" - -$projectRoot = Split-Path -Parent $PSScriptRoot - -foreach ($handoffPath in $HandoffPaths) { - $absoluteHandoffPath = if ([System.IO.Path]::IsPathRooted($handoffPath)) { - $handoffPath - } else { - Join-Path $projectRoot $handoffPath - } - - if (-not (Test-Path -LiteralPath $absoluteHandoffPath)) { - throw "Plugin handoff manifest not found: $absoluteHandoffPath" - } - - $handoff = Get-Content -LiteralPath $absoluteHandoffPath -Raw | ConvertFrom-Json - - if ($handoff.schema -ne "gamecult.eve.plugin_handoff.v1") { - throw "Unexpected plugin handoff schema in $($handoffPath): $($handoff.schema)" - } - if (-not $handoff.pluginId) { - throw "Plugin handoff missing pluginId: $handoffPath" - } - if (-not $handoff.ownerRepo) { - throw "Plugin handoff missing ownerRepo: $($handoff.pluginId)" - } - if ($handoff.currentHostRepo -ne "Eve") { - throw "Plugin handoff $($handoff.pluginId) has unexpected current host: $($handoff.currentHostRepo)" - } - - foreach ($pathProperty in @("manifestPath", "advertisementPath", "abiFixturePath")) { - $relativePath = $handoff.$pathProperty - if (-not $relativePath) { - throw "Plugin handoff $($handoff.pluginId) missing $pathProperty" - } - $absolutePath = Join-Path $projectRoot $relativePath - if (-not (Test-Path -LiteralPath $absolutePath)) { - throw "Plugin handoff $($handoff.pluginId) references missing $($pathProperty): $relativePath" - } - } - - $manifest = Get-Content -LiteralPath (Join-Path $projectRoot $handoff.manifestPath) -Raw | ConvertFrom-Json - $advertisement = Get-Content -LiteralPath (Join-Path $projectRoot $handoff.advertisementPath) -Raw | ConvertFrom-Json - $abiFixture = Get-Content -LiteralPath (Join-Path $projectRoot $handoff.abiFixturePath) -Raw | ConvertFrom-Json - - if ($manifest.pluginId -ne $handoff.pluginId) { - throw "Plugin handoff pluginId does not match manifest: $($handoff.pluginId) vs $($manifest.pluginId)" - } - if ($advertisement.pluginId -ne $handoff.pluginId) { - throw "Plugin handoff pluginId does not match advertisement: $($handoff.pluginId) vs $($advertisement.pluginId)" - } - if ($abiFixture.pluginId -ne $handoff.pluginId) { - throw "Plugin handoff pluginId does not match ABI fixture: $($handoff.pluginId) vs $($abiFixture.pluginId)" - } - if ($manifest.incubation.ownerRepo -ne $handoff.ownerRepo) { - throw "Plugin handoff $($handoff.pluginId) owner does not match manifest owner: $($manifest.incubation.ownerRepo)" - } - if ($manifest.incubation.splitTarget -ne $handoff.splitTarget) { - throw "Plugin handoff $($handoff.pluginId) split target does not match manifest: $($manifest.incubation.splitTarget)" - } - if ($manifest.runtime.invocationModel -ne "executable-sidecar") { - throw "Plugin handoff $($handoff.pluginId) runtime is not executable-sidecar: $($manifest.runtime.invocationModel)" - } - if ($manifest.runtime.contract -ne "gamecult.eve.plugin_abi.v1") { - throw "Plugin handoff $($handoff.pluginId) runtime contract is not gamecult.eve.plugin_abi.v1: $($manifest.runtime.contract)" - } - if ($advertisement.runtime.invocationModel -ne $manifest.runtime.invocationModel) { - throw "Plugin handoff $($handoff.pluginId) advertisement runtime does not match manifest runtime: $($advertisement.runtime.invocationModel)" - } - foreach ($transport in @("cultmesh", "stdio")) { - if (-not (@($manifest.runtime.transports) -contains $transport)) { - throw "Plugin handoff $($handoff.pluginId) manifest runtime missing transport: $transport" - } - if (-not (@($advertisement.runtime.transports) -contains $transport)) { - throw "Plugin handoff $($handoff.pluginId) advertisement runtime missing transport: $transport" - } - } - foreach ($authority in @("renderer-independent", "no-provider-state-mutation", "provider-accepts-or-denies-commands")) { - if (-not (@($manifest.runtime.authority) -contains $authority)) { - throw "Plugin handoff $($handoff.pluginId) manifest runtime missing authority: $authority" - } - if (-not (@($advertisement.runtime.authority) -contains $authority)) { - throw "Plugin handoff $($handoff.pluginId) advertisement runtime missing authority: $authority" - } - } - foreach ($sidecarProperty in @("processKind", "protocol", "requestSchema", "responseSchema", "commandEnvelope", "receiptSchema", "stateAuthority")) { - if (-not $manifest.runtime.sidecar.$sidecarProperty) { - throw "Plugin handoff $($handoff.pluginId) manifest sidecar missing property: $sidecarProperty" - } - if ($advertisement.runtime.sidecar.$sidecarProperty -ne $manifest.runtime.sidecar.$sidecarProperty) { - throw "Plugin handoff $($handoff.pluginId) advertisement sidecar $sidecarProperty does not match manifest: $($advertisement.runtime.sidecar.$sidecarProperty)" - } - } - - $operations = @($abiFixture.operations | ForEach-Object { $_.operation }) - if ($abiFixture.requestSchema -ne $manifest.runtime.sidecar.requestSchema) { - throw "Plugin handoff $($handoff.pluginId) ABI fixture request schema does not match sidecar: $($abiFixture.requestSchema)" - } - if ($abiFixture.responseSchema -ne $manifest.runtime.sidecar.responseSchema) { - throw "Plugin handoff $($handoff.pluginId) ABI fixture response schema does not match sidecar: $($abiFixture.responseSchema)" - } - foreach ($operation in @("describe", "validate", "project", "lower", "measure", "apply")) { - if (-not ($operations -contains $operation)) { - throw "Plugin handoff $($handoff.pluginId) ABI fixture missing operation: $operation" - } - if (-not (@($manifest.runtime.sidecar.operations) -contains $operation)) { - throw "Plugin handoff $($handoff.pluginId) manifest sidecar missing operation: $operation" - } - if (-not (@($advertisement.runtime.sidecar.operations) -contains $operation)) { - throw "Plugin handoff $($handoff.pluginId) advertisement sidecar missing operation: $operation" - } - } - - foreach ($moveSet in @($handoff.moveSets)) { - if ($moveSet.destinationOwner -ne $handoff.ownerRepo) { - throw "Plugin handoff $($handoff.pluginId) move set $($moveSet.id) has unexpected destination owner: $($moveSet.destinationOwner)" - } - if (-not $moveSet.replacementProof) { - throw "Plugin handoff $($handoff.pluginId) move set $($moveSet.id) missing replacement proof" - } - foreach ($relativePath in @($moveSet.currentPaths)) { - $absolutePath = Join-Path $projectRoot $relativePath - if (-not (Test-Path -LiteralPath $absolutePath)) { - throw "Plugin handoff $($handoff.pluginId) move set $($moveSet.id) references missing path: $relativePath" - } - } - } - - foreach ($contract in @( - "gamecult.eve.plugin.v1", - "gamecult.eve.plugin_advertisement.v1", - "gamecult.eve.plugin_abi.v1", - "gamecult.eve.plugin_abi.request.v1", - "gamecult.eve.plugin_abi.response.v1", - "gamecult.eve.plugin_abi_fixture.v1", - "gamecult.eve.conformance_export.v1" - )) { - if (-not (@($handoff.contractInputs) -contains $contract)) { - throw "Plugin handoff $($handoff.pluginId) missing contract input: $contract" - } - } - - foreach ($proof in @($handoff.requiredExternalProofs)) { - if (-not $proof) { - throw "Plugin handoff $($handoff.pluginId) contains an empty required external proof" - } - } -} - -Write-Host "Plugin handoff smoke passed: $($HandoffPaths -join ', ')" diff --git a/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 b/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 index bdec510..44fa4b5 100644 --- a/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 @@ -44,9 +44,6 @@ node $consumerScript $consumerExport ` --expect-plugin sai.vn ` --expect-plugin norn.graph ` --expect-plugin tex.math ` - --expect-plugin-handoff tex.math ` - --expect-plugin-handoff-move tex.math:plugin-manifest:current:exists:tex-math.plugin.json ` - --expect-plugin-handoff-move tex.math:abi-conformance:current:exists:tex-math.plugin-abi-fixture.json ` --expect-plugin-operation sai.vn:describe ` --expect-plugin-operation sai.vn:validate ` --expect-plugin-operation sai.vn:project ` @@ -101,16 +98,17 @@ node $consumerScript $consumerExport ` --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-transport tex.math:stdio ` --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.protocol:stdio-ndjson ` --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 + --expect-plugin-abi-field tex.math:apply:expect.receiptSchema:gamecult.eve.plugin_receipt.v1 ` + --expect-plugin-witness tex.math:stdio-ndjson:pass 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 40b05c1..d7d6754 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -507,20 +507,20 @@ { "pluginId": "tex.math", "title": "TeX Math", - "kind": "incubating", + "kind": "external-owner", "ownerRepo": "EvePlugins", - "repoRole": "plugin-incubating", + "repoRole": "plugin-owner", "splitTarget": "EvePlugins/eve-plugin-tex", - "graduationTrigger": "Split when TeX source, macro, baseline, cached render, and fallback fixtures are stable.", + "graduationTrigger": "Graduated: EvePlugins owns the executable TeX sidecar, fixtures, tests, and conformance witness.", "capabilities": ["embed.tex", "tex.inline", "tex.block"], "expectedRuntime": { "invocationModel": "executable-sidecar", "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["cultmesh", "stdio"], + "transports": ["stdio"], "authority": ["renderer-independent", "no-provider-state-mutation", "provider-accepts-or-denies-commands"], "sidecar": { "processKind": "long-running-daemon", - "protocol": "cultmesh-rpc-with-stdio-dev-transport", + "protocol": "stdio-ndjson", "requestSchema": "gamecult.eve.plugin_abi.request.v1", "responseSchema": "gamecult.eve.plugin_abi.response.v1", "commandEnvelope": "gamecult.eve.command_invocation.v1", @@ -530,17 +530,15 @@ }, "requiredFixtures": [], "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", + "manifestPath": "../EvePlugins/plugins/eve-plugin-tex/plugin.json", + "abiFixturePath": "../EvePlugins/plugins/eve-plugin-tex/plugin-abi-fixture.json", "advertisementSchemaPath": "schemas/gamecult.eve.plugin_advertisement.v1.schema.json", - "advertisementPath": "plugins/incubating/tex-math.plugin-advertisement.json", + "advertisementPath": "../EvePlugins/plugins/eve-plugin-tex/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-handoff.json", - "scripts/run-plugin-handoff-smoke.ps1" + "../EvePlugins/plugins/eve-plugin-tex/plugin.json", + "../EvePlugins/plugins/eve-plugin-tex/plugin-abi-fixture.json", + "../EvePlugins/plugins/eve-plugin-tex/advertisement.json", + "../EvePlugins/plugins/eve-plugin-tex/src/sidecar.mjs" ] } ],