diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index ae6ce69..f217b41 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -457,8 +457,11 @@ Recently cut: lifecycle smoke at `scripts/run-evetui-lifecycle-smoke.ps1`. The manifest 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. + it now carries an executable terminal capture request contract through + `tools/evetui/evetui-capture-contract.mjs` and + `scripts/run-evetui-capture-contract-smoke.ps1`. Plugin projection, terminal + package release, and actual transcript/cell-grid capture artifacts remain + 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, @@ -517,6 +520,17 @@ Recently cut: `scripts/run-eveunity-scene-capture-contract-smoke.ps1` proves the request without pretending a Unity scene frame has been captured. The actual frame or screenshot artifact remains a split blocker for EveUnity. +- EveTui capture lifecycle now carries a structured pending capture request + contract for terminal artifacts. `captureContract` names the TUI runtime, + transcript/cell-grid capture kind, ANSI transcript or JSON grid artifact kind, + conformance attachment point, required Aetheria provider surface, request + schema, request builder, advertisement input, and authority rule. + `tools/evetui/evetui-capture-contract.mjs` builds a + `gamecult.eve.runtime_capture_request.v1` request from the runtime capability + manifest and provider advertisement, and + `scripts/run-evetui-capture-contract-smoke.ps1` proves that request path + without pretending a durable terminal transcript has been captured. The + actual transcript or cell-grid artifact remains a split blocker for EveTui. - Runtime-owner conformance consumption now asserts EveUnity lifecycle stage evidence directly. The generic consumer supports `--expect-runtime-lifecycle-status` and diff --git a/docs/parity-testing-harness.md b/docs/parity-testing-harness.md index e882c29..77db111 100644 --- a/docs/parity-testing-harness.md +++ b/docs/parity-testing-harness.md @@ -307,9 +307,10 @@ a narrow provider-advertised surface-tree command surface and exposes a typed capture request contract, while packaged rendering, embedded document rendering, actual window capture, and plugin projection remain 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 +provider-advertised terminal-grid command surface and exposes a typed terminal +capture request contract, while actual 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 and exposes a typed capture request diff --git a/runtimes/incubating/eve-tui/eve-runtime-capability.json b/runtimes/incubating/eve-tui/eve-runtime-capability.json index 829d43f..3e4ad2b 100644 --- a/runtimes/incubating/eve-tui/eve-runtime-capability.json +++ b/runtimes/incubating/eve-tui/eve-runtime-capability.json @@ -112,6 +112,10 @@ "captureContract": { "ownerRepo": "EveTui", "runtimeId": "tui", + "targetId": "tui", + "requestSchema": "gamecult.eve.runtime_capture_request.v1", + "requestBuilder": "tools/evetui/evetui-capture-contract.mjs", + "advertisementPath": "web/fixtures/aetheria.provider-advertisement.json", "captureKind": "terminal-transcript-or-cell-grid", "artifactKind": "ansi-transcript-or-json-grid", "artifactPattern": "artifacts/evetui-capture/{stamp}/tui-transcript.ansi", @@ -121,7 +125,11 @@ "authority": "Capture observes terminal projection only; provider state, command acceptance, and receipts stay provider-owned.", "publishProof": "Terminal transcript or cell-grid capture artifact is attached to the runtime conformance report from EveTui." }, - "evidencePaths": [], + "evidencePaths": [ + "tools/evetui/evetui-capture-contract.mjs", + "tools/evetui/evetui-capture-contract.test.mjs", + "scripts/run-evetui-capture-contract-smoke.ps1" + ], "pendingProofs": [ "TUI terminal transcript or cell-grid capture artifact is attached to the runtime conformance report." ] diff --git a/runtimes/incubating/eve-tui/evetui-split-handoff.json b/runtimes/incubating/eve-tui/evetui-split-handoff.json index 615943c..ee4a39d 100644 --- a/runtimes/incubating/eve-tui/evetui-split-handoff.json +++ b/runtimes/incubating/eve-tui/evetui-split-handoff.json @@ -44,9 +44,13 @@ { "id": "tui-capture-lifecycle", "stage": "capture", - "currentPaths": [], + "currentPaths": [ + "tools/evetui/evetui-capture-contract.mjs", + "tools/evetui/evetui-capture-contract.test.mjs", + "scripts/run-evetui-capture-contract-smoke.ps1" + ], "destinationOwner": "EveTui", - "replacementProof": "EveTui attaches deterministic terminal transcript or cell-grid capture artifacts to conformance output." + "replacementProof": "EveTui builds a provider-advertisement-backed terminal capture request now; the split is not complete until EveTui attaches deterministic terminal transcript or cell-grid capture artifacts to conformance output." } ], "contractInputs": [ diff --git a/scripts/run-evetui-capture-contract-smoke.ps1 b/scripts/run-evetui-capture-contract-smoke.ps1 new file mode 100644 index 0000000..2902777 --- /dev/null +++ b/scripts/run-evetui-capture-contract-smoke.ps1 @@ -0,0 +1,99 @@ +param( + [string] $CapabilityManifestPath = "runtimes\incubating\eve-tui\eve-runtime-capability.json", + [string] $AdvertisementPath = "web\fixtures\aetheria.provider-advertisement.json", + [string] $OutputPath = "artifacts\evetui-capture-contract\latest\capture-request.json", + [string] $Stamp = "smoke" +) + +$ErrorActionPreference = "Stop" + +$projectRoot = Split-Path -Parent $PSScriptRoot +$absoluteCapabilityPath = if ([System.IO.Path]::IsPathRooted($CapabilityManifestPath)) { + $CapabilityManifestPath +} else { + Join-Path $projectRoot $CapabilityManifestPath +} +$absoluteAdvertisementPath = if ([System.IO.Path]::IsPathRooted($AdvertisementPath)) { + $AdvertisementPath +} else { + Join-Path $projectRoot $AdvertisementPath +} +$absoluteOutputPath = if ([System.IO.Path]::IsPathRooted($OutputPath)) { + $OutputPath +} else { + Join-Path $projectRoot $OutputPath +} + +foreach ($path in @($absoluteCapabilityPath, $absoluteAdvertisementPath)) { + if (-not (Test-Path -LiteralPath $path)) { + throw "EveTui capture contract input not found: $path" + } +} + +$manifest = Get-Content -LiteralPath $absoluteCapabilityPath -Raw | ConvertFrom-Json +$captureContract = $manifest.lifecycle.capture.captureContract +if ($null -eq $captureContract) { + throw "EveTui capture contract missing lifecycle.capture.captureContract" +} +foreach ($field in @("ownerRepo", "runtimeId", "targetId", "requestSchema", "requestBuilder", "advertisementPath", "captureKind", "artifactKind", "artifactPattern", "conformanceAttachment", "requiredProvider", "requiredSurface", "authority", "publishProof")) { + if (-not $captureContract.$field) { + throw "EveTui capture contract missing $field" + } +} +if ($captureContract.ownerRepo -ne "EveTui") { + throw "Unexpected EveTui capture owner: $($captureContract.ownerRepo)" +} +if ($captureContract.runtimeId -ne "tui") { + throw "Unexpected EveTui capture runtime: $($captureContract.runtimeId)" +} +if ($captureContract.targetId -ne "tui") { + throw "Unexpected EveTui capture target: $($captureContract.targetId)" +} +if ($captureContract.requestSchema -ne "gamecult.eve.runtime_capture_request.v1") { + throw "Unexpected EveTui capture request schema: $($captureContract.requestSchema)" +} + +$builderPath = Join-Path $projectRoot $captureContract.requestBuilder +if (-not (Test-Path -LiteralPath $builderPath)) { + throw "EveTui capture request builder not found: $($captureContract.requestBuilder)" +} +if ((Join-Path $projectRoot $captureContract.advertisementPath) -ne $absoluteAdvertisementPath) { + throw "EveTui capture advertisement path mismatch: $($captureContract.advertisementPath) vs $AdvertisementPath" +} + +node --test (Join-Path $projectRoot "tools\evetui\evetui-capture-contract.test.mjs") +if ($LASTEXITCODE -ne 0) { + throw "EveTui capture contract tests failed with exit code $LASTEXITCODE" +} + +node $builderPath --capability $absoluteCapabilityPath --advertisement $absoluteAdvertisementPath --output $absoluteOutputPath --stamp $Stamp +if ($LASTEXITCODE -ne 0) { + throw "EveTui capture request builder failed with exit code $LASTEXITCODE" +} +if (-not (Test-Path -LiteralPath $absoluteOutputPath)) { + throw "EveTui capture request was not written: $absoluteOutputPath" +} + +$request = Get-Content -LiteralPath $absoluteOutputPath -Raw | ConvertFrom-Json +foreach ($expectation in @( + @{ field = "schema"; value = "gamecult.eve.runtime_capture_request.v1" }, + @{ field = "runtimeId"; value = "tui" }, + @{ field = "ownerRepo"; value = "EveTui" }, + @{ field = "providerId"; value = "aetheria" }, + @{ field = "surfaceId"; value = "aetheria.daemon.game" }, + @{ field = "targetId"; value = "tui" }, + @{ field = "commandBoundary"; value = "aetheria.daemon.commands" }, + @{ field = "receiptSchema"; value = "aetheria.eve_command_acceptance_status.v1" }, + @{ field = "captureKind"; value = "terminal-transcript-or-cell-grid" }, + @{ field = "artifactKind"; value = "ansi-transcript-or-json-grid" }, + @{ field = "conformanceAttachment"; value = "runtime.captureArtifacts[]" } +)) { + if ($request.($expectation.field) -ne $expectation.value) { + throw "EveTui capture request $($expectation.field) expected $($expectation.value) got $($request.($expectation.field))" + } +} +if ($request.artifactPath -ne "artifacts/evetui-capture/$Stamp/tui-transcript.ansi") { + throw "Unexpected EveTui capture artifact path: $($request.artifactPath)" +} + +Write-Host "EveTui capture contract smoke passed: $absoluteOutputPath" diff --git a/scripts/run-evetui-lifecycle-smoke.ps1 b/scripts/run-evetui-lifecycle-smoke.ps1 index 8545633..0209a4b 100644 --- a/scripts/run-evetui-lifecycle-smoke.ps1 +++ b/scripts/run-evetui-lifecycle-smoke.ps1 @@ -135,13 +135,33 @@ foreach ($pathProperty in @("runnerScript", "consumerProject")) { } $captureContract = $manifest.lifecycle.capture.captureContract -foreach ($field in @("ownerRepo", "runtimeId", "captureKind", "artifactKind", "artifactPattern", "conformanceAttachment", "requiredProvider", "requiredSurface", "authority", "publishProof")) { +foreach ($field in @("ownerRepo", "runtimeId", "targetId", "requestSchema", "requestBuilder", "advertisementPath", "captureKind", "artifactKind", "artifactPattern", "conformanceAttachment", "requiredProvider", "requiredSurface", "authority", "publishProof")) { if (-not $captureContract.$field) { throw "EveTui capture contract missing $field" } } +if ($captureContract.runtimeId -ne "tui") { + throw "EveTui capture contract has unexpected runtime: $($captureContract.runtimeId)" +} +if ($captureContract.targetId -ne "tui") { + throw "EveTui capture contract has unexpected target: $($captureContract.targetId)" +} +if ($captureContract.requestSchema -ne "gamecult.eve.runtime_capture_request.v1") { + throw "EveTui capture contract has unexpected request schema: $($captureContract.requestSchema)" +} +if ($captureContract.captureKind -ne "terminal-transcript-or-cell-grid") { + throw "EveTui capture contract has unexpected capture kind: $($captureContract.captureKind)" +} +foreach ($pathProperty in @("requestBuilder", "advertisementPath")) { + $relativePath = $captureContract.$pathProperty + $absolutePath = Join-Path $projectRoot $relativePath + if (-not (Test-Path -LiteralPath $absolutePath)) { + throw "EveTui capture contract $pathProperty does not exist: $relativePath" + } +} & (Join-Path $projectRoot "scripts\run-evetui-split-handoff-smoke.ps1") & (Join-Path $projectRoot "scripts\run-evetui-provider-shell-smoke.ps1") +& (Join-Path $projectRoot "scripts\run-evetui-capture-contract-smoke.ps1") Write-Host "EveTui lifecycle smoke passed: $absoluteManifestPath" diff --git a/scripts/run-evetui-split-handoff-smoke.ps1 b/scripts/run-evetui-split-handoff-smoke.ps1 index 640e93e..3391977 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-world-surface-lowering", "tui-command-transport")) { + if ($id -in @("tui-runtime-body", "tui-world-surface-lowering", "tui-command-transport", "tui-capture-lifecycle")) { if ($currentPaths.Count -eq 0) { throw "EveTui split handoff move set $id must name provider-shell skeleton paths" } @@ -71,8 +71,6 @@ foreach ($id in $expectedMoveSets.Keys) { throw "EveTui split handoff move set $id references missing current path: $relativePath" } } - } elseif ($currentPaths.Count -ne 0) { - throw "EveTui split handoff move set $id must not claim existing Eve source paths before its proof exists" } if ($observedProviderPaths.Count -ne 0) { throw "EveTui split handoff move set $id must not treat provider product paths as generic TUI runtime source" diff --git a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 index 2396795..0214b03 100644 --- a/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-runtime-owner-conformance-consumer-smoke.ps1 @@ -186,6 +186,10 @@ node $consumerScript $consumerExport ` --expect-runtime-lifecycle-field "tui:test:testContract.runnerKind:terminal-provider-shell-smoke" ` --expect-runtime-lifecycle-field "tui:test:testContract.runnerScript:scripts/run-evetui-provider-shell-smoke.ps1" ` --expect-runtime-lifecycle-field "tui:capture:captureContract.captureKind:terminal-transcript-or-cell-grid" ` + --expect-runtime-lifecycle-field "tui:capture:captureContract.targetId:tui" ` + --expect-runtime-lifecycle-field "tui:capture:captureContract.requestSchema:gamecult.eve.runtime_capture_request.v1" ` + --expect-runtime-lifecycle-field "tui:capture:captureContract.requestBuilder:tools/evetui/evetui-capture-contract.mjs" ` + --expect-runtime-lifecycle-field "tui:capture:captureContract.advertisementPath:web/fixtures/aetheria.provider-advertisement.json" ` --expect-runtime-lifecycle-field "tui:capture:captureContract.requiredSurface:aetheria.daemon.game" if ($LASTEXITCODE -ne 0) { diff --git a/scripts/run-split-target-conformance-consumer-smoke.ps1 b/scripts/run-split-target-conformance-consumer-smoke.ps1 index 5e2972f..e51d8d8 100644 --- a/scripts/run-split-target-conformance-consumer-smoke.ps1 +++ b/scripts/run-split-target-conformance-consumer-smoke.ps1 @@ -79,6 +79,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-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) { throw "Split target conformance consumer smoke failed with exit code $LASTEXITCODE" diff --git a/tools/evetui/evetui-capture-contract.mjs b/tools/evetui/evetui-capture-contract.mjs new file mode 100644 index 0000000..9ff1dd5 --- /dev/null +++ b/tools/evetui/evetui-capture-contract.mjs @@ -0,0 +1,122 @@ +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +export function buildTuiCaptureRequest({ + advertisement, + capabilityManifest, + advertisementPath = "", + capabilityManifestPath = "", + stamp = new Date().toISOString().replace(/[:.]/g, "-"), +} = {}) { + if (!advertisement || typeof advertisement !== "object") { + throw new Error("advertisement is required"); + } + if (!capabilityManifest || typeof capabilityManifest !== "object") { + throw new Error("capabilityManifest is required"); + } + + const captureContract = capabilityManifest.lifecycle?.capture?.captureContract; + if (!captureContract) { + throw new Error("capability manifest is missing lifecycle.capture.captureContract"); + } + + if (advertisement.providerId !== captureContract.requiredProvider) { + throw new Error( + `capture provider mismatch: expected ${captureContract.requiredProvider} got ${advertisement.providerId || "missing"}`, + ); + } + + const targetId = captureContract.targetId || captureContract.runtimeId; + const surface = (advertisement.surfaces || []).find(candidate => candidate.surfaceId === captureContract.requiredSurface); + if (!surface) { + throw new Error(`capture surface not advertised: ${captureContract.requiredSurface}`); + } + + const loweringTargets = surface.worldInteraction?.loweringTargets || []; + if (!loweringTargets.includes(targetId)) { + throw new Error(`surface ${surface.surfaceId} does not advertise lowering target ${targetId}`); + } + + const artifactPath = replaceStamp(captureContract.artifactPattern, stamp); + + return { + schema: captureContract.requestSchema || "gamecult.eve.runtime_capture_request.v1", + runtimeId: capabilityManifest.runtimeId, + ownerRepo: captureContract.ownerRepo, + providerId: advertisement.providerId, + surfaceId: surface.surfaceId, + surfaceKind: surface.surfaceKind || "", + targetId, + projectionKind: surface.worldInteraction?.projectionKind || "", + commandBoundary: surface.worldInteraction?.commandBoundary || "", + receiptSchema: surface.worldInteraction?.receiptSchema || "", + captureKind: captureContract.captureKind, + artifactKind: captureContract.artifactKind, + artifactPath, + conformanceAttachment: captureContract.conformanceAttachment, + authority: captureContract.authority, + sourceAdvertisementPath: advertisementPath, + sourceCapabilityManifestPath: capabilityManifestPath, + issuedAtUtc: stamp, + }; +} + +export function loadJsonFile(filePath) { + return JSON.parse(readFileSync(filePath, "utf8")); +} + +export function writeCaptureRequest(request, outputPath) { + mkdirSync(path.dirname(outputPath), { recursive: true }); + writeFileSync(outputPath, `${JSON.stringify(request, null, 2)}\n`, "utf8"); +} + +function replaceStamp(pattern, stamp) { + if (!pattern || !pattern.includes("{stamp}")) { + throw new Error(`capture artifact pattern must include {stamp}: ${pattern || "missing"}`); + } + return pattern.replace("{stamp}", stamp); +} + +function parseArgs(argv) { + const args = {}; + for (let index = 0; index < argv.length; index += 1) { + const value = argv[index]; + if (!value.startsWith("--")) continue; + const key = value.slice(2); + const next = argv[index + 1]; + if (!next || next.startsWith("--")) { + args[key] = true; + } else { + args[key] = next; + index += 1; + } + } + return args; +} + +function runCli() { + const args = parseArgs(process.argv.slice(2)); + for (const required of ["advertisement", "capability", "output"]) { + if (!args[required]) { + throw new Error(`missing required --${required}`); + } + } + + const stamp = args.stamp || new Date().toISOString().replace(/[:.]/g, "-"); + const request = buildTuiCaptureRequest({ + advertisement: loadJsonFile(args.advertisement), + capabilityManifest: loadJsonFile(args.capability), + advertisementPath: args.advertisement, + capabilityManifestPath: args.capability, + stamp, + }); + writeCaptureRequest(request, args.output); + process.stdout.write(`${args.output}\n`); +} + +const invokedPath = process.argv[1] ? path.resolve(process.argv[1]) : ""; +const modulePath = fileURLToPath(import.meta.url); +if (invokedPath === modulePath) { + runCli(); +} diff --git a/tools/evetui/evetui-capture-contract.test.mjs b/tools/evetui/evetui-capture-contract.test.mjs new file mode 100644 index 0000000..58ba6f4 --- /dev/null +++ b/tools/evetui/evetui-capture-contract.test.mjs @@ -0,0 +1,42 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import test from "node:test"; +import { buildTuiCaptureRequest } from "./evetui-capture-contract.mjs"; + +const advertisement = JSON.parse(readFileSync(new URL("../../web/fixtures/aetheria.provider-advertisement.json", import.meta.url), "utf8")); +const capabilityManifest = JSON.parse(readFileSync(new URL("../../runtimes/incubating/eve-tui/eve-runtime-capability.json", import.meta.url), "utf8")); + +test("builds TUI capture request from provider advertisement", () => { + const request = buildTuiCaptureRequest({ + advertisement, + capabilityManifest, + advertisementPath: "web/fixtures/aetheria.provider-advertisement.json", + capabilityManifestPath: "runtimes/incubating/eve-tui/eve-runtime-capability.json", + stamp: "smoke", + }); + + assert.equal(request.schema, "gamecult.eve.runtime_capture_request.v1"); + assert.equal(request.runtimeId, "tui"); + assert.equal(request.ownerRepo, "EveTui"); + assert.equal(request.providerId, "aetheria"); + assert.equal(request.surfaceId, "aetheria.daemon.game"); + assert.equal(request.targetId, "tui"); + assert.equal(request.projectionKind, "provider-authored-world-surface"); + assert.equal(request.commandBoundary, "aetheria.daemon.commands"); + assert.equal(request.receiptSchema, "aetheria.eve_command_acceptance_status.v1"); + assert.equal(request.captureKind, "terminal-transcript-or-cell-grid"); + assert.equal(request.artifactKind, "ansi-transcript-or-json-grid"); + assert.equal(request.artifactPath, "artifacts/evetui-capture/smoke/tui-transcript.ansi"); + assert.match(request.authority, /provider state/); +}); + +test("rejects capture request when the surface does not advertise TUI", () => { + const withoutTarget = structuredClone(advertisement); + const surface = withoutTarget.surfaces.find(candidate => candidate.surfaceId === "aetheria.daemon.game"); + surface.worldInteraction.loweringTargets = surface.worldInteraction.loweringTargets.filter(target => target !== "tui"); + + assert.throws( + () => buildTuiCaptureRequest({ advertisement: withoutTarget, capabilityManifest, stamp: "smoke" }), + /does not advertise lowering target tui/, + ); +}); diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index 7b8aa31..56665f1 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -840,7 +840,10 @@ "runtimes/incubating/eve-tui/eve-runtime-capability.json", "scripts/run-evetui-split-handoff-smoke.ps1", "scripts/run-evetui-lifecycle-smoke.ps1", - "scripts/run-evetui-provider-shell-smoke.ps1" + "scripts/run-evetui-provider-shell-smoke.ps1", + "scripts/run-evetui-capture-contract-smoke.ps1", + "tools/evetui/evetui-capture-contract.mjs", + "tools/evetui/evetui-capture-contract.test.mjs" ], "expectedSourceSymbols": [ { @@ -850,6 +853,14 @@ { "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", "lowers provider surface trees into a terminal grid", "rejects surface documents that do not match the advertised TUI target", "aetheria.daemon.commands"] + }, + { + "path": "tools/evetui/evetui-capture-contract.mjs", + "contains": ["buildTuiCaptureRequest", "gamecult.eve.runtime_capture_request.v1", "ansi-transcript-or-json-grid", "loweringTargets", "writeCaptureRequest"] + }, + { + "path": "tools/evetui/evetui-capture-contract.test.mjs", + "contains": ["builds TUI capture request from provider advertisement", "rejects capture request when the surface does not advertise TUI", "artifacts/evetui-capture/smoke/tui-transcript.ansi"] } ], "capture": {