Carry plugin availability through Electron and TUI

This commit is contained in:
Meta Vens 2026-07-09 16:24:51 +01:00
commit e74f52ab0d
6 changed files with 20 additions and 2 deletions

View file

@ -969,6 +969,11 @@ Recently cut:
fallback catalog only advertises the Sai provider surface; independent Norn
and TeX availability is discovered through that provider's plugin
requirements and the separate plugin advertisements.
- Electron shell and compact TUI projection artifacts now carry the same
availability split as Unity projection artifacts: `sai.vn` projection is
required for the VN surface, while `norn.graph` and `tex.math` are
`optional-nested` independent sidecar plugin projections. This keeps
runtime projection support from becoming an implied Sai dependency story.
- Sai, Norn, and TeX now have plugin ABI fixtures for describe, validate,
project, lower, measure, and apply behavior. The parity harness validates
those fixtures against plugin manifests, so Eve proves the ABI shape without

View file

@ -170,6 +170,7 @@ function buildPluginProjection(componentKind, component) {
capabilities: ["vn.stage", "story.choose", "story.continue", "story.jump"],
documentId: firstString(component.props?.storyId, component.id),
semanticOwner: "Sai",
availability: "required",
};
}
@ -182,6 +183,7 @@ function buildPluginProjection(componentKind, component) {
capabilities: ["embed.norn"],
documentId: firstString(component.props?.sourceUri, component.props?.documentId, component.id),
semanticOwner: "Norn",
availability: "optional-nested",
};
}
@ -194,6 +196,7 @@ function buildPluginProjection(componentKind, component) {
capabilities: ["embed.tex", "tex.inline", "tex.block"],
documentId: firstString(component.props?.sourceUri, component.props?.source, component.id),
semanticOwner: "EvePlugins",
availability: "optional-nested",
};
}

View file

@ -89,6 +89,7 @@ test("lowers Sai, Norn, and TeX sidecar plugin shells without owning semantics",
assert.equal(projection.root.shellElementKind, "sai-vn-stage-shell");
assert.equal(projection.root.pluginProjection.pluginId, "sai.vn");
assert.equal(projection.root.pluginProjection.semanticOwner, "Sai");
assert.equal(projection.root.pluginProjection.availability, "required");
assert.equal(projection.root.pluginProjection.commandBoundary, "sidecar-advertised-plugin-abi");
assert.deepEqual(projection.root.pluginProjection.capabilities, [
"vn.stage",
@ -102,6 +103,7 @@ test("lowers Sai, Norn, and TeX sidecar plugin shells without owning semantics",
assert.equal(norn.pluginProjection.pluginId, "norn.graph");
assert.equal(norn.pluginProjection.projectionKind, "norn-graph-electron-overlay-shell");
assert.equal(norn.pluginProjection.semanticOwner, "Norn");
assert.equal(norn.pluginProjection.availability, "optional-nested");
assert.deepEqual(norn.pluginProjection.capabilities, ["embed.norn"]);
const tex = findNode(projection.root, "sai.tex.log-power");
@ -109,6 +111,7 @@ test("lowers Sai, Norn, and TeX sidecar plugin shells without owning semantics",
assert.equal(tex.pluginProjection.pluginId, "tex.math");
assert.equal(tex.pluginProjection.projectionKind, "tex-math-electron-block-source-shell");
assert.equal(tex.pluginProjection.semanticOwner, "EvePlugins");
assert.equal(tex.pluginProjection.availability, "optional-nested");
assert.equal(tex.pluginProjection.documentId, "\\\\mathrm{votes}(p)=1+\\\\lfloor\\\\log_b(1+p)\\\\rfloor");
assert.deepEqual(tex.pluginProjection.capabilities, ["embed.tex", "tex.inline", "tex.block"]);
});

View file

@ -235,6 +235,7 @@ function buildPluginProjection(componentKind, component) {
capabilities: ["vn.stage", "story.choose", "story.continue", "story.jump"],
documentId: firstString(props.storyId, component.id),
semanticOwner: "Sai",
availability: "required",
fallbackKind: "terminal-summary",
};
}
@ -248,6 +249,7 @@ function buildPluginProjection(componentKind, component) {
capabilities: ["embed.norn"],
documentId: firstString(props.sourceUri, props.documentId, component.id),
semanticOwner: "Norn",
availability: "optional-nested",
fallbackKind: "terminal-outline",
};
}
@ -261,6 +263,7 @@ function buildPluginProjection(componentKind, component) {
capabilities: ["embed.tex", "tex.inline", "tex.block"],
documentId: firstString(props.sourceUri, props.source, component.id),
semanticOwner: "EvePlugins",
availability: "optional-nested",
fallbackKind: "source-text",
};
}

View file

@ -86,6 +86,7 @@ test("lowers provider surface trees into a terminal grid", () => {
capabilities: ["embed.norn"],
documentId: "aetheria.daemon.game.norn",
semanticOwner: "Norn",
availability: "optional-nested",
fallbackKind: "terminal-outline",
},
]);
@ -123,6 +124,7 @@ test("lowers Sai, Norn, and TeX plugin surfaces into compact terminal fallbacks"
const byPlugin = new Map(grid.pluginProjections.map(projection => [projection.pluginId, projection]));
assert.equal(byPlugin.get("sai.vn").semanticOwner, "Sai");
assert.equal(byPlugin.get("sai.vn").availability, "required");
assert.equal(byPlugin.get("sai.vn").projectionKind, "sai-vn-terminal-stage-summary");
assert.deepEqual(byPlugin.get("sai.vn").capabilities, [
"vn.stage",
@ -131,8 +133,10 @@ test("lowers Sai, Norn, and TeX plugin surfaces into compact terminal fallbacks"
"story.jump",
]);
assert.equal(byPlugin.get("norn.graph").semanticOwner, "Norn");
assert.equal(byPlugin.get("norn.graph").availability, "optional-nested");
assert.equal(byPlugin.get("norn.graph").fallbackKind, "terminal-outline");
assert.equal(byPlugin.get("tex.math").semanticOwner, "EvePlugins");
assert.equal(byPlugin.get("tex.math").availability, "optional-nested");
assert.equal(byPlugin.get("tex.math").projectionKind, "tex-math-terminal-block-source");
assert.equal(byPlugin.get("tex.math").fallbackKind, "source-text");
assert.equal(byPlugin.get("tex.math").documentId, "\\\\mathrm{votes}(p)=1+\\\\lfloor\\\\log_b(1+p)\\\\rfloor");

View file

@ -800,7 +800,7 @@
},
{
"path": "runtimes/incubating/eve-electron/test/eve-electron-shell.test.mjs",
"contains": ["selects the active advertised provider surface", "lowers provider surface trees into an Electron shell projection", "lowers Sai, Norn, and TeX sidecar plugin shells without owning semantics", "embeddedDocuments", "norn.map", "sai-vn-stage-shell", "norn-graph-shell", "tex-math-shell", "rejects surface documents that do not match the advertised target", "command intents carry provider-advertised boundaries", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
"contains": ["selects the active advertised provider surface", "lowers provider surface trees into an Electron shell projection", "lowers Sai, Norn, and TeX sidecar plugin shells without owning semantics", "embeddedDocuments", "norn.map", "sai-vn-stage-shell", "norn-graph-shell", "tex-math-shell", "optional-nested", "rejects surface documents that do not match the advertised target", "command intents carry provider-advertised boundaries", "aetheria.daemon.commands", "aetheria.eve_command_acceptance_status.v1"]
},
{
"path": "tools/eveelectron/eveelectron-capture-contract.mjs",
@ -917,7 +917,7 @@
},
{
"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", "lowers Sai, Norn, and TeX plugin surfaces into compact terminal fallbacks", "embeddedDocumentSlots", "pluginProjections", "norn.map", "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"]
"contains": ["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", "embeddedDocumentSlots", "pluginProjections", "optional-nested", "norn.map", "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"]
},
{
"path": "tools/evetui/evetui-capture-contract.mjs",