Clarify optional nested plugin ownership
This commit is contained in:
parent
052a355d74
commit
5d58f3e414
5 changed files with 34 additions and 15 deletions
|
|
@ -710,6 +710,10 @@ Recently cut:
|
|||
Aetheria consumer smoke asserts editor ownership and the pending TUI lowering
|
||||
gap from the exported contract 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
|
||||
provider-plugin requirement availability, so `sai.vn` remains required while
|
||||
`norn.graph` and `tex.math` stay optional nested sidecar plugins.
|
||||
- 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
|
||||
|
|
|
|||
|
|
@ -188,7 +188,9 @@ plugin owners can consume requirement coverage without reconstructing the
|
|||
provider/plugin join. `availability: optional-nested` means the parent surface
|
||||
can host that independent plugin when available; it is not a parent-plugin
|
||||
dependency. Consumer smokes can assert them with
|
||||
`--expect-provider-plugin-requirement <providerId:surfaceId:pluginId:status:pluginOwnerRepo>`.
|
||||
`--expect-provider-plugin-requirement <providerId:surfaceId:pluginId:status:pluginOwnerRepo[:availability]>`.
|
||||
Plugin-owner smokes should use the optional availability field when proving that
|
||||
Sai's required VN plugin is distinct from optional nested Norn or TeX surfaces.
|
||||
|
||||
The runtime conformance pack is evidence-shaped, not fixture-shaped. Its
|
||||
`packs/runtime.json` document includes `runtimeTargets` so runtime repos can
|
||||
|
|
|
|||
|
|
@ -146,10 +146,15 @@ placeholder; it must not invent a local substitute for the child document.
|
|||
|
||||
## Embedded Knowledge Surfaces
|
||||
|
||||
Eve must be able to place rich interactive surfaces inside another surface. For
|
||||
Sai, this means the VN scene can host Norn and TeX as diegetic scene elements:
|
||||
whiteboards, handheld tablets, hologram panes, cockpit screens, chalkboards, or
|
||||
chromakey regions baked into sprite assets.
|
||||
Eve must be able to place rich interactive surfaces inside another surface.
|
||||
Nested placement is composition, not custody. A parent surface may reserve scene
|
||||
space for another plugin's surface when that plugin is available, but the
|
||||
nested plugin keeps its own ABI, capability claims, conformance pack, and
|
||||
semantic owner. For Sai, this means a VN scene can deploy with Norn and TeX as
|
||||
optional diegetic scene elements: whiteboards, handheld tablets, hologram
|
||||
panes, cockpit screens, chalkboards, or chromakey regions baked into sprite
|
||||
assets. Sai owns the VN stage. Norn owns graph semantics. TeX owns math and
|
||||
typesetting semantics.
|
||||
|
||||
### `embed.norn`
|
||||
|
||||
|
|
@ -352,12 +357,16 @@ Sai requires Eve/CultUI to carry:
|
|||
- speaker, avatar, dialogue, and choices;
|
||||
- sprite layers with position, scale, and offsets;
|
||||
- external provider-owned cards/fragments;
|
||||
- embedded Norn graph/map surfaces with clickable node targets;
|
||||
- embedded TeX surfaces for equations, whitepapers, ledgers, and proofs;
|
||||
- optional embedded Norn graph/map surfaces with clickable node targets when
|
||||
`norn.graph` is advertised and available;
|
||||
- optional embedded TeX surfaces for equations, whitepapers, ledgers, and proofs
|
||||
when `tex.math` is advertised and available;
|
||||
- diegetic placement with perspective, skew, keystone, chromakey, and occlusion
|
||||
metadata;
|
||||
- synchronized style tokens;
|
||||
- story commands for continue, choice, jump, and style patch.
|
||||
|
||||
Those requirements are now inside the contract, not Sai-specific browser
|
||||
behavior.
|
||||
Those requirements are now inside the Eve surface and plugin-advertisement
|
||||
contracts, not Sai-specific browser behavior. Optional nested Norn or TeX gaps
|
||||
degrade the nested surface; they do not move graph, math, or renderer semantics
|
||||
into Sai.
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ node $consumerScript $consumerExport `
|
|||
--expect-plugin-abi-operation-coverage sai.vn:describe:contracted:Sai `
|
||||
--expect-plugin-abi-operation-coverage sai.vn:lower:contracted:Sai `
|
||||
--expect-plugin-abi-operation-coverage sai.vn:apply:contracted:Sai `
|
||||
--expect-provider-plugin-requirement gamecult.home.vn:sai.visual_novel.surface:sai.vn:satisfied:Sai `
|
||||
--expect-provider-plugin-requirement gamecult.home.vn:sai.visual_novel.surface:sai.vn:satisfied:Sai:required `
|
||||
--expect-plugin-operation norn.graph:describe `
|
||||
--expect-plugin-operation norn.graph:validate `
|
||||
--expect-plugin-operation norn.graph:project `
|
||||
|
|
@ -58,8 +58,8 @@ node $consumerScript $consumerExport `
|
|||
--expect-plugin-abi-operation-coverage norn.graph:describe:contracted:Norn `
|
||||
--expect-plugin-abi-operation-coverage norn.graph:lower:contracted:Norn `
|
||||
--expect-plugin-abi-operation-coverage norn.graph:apply:contracted:Norn `
|
||||
--expect-provider-plugin-requirement gamecult.home.vn:sai.visual_novel.surface:norn.graph:optional-satisfied:Norn `
|
||||
--expect-provider-plugin-requirement gamecult.home.vn:sai.visual_novel.surface:tex.math:optional-satisfied:EvePlugins `
|
||||
--expect-provider-plugin-requirement gamecult.home.vn:sai.visual_novel.surface:norn.graph:optional-satisfied:Norn:optional-nested `
|
||||
--expect-provider-plugin-requirement gamecult.home.vn:sai.visual_novel.surface:tex.math:optional-satisfied:EvePlugins:optional-nested `
|
||||
--expect-plugin-capability sai.vn:vn.stage `
|
||||
--expect-plugin-capability sai.vn:story.choose `
|
||||
--expect-plugin-capability sai.vn:story.continue `
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ if (!exportDirectory) {
|
|||
" --expect-provider-surface-kind <providerId:surfaceId:surfaceKind>",
|
||||
" --expect-provider-surface-field <providerId:surfaceId:field.path:value>",
|
||||
" --expect-interactive-world-surface <providerId:surfaceId:targetId:ownerRepo>",
|
||||
" --expect-provider-plugin-requirement <providerId:surfaceId:pluginId:status:pluginOwnerRepo>",
|
||||
" --expect-provider-plugin-requirement <providerId:surfaceId:pluginId:status:pluginOwnerRepo[:availability]>",
|
||||
" --expect-provider-command <providerId:command>",
|
||||
" --expect-provider-receipt-state <providerId:state>",
|
||||
" --expect-provider-handoff <providerId>",
|
||||
|
|
@ -464,6 +464,9 @@ function validateIndex(index, directory, expectations, errors) {
|
|||
if (requirement.pluginOwnerRepo !== expectation.pluginOwnerRepo) {
|
||||
errors.push(`providerPluginRequirementCoverage:${expectation.providerId}:${expectation.surfaceId}:${expectation.pluginId}:pluginOwnerRepo:expected ${expectation.pluginOwnerRepo} got ${requirement.pluginOwnerRepo || ""}`);
|
||||
}
|
||||
if (expectation.availability && requirement.availability !== expectation.availability) {
|
||||
errors.push(`providerPluginRequirementCoverage:${expectation.providerId}:${expectation.surfaceId}:${expectation.pluginId}:availability:expected ${expectation.availability} got ${requirement.availability || ""}`);
|
||||
}
|
||||
}
|
||||
for (const expectation of expectations.providerCommands) {
|
||||
const provider = providers.find(candidate => candidate.providerId === expectation.providerId);
|
||||
|
|
@ -1406,8 +1409,8 @@ function parseInteractiveWorldSurfaceExpectation(value) {
|
|||
|
||||
function parseProviderPluginRequirementExpectation(value) {
|
||||
const parts = value.split(":");
|
||||
if (parts.length !== 5 || parts.some(part => !part)) {
|
||||
console.error(`Expected provider plugin requirement in <providerId:surfaceId:pluginId:status:pluginOwnerRepo> form, got: ${value}`);
|
||||
if (![5, 6].includes(parts.length) || parts.some(part => !part)) {
|
||||
console.error(`Expected provider plugin requirement in <providerId:surfaceId:pluginId:status:pluginOwnerRepo[:availability]> form, got: ${value}`);
|
||||
process.exit(2);
|
||||
}
|
||||
return {
|
||||
|
|
@ -1416,6 +1419,7 @@ function parseProviderPluginRequirementExpectation(value) {
|
|||
pluginId: parts[2],
|
||||
status: parts[3],
|
||||
pluginOwnerRepo: parts[4],
|
||||
availability: parts[5] || "",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue