From 41d20338d9657db150763e9de8b95ea6bb18adc1 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 9 Jul 2026 11:11:47 +0100 Subject: [PATCH] Add TUI terminal grid lowering claim --- docs/eve-migration-roadmap.md | 51 ++++++------ docs/parity-testing-harness.md | 8 +- plugins/incubating/sai-vn.plugin-handoff.json | 2 +- .../eve-tui/eve-runtime-capability.json | 22 ++++- .../eve-tui/evetui-split-handoff.json | 12 ++- .../incubating/eve-tui/src/eve-tui-shell.mjs | 73 ++++++++++++++++- .../eve-tui/test/eve-tui-shell.test.mjs | 80 ++++++++++++++++++- .../eve-runtime-capability.json | 2 +- ...un-aetheria-conformance-consumer-smoke.ps1 | 10 ++- scripts/run-conformance-consumer-smoke.ps1 | 9 +-- scripts/run-eveelectron-lifecycle-smoke.ps1 | 2 +- scripts/run-evetui-lifecycle-smoke.ps1 | 28 ++++++- scripts/run-evetui-provider-shell-smoke.ps1 | 40 +++++++++- scripts/run-evetui-split-handoff-smoke.ps1 | 2 +- .../run-eveunity-scene-lifecycle-smoke.ps1 | 2 +- ...ntime-owner-conformance-consumer-smoke.ps1 | 7 ++ ...plit-target-conformance-consumer-smoke.ps1 | 1 + tools/parity/parity-manifest.json | 28 +++++-- 18 files changed, 315 insertions(+), 64 deletions(-) diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index ed812f0..ac3bd33 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -294,13 +294,12 @@ Recently cut: lower provider-owned world state without owning it. Parity compares those claims against the ledger, exports them through runtime records and `packs/runtime.json`, the runtime-owner smoke asserts them, and the generic - conformance smoke now treats `unity-scene` and `electron-shell` as narrow - runtime-owned command-surface claims while capture and release remain split - blockers. -- Missing provider-advertised world-surface lowering targets are now assigned - to their pending runtime owner when one exists. `tui` gaps point at EveTui's - pending `tui` runtime. Eve only owns a world-lowering gap when no runtime - target has been declared. + conformance smoke now treats `unity-scene`, `electron-shell`, and `tui` as + narrow runtime-owned command-surface claims while capture and release remain + split blockers. +- Missing provider-advertised world-surface lowering targets are still assigned + to their pending runtime owner when one exists. Eve only owns a world-lowering + gap when no runtime target has been declared. - The conformance export now carries `worldSurfaceLoweringGaps[]` as typed data in addition to the generic `capabilityGaps[]` ledger. Runtime owners can consume provider id, surface id, target id, owner repo, runtime id, split @@ -309,14 +308,12 @@ Recently cut: provider-surface-to-target ledger that marks each advertised lowering target as `claimed`, `missing-claim`, or `missing-runtime`. The generic conformance consumer now asserts Aetheria's claimed web, UI Toolkit, Unity scene graph, - and Electron shell targets plus the missing TUI targets from the same typed - surface. + Electron shell, and TUI terminal-grid targets from the same typed surface. - The conformance export carries `commandBoundaryCoverage[]`, joining each provider-owned interactive world surface target to its runtime owner, provider command boundary, receipt schema, and runtime command envelope. Web, - Unity UI Toolkit, Unity scene, and Electron shell are `covered` because they - advertise `gamecult.eve.command.v1`; TUI stays visible as - `missing-runtime-claim` until its generic terminal lowerer exists. + Unity UI Toolkit, Unity scene, Electron shell, and TUI are `covered` because + they advertise `gamecult.eve.command.v1`. - The browser reference lowerer now carries the active provider surface's advertised `worldInteraction.commandBoundary` and `worldInteraction.receiptSchema` into each `gamecult.eve.command.v1` intent. @@ -342,9 +339,10 @@ Recently cut: - EveTui now has a provider-shell contract skeleton under `runtimes/incubating/eve-tui`. The shell selects advertised provider surfaces, emits `gamecult.eve.command.v1` intents with provider command - boundary and receipt schema fields, and produces an explicitly lossy - `gamecult.eve.tui_grid.v1` summary without claiming full `tui` world lowering - or transcript capture. + boundary and receipt schema fields, lowers Eve surface trees into an + explicitly lossy `gamecult.eve.tui_grid.v1` terminal grid, and claims the + `tui` command-surface target without owning provider truth or transcript + capture. - The conformance export carries `splitHandoffMoveCoverage[]`, joining runtime split handoff move sets to source path status. EveElectron now exposes the existing Aetheria `Aetheria.Rts.Web/Electron` and command transport paths as @@ -441,19 +439,20 @@ Recently cut: capability documents; the conformance export reads command/lifecycle contracts from those documents for pending runtimes. - EveTui now has a pending split target and handoff at - `runtimes/incubating/eve-tui/evetui-split-handoff.json`. It does not claim - the advertised `tui` world-surface lowering target yet. The handoff draws the - line between a future provider-agnostic terminal/grid lowerer and - provider-owned TUI surfaces, and the split-target consumer smoke keeps the - missing runtime body, provider-advertisement consumption, command transport, - transcript/cell-grid capture, and `tui` lowering proof visible as blockers. + `runtimes/incubating/eve-tui/evetui-split-handoff.json`. It claims the + advertised `tui` world-surface lowering target as a lossy terminal-grid + command surface. The handoff draws the line between the provider-agnostic + terminal/grid lowerer and provider-owned TUI surfaces, and the split-target + consumer smoke keeps runtime graduation and transcript/cell-grid capture + visible as blockers. - EveTui now has a direct split handoff smoke at `scripts/run-evetui-split-handoff-smoke.ps1`, a pending runtime capability manifest at `runtimes/incubating/eve-tui/eve-runtime-capability.json`, and a lifecycle smoke at `scripts/run-evetui-lifecycle-smoke.ps1`. The manifest - declares no supported runtime features or plugin projection yet; it only - types the pending command boundary, terminal package release, - provider-advertisement TUI smoke, and transcript/cell-grid capture contracts. + declares provider advertisement consumption, command transport, terminal-grid + summary, terminal-grid lowering, and the `tui` world/editor lowering claim; + it still keeps plugin projection, terminal package release, and + transcript/cell-grid capture contracts pending. - Aetheria interactive world surfaces now carry a structured provider-owned `worldInteraction` contract. The provider advertisement names projection kind, provider state schemas, daemon command boundary, receipt schema, @@ -742,8 +741,8 @@ Recently cut: states without importing Aetheria internals into Eve. - Aetheria's provider scenario now covers both `aetheria.daemon.game` and `aetheria.daemon.editor` as provider-owned interactive world surfaces. The - Aetheria consumer smoke asserts editor ownership and the pending TUI lowering - gap from the exported contract instead of letting editor support hide behind + Aetheria consumer smoke asserts editor ownership and the claimed TUI + terminal-grid lowering target instead of letting editor support hide behind the game-surface scenario. - The surface contract now states nested Norn and TeX placement as optional composition, not Sai custody. The plugin-owner consumer can assert diff --git a/docs/parity-testing-harness.md b/docs/parity-testing-harness.md index 8c388d0..43075eb 100644 --- a/docs/parity-testing-harness.md +++ b/docs/parity-testing-harness.md @@ -305,10 +305,10 @@ Electron source paths named by the handoff currently exist as turning those paths into EveElectron authority. The Electron runtime now claims a narrow provider-advertised surface-tree command surface, while packaged rendering, embedded document rendering, capture, and plugin projection remain -blockers. EveTui is also intentionally -pending: Aetheria advertises `tui` as an agent-facing lowering target, but Eve -should not claim that target until a real terminal/grid lowerer and transcript -capture exist. EveUnity includes both the active `unity-uitoolkit` package proof +blockers. EveTui is also intentionally pending: it now claims a lossy +provider-advertised terminal-grid command surface, while transcript/cell-grid +capture, embedded document rendering, plugin projection, and repo graduation +remain blockers. EveUnity includes both the active `unity-uitoolkit` package proof and the pending `unity-scene` runtime boundary; UI Toolkit support is not treated as full Unity scene/world lowering. The `unity-scene` runtime now claims a narrow scene graph command surface, while capture, release, and plugin diff --git a/plugins/incubating/sai-vn.plugin-handoff.json b/plugins/incubating/sai-vn.plugin-handoff.json index 2a7e6ac..a3432cf 100644 --- a/plugins/incubating/sai-vn.plugin-handoff.json +++ b/plugins/incubating/sai-vn.plugin-handoff.json @@ -39,7 +39,7 @@ "forbiddenImports": [ "Aetheria provider state", "renderer-native projection internals", - "Unity plugin host internals", + "runtime plugin projection internals", "provider command acceptance or receipt authority" ], "requiredExternalProofs": [ diff --git a/runtimes/incubating/eve-tui/eve-runtime-capability.json b/runtimes/incubating/eve-tui/eve-runtime-capability.json index 289022b..829d43f 100644 --- a/runtimes/incubating/eve-tui/eve-runtime-capability.json +++ b/runtimes/incubating/eve-tui/eve-runtime-capability.json @@ -16,7 +16,8 @@ "supportedFeatures": [ "providerAdvertisements", "commandTransport", - "terminalGridSummary" + "terminalGridSummary", + "terminalGridLowering" ], "supportedPlugins": [], "unsupportedPlugins": [ @@ -33,10 +34,25 @@ "reason": "TUI provider-shell skeleton exists, but no TeX terminal fallback exists in this runtime." } ], + "worldSurfaceLowering": [ + { + "targetId": "tui", + "surfaceKinds": ["interactive-world", "interactive-world-editor"], + "projectionKinds": ["provider-authored-world-surface", "provider-authored-world-editor-surface"], + "supportLevel": "terminal-grid-command-surface", + "ownership": "runtime-lowers-provider-world-surface-without-owning-world-state", + "lossiness": "terminal-grid-summary-only", + "evidencePaths": [ + "runtimes/incubating/eve-tui/src/eve-tui-shell.mjs", + "runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs", + "web/fixtures/aetheria.provider-advertisement.json" + ] + } + ], "commandTransport": { "schema": "gamecult.eve.command.v1", "status": "provider-shell-contract-skeleton", - "emitter": "EveTui.EmitCommand", + "emitter": "EveTuiShell.createCommandIntent", "clientId": "tui", "authority": "TUI emits command intents through provider-advertised command boundaries; providers accept, deny, and publish receipts." }, @@ -113,6 +129,6 @@ }, "capture": { "status": "missing", - "note": "TUI transcript or cell-grid capture is a split blocker until EveTui owns a provider-agnostic lowerer." + "note": "TUI transcript or cell-grid capture is a split blocker until EveTui attaches durable terminal artifacts." } } diff --git a/runtimes/incubating/eve-tui/evetui-split-handoff.json b/runtimes/incubating/eve-tui/evetui-split-handoff.json index 1c1ff14..615943c 100644 --- a/runtimes/incubating/eve-tui/evetui-split-handoff.json +++ b/runtimes/incubating/eve-tui/evetui-split-handoff.json @@ -23,9 +23,13 @@ { "id": "tui-world-surface-lowering", "stage": "world-surface-lowering", - "currentPaths": [], + "currentPaths": [ + "runtimes/incubating/eve-tui/src/eve-tui-shell.mjs", + "runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs", + "runtimes/incubating/eve-tui/eve-runtime-capability.json" + ], "destinationOwner": "EveTui", - "replacementProof": "EveTui claims the provider-advertised tui world-surface lowering target with explicit support level, lossiness, command boundary, and transcript evidence." + "replacementProof": "EveTui claims the provider-advertised tui world-surface lowering target with explicit support level, lossiness, and command boundary evidence; transcript capture remains a separate lifecycle proof." }, { "id": "tui-command-transport", @@ -62,8 +66,8 @@ ], "requiredExternalProofs": [ "EveTui publishes a runtime capability manifest with terminal/grid capabilities.", - "EveTui owns a provider-shell contract skeleton that selects advertised provider surfaces, emits gamecult.eve.command.v1 intents, and produces an explicitly lossy terminal-grid summary.", - "EveTui claims the tui world-surface lowering target only after a real provider-agnostic lowerer exists.", + "EveTui owns a provider-shell contract skeleton that selects advertised provider surfaces, lowers Eve surface trees, emits gamecult.eve.command.v1 intents, and produces an explicitly lossy terminal grid.", + "EveTui owns the provider-agnostic terminal grid lowerer outside Eve incubation.", "EveTui consumes at least one non-Aetheria provider advertisement.", "EveTui consumes Aetheria's agent-facing TUI surface through provider advertisements without importing Aetheria internals.", "EveTui emits gamecult.eve.command.v1 intents and renders provider receipts.", diff --git a/runtimes/incubating/eve-tui/src/eve-tui-shell.mjs b/runtimes/incubating/eve-tui/src/eve-tui-shell.mjs index 7ea318f..46f4ef8 100644 --- a/runtimes/incubating/eve-tui/src/eve-tui-shell.mjs +++ b/runtimes/incubating/eve-tui/src/eve-tui-shell.mjs @@ -55,6 +55,36 @@ export class EveTuiShell { return intent; } + lowerSurface(surfaceDocument, providerAdvertisement, requestedSurfaceId = "") { + const selected = this.selectSurface(providerAdvertisement, requestedSurfaceId); + const document = normalizeSurfaceDocument(surfaceDocument); + if (document.surfaceId !== selected.surfaceId) { + throw new Error(`Surface document ${document.surfaceId} does not match advertised TUI surface ${selected.surfaceId}.`); + } + + const lines = [ + fitLine(`EveTui ${selected.providerId}`, this.width), + fitLine(`surface ${selected.surfaceId}`, this.width), + fitLine(`command ${selected.worldInteraction.commandBoundary || "unadvertised"}`, this.width), + fitLine(`receipt ${selected.worldInteraction.receiptSchema || "unadvertised"}`, this.width), + ...buildComponentLines(document.root, this.width), + ]; + + return { + schema: "gamecult.eve.tui_grid.v1", + runtimeId: "tui", + providerId: selected.providerId, + surfaceId: selected.surfaceId, + projectionKind: selected.worldInteraction.projectionKind, + commandBoundary: selected.worldInteraction.commandBoundary, + receiptSchema: selected.worldInteraction.receiptSchema, + ownership: selected.worldInteraction.ownership, + width: this.width, + lines, + lossiness: "terminal-grid-command-surface; summarizes provider-authored world surface without owning provider state", + }; + } + renderSummary(providerAdvertisement, requestedSurfaceId = "") { const selected = this.selectSurface(providerAdvertisement, requestedSurfaceId); const lines = [ @@ -71,7 +101,7 @@ export class EveTuiShell { surfaceId: selected.surfaceId, width: this.width, lines, - lossiness: "provider-shell-summary-only; not a full TUI world-surface lowering claim", + lossiness: "provider-shell-summary-only; use lowerSurface for TUI world-surface lowering", }; } } @@ -91,6 +121,21 @@ export function normalizeProviderAdvertisement(providerAdvertisement) { return { ...providerAdvertisement, providerId, surfaces }; } +export function normalizeSurfaceDocument(surfaceDocument) { + if (!surfaceDocument || typeof surfaceDocument !== "object") { + throw new Error("Surface document is required."); + } + if (surfaceDocument.schema !== "gamecult.eve.surface.v1") { + throw new Error(`Unexpected surface schema: ${surfaceDocument.schema || ""}`); + } + const surface = objectValue(surfaceDocument.surface); + const surfaceId = firstString(surface.id); + if (!surfaceId) throw new Error("Surface document missing surface.id."); + const root = objectValue(surface.root); + if (!root.id) throw new Error(`Surface document ${surfaceId} missing surface.root.`); + return { ...surfaceDocument, surfaceId, root }; +} + function normalizeWorldInteraction(value) { const source = objectValue(value); return { @@ -101,6 +146,32 @@ function normalizeWorldInteraction(value) { }; } +function buildComponentLines(component, width, depth = 0) { + const source = objectValue(component); + const kind = firstString(source.kind) || "component"; + const id = firstString(source.id) || "(anonymous)"; + const props = objectValue(source.props); + const label = firstString(props.label, props.title, props.text, props.bind, props.command, props.fieldId); + const indent = " ".repeat(Math.min(depth, 6)); + const ownLine = fitLine(`${indent}${terminalElementKind(kind)} ${id}${label ? ` ${label}` : ""}`, width); + const children = Array.isArray(source.children) ? source.children : []; + return [ + ownLine, + ...children.flatMap(child => buildComponentLines(child, width, depth + 1)), + ]; +} + +function terminalElementKind(componentKind) { + if (!componentKind) return "empty"; + if (componentKind.startsWith("control.")) return "command"; + if (componentKind.startsWith("embed.")) return "plugin"; + if (componentKind === "surface.slot") return "slot"; + if (componentKind.startsWith("field.") || componentKind.startsWith("world.")) return "world"; + if (componentKind.startsWith("text.") || componentKind === "text" || componentKind === "label") return "text"; + if (componentKind === "metric") return "metric"; + return componentKind; +} + function fitLine(value, width) { const text = String(value || ""); if (text.length <= width) return text; diff --git a/runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs b/runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs index 12fe3e3..d480395 100644 --- a/runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs +++ b/runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs @@ -43,10 +43,36 @@ test("summary grid is explicitly lossy provider-shell evidence", () => { assert.equal(grid.schema, "gamecult.eve.tui_grid.v1"); assert.equal(grid.runtimeId, "tui"); assert.equal(grid.surfaceId, "aetheria.daemon.game"); - assert.match(grid.lossiness, /not a full TUI world-surface lowering claim/); + assert.match(grid.lossiness, /use lowerSurface/); assert.ok(grid.lines.every(line => line.length <= 36)); }); +test("lowers provider surface trees into a terminal grid", () => { + const shell = new EveTuiShell({ width: 44 }); + const grid = shell.lowerSurface(surfaceDocument(), advertisement(), "aetheria.daemon.game"); + + assert.equal(grid.schema, "gamecult.eve.tui_grid.v1"); + assert.equal(grid.runtimeId, "tui"); + assert.equal(grid.providerId, "aetheria"); + assert.equal(grid.surfaceId, "aetheria.daemon.game"); + assert.equal(grid.projectionKind, "provider-authored-world-surface"); + assert.equal(grid.commandBoundary, "aetheria.daemon.commands"); + assert.equal(grid.receiptSchema, "aetheria.eve_command_acceptance_status.v1"); + assert.match(grid.lossiness, /terminal-grid-command-surface/); + assert.ok(grid.lines.every(line => line.length <= 44)); + assert.ok(grid.lines.some(line => line.includes("world aetheria.daemon.game.gravity"))); + assert.ok(grid.lines.some(line => line.includes("command aetheria.daemon.game.focus"))); + assert.ok(grid.lines.some(line => line.includes("plugin aetheria.daemon.game.norn"))); +}); + +test("rejects surface documents that do not match the advertised TUI target", () => { + const shell = new EveTuiShell(); + assert.throws( + () => shell.lowerSurface(surfaceDocument("aetheria.daemon.game"), advertisement(), "aetheria.daemon.editor"), + /does not match advertised TUI surface/, + ); +}); + function advertisement() { return { schema: "gamecult.eve.provider_advertisement.v1", @@ -78,3 +104,55 @@ function advertisement() { ], }; } + +function surfaceDocument(surfaceId = "aetheria.daemon.game") { + return { + type: "surface-state", + schema: "gamecult.eve.surface.v1", + providerId: "aetheria", + providerKind: "game.runtime", + title: "Aetheria world", + version: 1, + updatedAtUtc: "2026-07-09T00:00:00Z", + surface: { + id: surfaceId, + root: { + id: `${surfaceId}.root`, + kind: "surface", + props: {}, + children: [ + { + id: `${surfaceId}.gravity`, + kind: "field.surface2d", + props: { + label: "Current Zone Gravity", + bind: "aetheria.daemon.soaView.gravityField", + fieldId: "aetheria.zone.gravity", + }, + children: [], + }, + { + id: `${surfaceId}.focus`, + kind: "control.button", + props: { + label: "Focus Relay", + command: "aetheria.daemon.commands", + commandId: "aetheria.daemon.focus", + }, + children: [], + }, + { + id: `${surfaceId}.norn`, + kind: "embed.norn", + props: { + label: "Norn tactical map", + }, + children: [], + }, + ], + }, + styles: [], + }, + commands: [], + }; +} diff --git a/runtimes/incubating/eve-unity-scene/eve-runtime-capability.json b/runtimes/incubating/eve-unity-scene/eve-runtime-capability.json index e1e4b63..c06cd78 100644 --- a/runtimes/incubating/eve-unity-scene/eve-runtime-capability.json +++ b/runtimes/incubating/eve-unity-scene/eve-runtime-capability.json @@ -22,7 +22,7 @@ "unsupportedPlugins": [ { "pluginId": "sai.vn", - "reason": "Unity scene graph projection exists, but no Sai VN scene projection adapter or sidecar bridge exists in this runtime." + "reason": "Unity scene graph projection exists, but no Sai VN scene projection adapter for sidecar-advertised capabilities exists in this runtime." }, { "pluginId": "norn.graph", diff --git a/scripts/run-aetheria-conformance-consumer-smoke.ps1 b/scripts/run-aetheria-conformance-consumer-smoke.ps1 index 3566d28..e47b108 100644 --- a/scripts/run-aetheria-conformance-consumer-smoke.ps1 +++ b/scripts/run-aetheria-conformance-consumer-smoke.ps1 @@ -56,26 +56,30 @@ 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.game:electron-shell:Aetheria ` + --expect-interactive-world-surface aetheria:aetheria.daemon.game:tui:Aetheria ` --expect-interactive-world-surface aetheria:aetheria.daemon.editor:unity-uitoolkit:Aetheria ` --expect-interactive-world-surface aetheria:aetheria.daemon.editor:electron-shell:Aetheria ` + --expect-interactive-world-surface aetheria:aetheria.daemon.editor:tui: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:claimed:EveUnity:unity-scene ` --expect-world-lowering-coverage aetheria:aetheria.daemon.game:electron-shell:claimed:EveElectron:electron-shell ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.game:tui:claimed:EveTui:tui ` --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-world-lowering-coverage aetheria:aetheria.daemon.editor:electron-shell:claimed:EveElectron:electron-shell ` - --expect-world-lowering-coverage aetheria:aetheria.daemon.editor:tui:missing-claim:EveTui:tui ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.editor:tui:claimed:EveTui:tui ` --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:covered:EveUnity:unity-scene ` --expect-command-boundary-coverage aetheria:aetheria.daemon.game:electron-shell:covered:EveElectron:electron-shell ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.game:tui:covered:EveTui:tui ` --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-command-boundary-coverage aetheria:aetheria.daemon.editor:electron-shell:covered:EveElectron:electron-shell ` - --expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:missing-runtime-claim:EveTui:tui ` - --expect-world-lowering-gap aetheria:aetheria.daemon.editor:tui:EveTui:tui ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:covered:EveTui:tui ` --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-target-blocker "EveUnity:Unity scene runtime body graduates to EveUnity outside Aetheria product code" ` --expect-split-target-blocker "EveElectron:Electron shell runtime body graduates to EveElectron outside Aetheria product code" ` diff --git a/scripts/run-conformance-consumer-smoke.ps1 b/scripts/run-conformance-consumer-smoke.ps1 index 4f185b7..4d401f6 100644 --- a/scripts/run-conformance-consumer-smoke.ps1 +++ b/scripts/run-conformance-consumer-smoke.ps1 @@ -33,21 +33,20 @@ try { node .\tools\conformance\consume-export.mjs $consumerExport ` --expect-capability-matrix ` --expect-capability-gap runtime:Fensalir:direct2d:capture:missing ` - --expect-capability-gap "runtime:EveTui:tui:provider:aetheria:surface:aetheria.daemon.game:world-lowering-target:tui:missing-runtime" ` --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:claimed:EveUnity:unity-scene ` --expect-world-lowering-coverage aetheria:aetheria.daemon.game:electron-shell:claimed:EveElectron:electron-shell ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.game:tui:claimed:EveTui:tui ` --expect-world-lowering-coverage aetheria:aetheria.daemon.editor:electron-shell:claimed:EveElectron:electron-shell ` - --expect-world-lowering-coverage aetheria:aetheria.daemon.editor:tui:missing-claim:EveTui:tui ` + --expect-world-lowering-coverage aetheria:aetheria.daemon.editor:tui:claimed:EveTui:tui ` --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:covered:EveUnity:unity-scene ` --expect-command-boundary-coverage aetheria:aetheria.daemon.game:electron-shell:covered:EveElectron:electron-shell ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.game:tui:covered:EveTui:tui ` --expect-command-boundary-coverage aetheria:aetheria.daemon.editor:electron-shell:covered:EveElectron:electron-shell ` - --expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:missing-runtime-claim:EveTui:tui ` - --expect-world-lowering-gap aetheria:aetheria.daemon.game:tui:EveTui:tui ` - --expect-world-lowering-gap aetheria:aetheria.daemon.editor:tui:EveTui:tui ` + --expect-command-boundary-coverage aetheria:aetheria.daemon.editor:tui:covered:EveTui:tui ` --expect-capability-gap "split-target:EveUnity:EveUnity:proof:Tagged UPM release" ` --expect-conformance-handoff if ($LASTEXITCODE -ne 0) { diff --git a/scripts/run-eveelectron-lifecycle-smoke.ps1 b/scripts/run-eveelectron-lifecycle-smoke.ps1 index e12180b..318d11d 100644 --- a/scripts/run-eveelectron-lifecycle-smoke.ps1 +++ b/scripts/run-eveelectron-lifecycle-smoke.ps1 @@ -45,7 +45,7 @@ foreach ($feature in @("providerAdvertisements", "commandTransport", "surfaceTre } } if (@($manifest.supportedPlugins).Count -ne 0) { - throw "EveElectron must not claim plugin projection before runtime adapters or sidecar bridges exist" + throw "EveElectron must not claim plugin projection before runtime projection adapters for sidecar-advertised capabilities exist" } $worldSurfaceLoweringClaims = @() diff --git a/scripts/run-evetui-lifecycle-smoke.ps1 b/scripts/run-evetui-lifecycle-smoke.ps1 index e1b15f8..8545633 100644 --- a/scripts/run-evetui-lifecycle-smoke.ps1 +++ b/scripts/run-evetui-lifecycle-smoke.ps1 @@ -36,13 +36,37 @@ if ($manifest.incubation.splitTarget -ne "EveTui") { throw "Unexpected EveTui split target: $($manifest.incubation.splitTarget)" } -foreach ($feature in @("providerAdvertisements", "commandTransport", "terminalGridSummary")) { +foreach ($feature in @("providerAdvertisements", "commandTransport", "terminalGridSummary", "terminalGridLowering")) { 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 the generic TUI lowerer exists" + throw "EveTui must not claim plugin projection before terminal projection adapters for sidecar-advertised capabilities exist" +} + +$worldSurfaceLoweringClaims = @() +if ($null -ne $manifest.worldSurfaceLowering) { + $worldSurfaceLoweringClaims = @($manifest.worldSurfaceLowering) +} +if ($worldSurfaceLoweringClaims.Count -ne 1) { + throw "EveTui must claim exactly one world-surface lowering target" +} +$worldSurfaceLoweringClaim = $worldSurfaceLoweringClaims | Where-Object { $_.targetId -eq "tui" } | Select-Object -First 1 +if (-not $worldSurfaceLoweringClaim) { + throw "EveTui manifest missing tui world-surface lowering claim" +} +if ($worldSurfaceLoweringClaim.supportLevel -ne "terminal-grid-command-surface") { + throw "Unexpected EveTui world-surface support level: $($worldSurfaceLoweringClaim.supportLevel)" +} +if ($worldSurfaceLoweringClaim.ownership -ne "runtime-lowers-provider-world-surface-without-owning-world-state") { + throw "Unexpected EveTui world-surface ownership: $($worldSurfaceLoweringClaim.ownership)" +} +foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) { + $absoluteEvidencePath = Join-Path $projectRoot $evidencePath + if (-not (Test-Path -LiteralPath $absoluteEvidencePath)) { + throw "EveTui world-surface claim missing evidence path: $evidencePath" + } } foreach ($pluginId in @("sai.vn", "norn.graph", "tex.math")) { diff --git a/scripts/run-evetui-provider-shell-smoke.ps1 b/scripts/run-evetui-provider-shell-smoke.ps1 index 19c9575..c9a3385 100644 --- a/scripts/run-evetui-provider-shell-smoke.ps1 +++ b/scripts/run-evetui-provider-shell-smoke.ps1 @@ -24,12 +24,46 @@ 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")) { +foreach ($feature in @("providerAdvertisements", "commandTransport", "terminalGridSummary", "terminalGridLowering")) { if (-not (@($manifest.supportedFeatures) -contains $feature)) { throw "EveTui provider shell missing supported feature: $feature" } } +$worldSurfaceLoweringClaims = @() +if ($null -ne $manifest.worldSurfaceLowering) { + $worldSurfaceLoweringClaims = @($manifest.worldSurfaceLowering) +} +if ($worldSurfaceLoweringClaims.Count -ne 1) { + throw "EveTui must claim exactly one provider world-surface lowering target" +} +$worldSurfaceLoweringClaim = $worldSurfaceLoweringClaims | Where-Object { $_.targetId -eq "tui" } | Select-Object -First 1 +if (-not $worldSurfaceLoweringClaim) { + throw "EveTui missing tui world-surface lowering claim" +} +foreach ($surfaceKind in @("interactive-world", "interactive-world-editor")) { + if (-not (@($worldSurfaceLoweringClaim.surfaceKinds) -contains $surfaceKind)) { + throw "EveTui world-surface claim missing surface kind: $surfaceKind" + } +} +foreach ($projectionKind in @("provider-authored-world-surface", "provider-authored-world-editor-surface")) { + if (-not (@($worldSurfaceLoweringClaim.projectionKinds) -contains $projectionKind)) { + throw "EveTui world-surface claim missing projection kind: $projectionKind" + } +} +if ($worldSurfaceLoweringClaim.supportLevel -ne "terminal-grid-command-surface") { + throw "Unexpected EveTui support level: $($worldSurfaceLoweringClaim.supportLevel)" +} +if ($worldSurfaceLoweringClaim.ownership -ne "runtime-lowers-provider-world-surface-without-owning-world-state") { + throw "Unexpected EveTui ownership: $($worldSurfaceLoweringClaim.ownership)" +} +foreach ($evidencePath in @($worldSurfaceLoweringClaim.evidencePaths)) { + $absoluteEvidencePath = Join-Path $projectRoot $evidencePath + if (-not (Test-Path -LiteralPath $absoluteEvidencePath)) { + throw "EveTui world-surface claim missing evidence path: $evidencePath" + } +} + $expectedFiles = @( "runtimes\incubating\eve-tui\package.json", "runtimes\incubating\eve-tui\src\eve-tui-shell.mjs", @@ -44,14 +78,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", "createCommandIntent", "renderSummary", "gamecult.eve.tui_grid.v1", "commandBoundary", "receiptSchema")) { +foreach ($symbol in @("EveTuiShell", "selectSurface", "lowerSurface", "normalizeSurfaceDocument", "buildComponentLines", "terminalElementKind", "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", "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", "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" } diff --git a/scripts/run-evetui-split-handoff-smoke.ps1 b/scripts/run-evetui-split-handoff-smoke.ps1 index 8517cbb..640e93e 100644 --- a/scripts/run-evetui-split-handoff-smoke.ps1 +++ b/scripts/run-evetui-split-handoff-smoke.ps1 @@ -61,7 +61,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-command-transport")) { + if ($id -in @("tui-runtime-body", "tui-world-surface-lowering", "tui-command-transport")) { if ($currentPaths.Count -eq 0) { throw "EveTui split handoff move set $id must name provider-shell skeleton paths" } diff --git a/scripts/run-eveunity-scene-lifecycle-smoke.ps1 b/scripts/run-eveunity-scene-lifecycle-smoke.ps1 index 5da5bf8..925b985 100644 --- a/scripts/run-eveunity-scene-lifecycle-smoke.ps1 +++ b/scripts/run-eveunity-scene-lifecycle-smoke.ps1 @@ -45,7 +45,7 @@ foreach ($feature in @("providerAdvertisements", "commandTransport", "sceneGraph } } if (@($manifest.supportedPlugins).Count -ne 0) { - throw "EveUnity scene must not claim plugin projection before runtime adapters or sidecar bridges exist" + throw "EveUnity scene must not claim plugin projection before runtime projection adapters for sidecar-advertised capabilities exist" } $worldSurfaceLoweringClaims = @() if ($null -ne $manifest.worldSurfaceLowering) { diff --git a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 index 1313bea..9317f92 100644 --- a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 @@ -62,6 +62,7 @@ node $consumerScript $consumerExport ` --expect-runtime-feature tui:providerAdvertisements ` --expect-runtime-feature tui:commandTransport ` --expect-runtime-feature tui:terminalGridSummary ` + --expect-runtime-feature tui:terminalGridLowering ` --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 ` @@ -75,6 +76,9 @@ node $consumerScript $consumerExport ` --expect-runtime-world-target electron-shell:electron-shell ` --expect-runtime-world-field electron-shell:electron-shell:supportLevel:electron-shell-surface-tree-command-surface ` --expect-runtime-world-field electron-shell:electron-shell:ownership:runtime-lowers-provider-world-surface-without-owning-world-state ` + --expect-runtime-world-target tui:tui ` + --expect-runtime-world-field tui:tui:supportLevel:terminal-grid-command-surface ` + --expect-runtime-world-field tui:tui:ownership:runtime-lowers-provider-world-surface-without-owning-world-state ` --expect-runtime-plugin-projection unity-uitoolkit:sai.vn:supported:EveUnity ` --expect-runtime-plugin-projection unity-uitoolkit:norn.graph:supported:EveUnity ` --expect-runtime-plugin-projection unity-uitoolkit:tex.math:unsupported:EveUnity ` @@ -94,6 +98,9 @@ node $consumerScript $consumerExport ` --expect-runtime-plugin-gap electron-shell:sai.vn:EveElectron ` --expect-runtime-plugin-gap electron-shell:norn.graph:EveElectron ` --expect-runtime-plugin-gap electron-shell:tex.math:EveElectron ` + --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 ` diff --git a/scripts/run-split-target-conformance-consumer-smoke.ps1 b/scripts/run-split-target-conformance-consumer-smoke.ps1 index 9c04e6f..8902893 100644 --- a/scripts/run-split-target-conformance-consumer-smoke.ps1 +++ b/scripts/run-split-target-conformance-consumer-smoke.ps1 @@ -75,6 +75,7 @@ try { --expect-split-target-blocker "EveTui:runtime:tui:status:pending" ` --expect-split-target-blocker-record EveTui:runtime-feature:tui:embeddedDocuments ` --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-target-blocker "EveTui:TUI runtime body graduates to EveTui outside provider product code" if ($LASTEXITCODE -ne 0) { diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index 0533e19..cbc8382 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -689,7 +689,7 @@ ] }, { - "description": "EveTui provider-shell skeleton selects advertised surfaces and emits Eve command intents.", + "description": "EveTui provider-shell skeleton selects advertised surfaces, lowers Eve surface trees into terminal grids, and emits Eve command intents.", "status": "passed", "evidencePaths": [ "runtimes/incubating/eve-tui/package.json", @@ -701,7 +701,6 @@ ], "pendingProofs": [ "TUI runtime body graduates to EveTui outside provider product code.", - "TUI claims provider-advertised tui world-surface lowering with real transcript evidence.", "TUI terminal transcript or cell-grid captures are attached to conformance output." ] } @@ -791,7 +790,7 @@ "splitHandoffPath": "runtimes/incubating/eve-tui/evetui-split-handoff.json", "requiredFixtures": ["embedded-surface", "aetheria-world"], "pluginFixtures": [], - "supportedFeatures": ["providerAdvertisements", "commandTransport", "terminalGridSummary"], + "supportedFeatures": ["providerAdvertisements", "commandTransport", "terminalGridSummary", "terminalGridLowering"], "supportedPlugins": [], "unsupportedPlugins": [ { @@ -807,6 +806,21 @@ "reason": "TUI provider-shell skeleton exists, but no TeX terminal fallback exists in this runtime." } ], + "worldSurfaceLowering": [ + { + "targetId": "tui", + "surfaceKinds": ["interactive-world", "interactive-world-editor"], + "projectionKinds": ["provider-authored-world-surface", "provider-authored-world-editor-surface"], + "supportLevel": "terminal-grid-command-surface", + "ownership": "runtime-lowers-provider-world-surface-without-owning-world-state", + "lossiness": "terminal-grid-summary-only", + "evidencePaths": [ + "runtimes/incubating/eve-tui/src/eve-tui-shell.mjs", + "runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs", + "web/fixtures/aetheria.provider-advertisement.json" + ] + } + ], "expectedPaths": [ "runtimes/incubating/eve-tui/package.json", "runtimes/incubating/eve-tui/src/eve-tui-shell.mjs", @@ -820,16 +834,16 @@ "expectedSourceSymbols": [ { "path": "runtimes/incubating/eve-tui/src/eve-tui-shell.mjs", - "contains": ["EveTuiShell", "selectSurface", "createCommandIntent", "renderSummary", "gamecult.eve.tui_grid.v1", "commandBoundary", "receiptSchema"] + "contains": ["EveTuiShell", "selectSurface", "lowerSurface", "normalizeSurfaceDocument", "buildComponentLines", "terminalElementKind", "createCommandIntent", "renderSummary", "gamecult.eve.tui_grid.v1", "commandBoundary", "receiptSchema"] }, { "path": "runtimes/incubating/eve-tui/test/eve-tui-shell.test.mjs", - "contains": ["selects advertised provider surfaces", "command intents carry provider-advertised boundaries", "summary grid is explicitly lossy", "aetheria.daemon.commands"] + "contains": ["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"] } ], "capture": { "status": "missing", - "note": "TUI transcript or cell-grid capture is a split blocker until EveTui owns a provider-agnostic lowerer." + "note": "TUI transcript or cell-grid capture is a split blocker until EveTui attaches durable terminal artifacts." } }, { @@ -852,7 +866,7 @@ "unsupportedPlugins": [ { "pluginId": "sai.vn", - "reason": "Unity scene graph projection exists, but no Sai VN scene projection adapter or sidecar bridge exists in this runtime." + "reason": "Unity scene graph projection exists, but no Sai VN scene projection adapter for sidecar-advertised capabilities exists in this runtime." }, { "pluginId": "norn.graph",