Add EveTui plugin fallback projections

This commit is contained in:
Meta Vens 2026-07-09 13:25:20 +01:00
commit e1c635d033
12 changed files with 319 additions and 49 deletions

View file

@ -36,13 +36,30 @@ if ($manifest.incubation.splitTarget -ne "EveTui") {
throw "Unexpected EveTui split target: $($manifest.incubation.splitTarget)"
}
foreach ($feature in @("providerAdvertisements", "commandTransport", "terminalGridSummary", "terminalGridLowering", "embeddedDocuments")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "terminalGridSummary", "terminalGridLowering", "embeddedDocuments", "pluginProjection")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveTui manifest missing provider-shell feature: $feature"
}
}
if (@($manifest.supportedPlugins).Count -ne 0) {
throw "EveTui must not claim plugin projection before terminal projection adapters for sidecar-advertised capabilities exist"
$expectedPlugins = @{
"sai.vn" = @("vn.stage", "story.choose", "story.continue", "story.jump")
"norn.graph" = @("embed.norn")
"tex.math" = @("embed.tex", "tex.inline", "tex.block")
}
foreach ($pluginId in $expectedPlugins.Keys) {
$supported = @($manifest.supportedPlugins) | Where-Object { $_.pluginId -eq $pluginId } | Select-Object -First 1
if (-not $supported) {
throw "EveTui manifest missing supported plugin declaration: $pluginId"
}
foreach ($capability in $expectedPlugins[$pluginId]) {
if (-not (@($supported.capabilities) -contains $capability)) {
throw "EveTui supported plugin $pluginId missing capability: $capability"
}
}
if ($supported.projectionAdapter -ne "EveTuiShell.buildPluginProjection") {
throw "EveTui supported plugin $pluginId has unexpected projection adapter: $($supported.projectionAdapter)"
}
}
$worldSurfaceLoweringClaims = @()
@ -69,10 +86,10 @@ foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) {
}
}
foreach ($pluginId in @("sai.vn", "norn.graph", "tex.math")) {
foreach ($pluginId in $expectedPlugins.Keys) {
$unsupported = @($manifest.unsupportedPlugins) | Where-Object { $_.pluginId -eq $pluginId } | Select-Object -First 1
if (-not $unsupported) {
throw "EveTui manifest missing unsupported plugin declaration: $pluginId"
if ($unsupported) {
throw "EveTui manifest must not report $pluginId unsupported while terminal fallback projection is declared"
}
}

View file

@ -24,12 +24,19 @@ if ($manifest.lifecycle.test.status -ne "provider-shell-contract-skeleton") {
throw "Unexpected EveTui provider shell status: $($manifest.lifecycle.test.status)"
}
foreach ($feature in @("providerAdvertisements", "commandTransport", "terminalGridSummary", "terminalGridLowering")) {
foreach ($feature in @("providerAdvertisements", "commandTransport", "terminalGridSummary", "terminalGridLowering", "pluginProjection")) {
if (-not (@($manifest.supportedFeatures) -contains $feature)) {
throw "EveTui provider shell missing supported feature: $feature"
}
}
foreach ($pluginId in @("sai.vn", "norn.graph", "tex.math")) {
$supported = @($manifest.supportedPlugins) | Where-Object { $_.pluginId -eq $pluginId } | Select-Object -First 1
if (-not $supported) {
throw "EveTui provider shell missing supported plugin projection: $pluginId"
}
}
$worldSurfaceLoweringClaims = @()
if ($null -ne $manifest.worldSurfaceLowering) {
$worldSurfaceLoweringClaims = @($manifest.worldSurfaceLowering)
@ -78,14 +85,14 @@ foreach ($relativePath in $expectedFiles) {
}
$shellSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-tui\src\eve-tui-shell.mjs") -Raw
foreach ($symbol in @("EveTuiShell", "selectSurface", "lowerSurface", "normalizeSurfaceDocument", "buildComponentLines", "terminalElementKind", "createCommandIntent", "renderSummary", "gamecult.eve.tui_grid.v1", "commandBoundary", "receiptSchema")) {
foreach ($symbol in @("EveTuiShell", "selectSurface", "lowerSurface", "normalizeSurfaceDocument", "buildComponentLines", "buildPluginProjection", "collectPluginProjections", "terminalElementKind", "sai.vn", "norn.graph", "tex.math", "sidecar-advertised-plugin-abi", "createCommandIntent", "renderSummary", "gamecult.eve.tui_grid.v1", "commandBoundary", "receiptSchema")) {
if (-not $shellSource.Contains($symbol)) {
throw "EveTui provider shell source missing symbol: $symbol"
}
}
$testSource = Get-Content -LiteralPath (Join-Path $projectRoot "runtimes\incubating\eve-tui\test\eve-tui-shell.test.mjs") -Raw
foreach ($symbol in @("selects advertised provider surfaces", "command intents carry provider-advertised boundaries", "summary grid is explicitly lossy", "lowers provider surface trees into a terminal grid", "rejects surface documents that do not match the advertised TUI target", "aetheria.daemon.commands")) {
foreach ($symbol in @("selects advertised provider surfaces", "command intents carry provider-advertised boundaries", "summary grid is explicitly lossy", "lowers provider surface trees into a terminal grid", "lowers Sai, Norn, and TeX plugin surfaces into compact terminal fallbacks", "pluginProjections", "sai-vn-terminal-stage-summary", "norn-graph-terminal-outline", "tex-math-terminal-block-source", "rejects surface documents that do not match the advertised TUI target", "aetheria.daemon.commands")) {
if (-not $testSource.Contains($symbol)) {
throw "EveTui provider shell test missing symbol: $symbol"
}

View file

@ -42,6 +42,7 @@ $expectedMoveSets = @{
"tui-runtime-body" = "runtime-body"
"tui-world-surface-lowering" = "world-surface-lowering"
"tui-command-transport" = "command"
"tui-plugin-projection" = "plugin-projection"
"tui-capture-lifecycle" = "capture"
}
$moveSets = @($handoff.moveSets)
@ -61,7 +62,7 @@ foreach ($id in $expectedMoveSets.Keys) {
}
$currentPaths = if ($null -eq $moveSet.currentPaths) { @() } else { @($moveSet.currentPaths) }
$observedProviderPaths = if ($null -eq $moveSet.observedProviderPaths) { @() } else { @($moveSet.observedProviderPaths) }
if ($id -in @("tui-runtime-body", "tui-world-surface-lowering", "tui-command-transport", "tui-capture-lifecycle")) {
if ($id -in @("tui-runtime-body", "tui-world-surface-lowering", "tui-command-transport", "tui-plugin-projection", "tui-capture-lifecycle")) {
if ($currentPaths.Count -eq 0) {
throw "EveTui split handoff move set $id must name provider-shell skeleton paths"
}
@ -94,7 +95,9 @@ foreach ($forbiddenImport in @(
"provider internals as TUI runtime authority",
"renderer-local product state as provider truth",
"terminal-only command routes that bypass gamecult.eve.command.v1",
"plugin semantic internals",
"Sai story state, VN/Ink semantics, or story command interpretation as TUI runtime authority",
"Norn graph layout, graph state, or command semantics as TUI runtime authority",
"TeX parsing, typesetting, baseline metrics, or render-cache semantics as TUI runtime authority",
"lossy text summaries pretending to be provider state"
)) {
if (-not (@($handoff.forbiddenImports) -contains $forbiddenImport)) {
@ -102,6 +105,17 @@ foreach ($forbiddenImport in @(
}
}
$pluginMoveSet = $moveSets | Where-Object { $_.id -eq "tui-plugin-projection" } | Select-Object -First 1
foreach ($relativePath in @(
"runtimes/incubating/eve-tui/src/eve-tui-shell.mjs",
"runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs",
"web/fixtures/sai-vn-surface.json"
)) {
if (-not (@($pluginMoveSet.currentPaths) -contains $relativePath)) {
throw "EveTui plugin projection move set missing current path: $relativePath"
}
}
foreach ($proof in @($handoff.requiredExternalProofs)) {
if (-not $proof) {
throw "EveTui split handoff contains an empty required external proof"

View file

@ -74,6 +74,7 @@ node $consumerScript $consumerExport `
--expect-runtime-feature tui:terminalGridSummary `
--expect-runtime-feature tui:terminalGridLowering `
--expect-runtime-feature tui:embeddedDocuments `
--expect-runtime-feature tui:pluginProjection `
--expect-runtime-feature direct2d:embeddedDocuments `
--expect-runtime-world-target web:web-reference `
--expect-runtime-world-field web:web-reference:supportLevel:reference-dom-canvas-command-boundary `
@ -99,6 +100,9 @@ node $consumerScript $consumerExport `
--expect-runtime-plugin-projection electron-shell:sai.vn:supported:EveElectron `
--expect-runtime-plugin-projection electron-shell:norn.graph:supported:EveElectron `
--expect-runtime-plugin-projection electron-shell:tex.math:supported:EveElectron `
--expect-runtime-plugin-projection tui:sai.vn:supported:EveTui `
--expect-runtime-plugin-projection tui:norn.graph: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:tex.math:optional-supported:Eve `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:unity-uitoolkit:sai.vn:supported:EveUnity `
@ -110,11 +114,11 @@ node $consumerScript $consumerExport `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:electron-shell:sai.vn:supported:EveElectron `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:electron-shell:norn.graph:optional-supported:EveElectron `
--expect-provider-runtime-plugin-projection gamecult.home.vn:sai.visual_novel.surface:electron-shell:tex.math:optional-supported:EveElectron `
--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-plugin-gap tui:sai.vn:EveTui `
--expect-runtime-plugin-gap tui:norn.graph:EveTui `
--expect-runtime-plugin-gap tui:tex.math:EveTui `
--expect-runtime-handoff unity-uitoolkit `
--expect-runtime-command-schema web:gamecult.eve.command.v1 `
--expect-runtime-command-schema windows-flutter:gamecult.eve.command.v1 `

View file

@ -80,6 +80,7 @@ try {
--expect-split-handoff-move EveTui:tui:tui-runtime-body:current:exists:eve-tui-shell.mjs `
--expect-split-handoff-move EveTui:tui:tui-world-surface-lowering:current:exists:eve-tui-shell.mjs `
--expect-split-handoff-move EveTui:tui:tui-command-transport:current:exists:eve-tui-shell.mjs `
--expect-split-handoff-move EveTui:tui:tui-plugin-projection:current:exists:sai-vn-surface.json `
--expect-split-handoff-move EveTui:tui:tui-capture-lifecycle:current:exists:evetui-capture-contract.mjs `
--expect-split-target-blocker "EveTui:TUI runtime body graduates to EveTui outside provider product code"
if ($LASTEXITCODE -ne 0) {