From 29515102c097e0c9e7cde0299da4a2f9de84366b Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 10 Jul 2026 07:33:20 +0100 Subject: [PATCH] Graduate Sai plugin authority to owner repo --- docs/eve-migration-roadmap.md | 11 ++- .../incubating/sai-vn.plugin-abi-fixture.json | 89 ----------------- .../sai-vn.plugin-advertisement.json | 45 --------- plugins/incubating/sai-vn.plugin-handoff.json | 53 ---------- plugins/incubating/sai-vn.plugin.json | 98 ------------------- scripts/run-plugin-handoff-smoke.ps1 | 1 - ...lugin-owner-conformance-consumer-smoke.ps1 | 15 +-- tools/parity/parity-manifest.json | 30 +++--- web/fixtures/sai-vn-surface.conformance.json | 6 +- 9 files changed, 31 insertions(+), 317 deletions(-) delete mode 100644 plugins/incubating/sai-vn.plugin-abi-fixture.json delete mode 100644 plugins/incubating/sai-vn.plugin-advertisement.json delete mode 100644 plugins/incubating/sai-vn.plugin-handoff.json delete mode 100644 plugins/incubating/sai-vn.plugin.json diff --git a/docs/eve-migration-roadmap.md b/docs/eve-migration-roadmap.md index 95152eb..9961785 100644 --- a/docs/eve-migration-roadmap.md +++ b/docs/eve-migration-roadmap.md @@ -287,11 +287,18 @@ Exit criteria: 1. Graduate the generic Electron host/preload contract into EveElectron so Aetheria retains only daemon lifecycle and provider transport configuration. -2. Build Sai's owner-side playback daemon and live sidecar witness without - absorbing Norn or TeX semantics into the Sai process. Recently cut: +- Sai now owns a live runtime-independent Ink playback sidecar. One retained + `stdio-ndjson` process opens a compiled story, applies a branch choice, + projects the resulting `gamecult.eve.surface.v1`, and jumps to another knot. + Its owner pack declares Norn and TeX only as optional nested plugins; the Sai + process imports neither implementation. Eve parity consumes Sai's manifest, + advertisement, ABI fixture, and executable from `../Sai`, and the obsolete + incubating copies and handoff document have been deleted from Eve. The Sai + and Norn witnesses both survive conformance export and consumer validation. + - CultLib now owns `CultMeshSnapshotSession`, a retained endpoint connection for ordered bulk snapshot transfer. RUDP ACK packets are sequence-neutral, fragmented data is acknowledged as it arrives, and sequenced control packets diff --git a/plugins/incubating/sai-vn.plugin-abi-fixture.json b/plugins/incubating/sai-vn.plugin-abi-fixture.json deleted file mode 100644 index 7b8e5b3..0000000 --- a/plugins/incubating/sai-vn.plugin-abi-fixture.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "schema": "gamecult.eve.plugin_abi_fixture.v1", - "fixtureId": "sai-vn-plugin-abi", - "pluginId": "sai.vn", - "ownerRepo": "Sai", - "contract": "gamecult.eve.plugin_abi.v1", - "requestSchema": "gamecult.eve.plugin_abi.request.v1", - "responseSchema": "gamecult.eve.plugin_abi.response.v1", - "sourceFixture": "sai-vn", - "operations": [ - { - "operation": "describe", - "input": { - "manifest": "plugins/incubating/sai-vn.plugin.json", - "advertisement": "plugins/incubating/sai-vn.plugin-advertisement.json" - }, - "expect": { - "pluginId": "sai.vn", - "componentKinds": ["vn.stage", "panel.dialogue", "text.dialogue", "rail.actions"], - "commands": ["story.continue", "story.choose", "story.jump"], - "capabilities": ["vn.stage", "story.choose", "story.continue", "story.jump"] - } - }, - { - "operation": "validate", - "input": { - "surface": "web/fixtures/sai-vn-surface.json", - "componentKinds": ["vn.stage", "panel.dialogue", "text.dialogue", "rail.actions"] - }, - "expect": { - "acceptedComponentKinds": ["vn.stage", "panel.dialogue", "text.dialogue", "rail.actions"], - "rejectedComponentKinds": ["combat.timeline"], - "requiredCapabilities": ["vn.stage", "story.choose", "story.continue", "story.jump"] - } - }, - { - "operation": "project", - "input": { - "surface": "web/fixtures/sai-vn-surface.json", - "rootKind": "vn.stage" - }, - "expect": { - "projectionKind": "semantic-surface", - "ownedComponentKinds": ["vn.stage", "panel.dialogue", "text.dialogue", "rail.actions"], - "delegatedPlugins": ["norn.graph", "tex.math"] - } - }, - { - "operation": "lower", - "input": { - "projection": "semantic-surface", - "targetRuntimes": ["web", "unity-uitoolkit"], - "componentKinds": ["vn.stage", "panel.dialogue", "text.dialogue", "rail.actions"] - }, - "expect": { - "loweringKind": "runtime-neutral-stage-parts", - "preservedComponentKinds": ["vn.stage", "panel.dialogue", "text.dialogue", "rail.actions"], - "delegatedPlugins": ["norn.graph", "tex.math"], - "commandEnvelope": "gamecult.eve.command_invocation.v1" - } - }, - { - "operation": "measure", - "input": { - "projection": "semantic-surface", - "placementKinds": ["overlay", "keystone", "sprite-chromakey"] - }, - "expect": { - "measurementKind": "scene-placement-hints", - "measurementOutputs": ["preferredBounds", "safeTextRegion", "embeddedSurfaceSlots"], - "preservesProviderAuthority": true - } - }, - { - "operation": "apply", - "input": { - "commands": ["story.continue", "story.choose", "story.jump"] - }, - "expect": { - "commandEffects": { - "story.continue": "advance-story", - "story.choose": "choose-branch", - "story.jump": "jump-to-knot" - }, - "receiptSchema": "gamecult.eve.command_receipt.v1" - } - } - ] -} diff --git a/plugins/incubating/sai-vn.plugin-advertisement.json b/plugins/incubating/sai-vn.plugin-advertisement.json deleted file mode 100644 index c364189..0000000 --- a/plugins/incubating/sai-vn.plugin-advertisement.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema": "gamecult.eve.plugin_advertisement.v1", - "pluginId": "sai.vn", - "ownerService": "sai", - "version": "0.1.0-incubating", - "manifestAddress": "file://plugins/incubating/sai-vn.plugin.json", - "runtime": { - "invocationModel": "executable-sidecar", - "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["cultmesh", "stdio"], - "authority": [ - "renderer-independent", - "no-provider-state-mutation", - "provider-accepts-or-denies-commands" - ], - "sidecar": { - "processKind": "long-running-daemon", - "protocol": "cultmesh-rpc-with-stdio-dev-transport", - "requestSchema": "gamecult.eve.plugin_abi.request.v1", - "responseSchema": "gamecult.eve.plugin_abi.response.v1", - "operations": ["describe", "validate", "project", "lower", "measure", "apply"], - "commandEnvelope": "gamecult.eve.command_invocation.v1", - "receiptSchema": "gamecult.eve.command_receipt.v1", - "stateAuthority": "proposes-plugin-state-only-provider-accepts" - } - }, - "schemas": [ - "sai.vn.story_session.v1", - "sai.vn.visual_manifest.v1" - ], - "componentKinds": [ - "vn.stage", - "panel.dialogue", - "text.dialogue", - "rail.actions" - ], - "commands": [ - "story.continue", - "story.choose", - "story.jump" - ], - "fixtures": [ - "sai-vn" - ] -} diff --git a/plugins/incubating/sai-vn.plugin-handoff.json b/plugins/incubating/sai-vn.plugin-handoff.json deleted file mode 100644 index 57e2999..0000000 --- a/plugins/incubating/sai-vn.plugin-handoff.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema": "gamecult.eve.plugin_handoff.v1", - "pluginId": "sai.vn", - "ownerRepo": "Sai", - "currentHostRepo": "Eve", - "splitTarget": "Sai/sai-vn-plugin", - "manifestPath": "plugins/incubating/sai-vn.plugin.json", - "advertisementPath": "plugins/incubating/sai-vn.plugin-advertisement.json", - "abiFixturePath": "plugins/incubating/sai-vn.plugin-abi-fixture.json", - "authorityBoundary": "Sai owns VN/Ink story semantics, visual manifest semantics, story command interpretation, and plugin ABI behavior. Eve owns only plugin manifest, advertisement, ABI, provider requirement, and conformance export contracts.", - "moveSets": [ - { - "id": "plugin-manifest", - "destinationOwner": "Sai", - "currentPaths": [ - "plugins/incubating/sai-vn.plugin.json", - "plugins/incubating/sai-vn.plugin-advertisement.json" - ], - "replacementProof": "Sai publishes sai.vn plugin manifest and advertisement from the Sai repo or sidecar daemon." - }, - { - "id": "abi-conformance", - "destinationOwner": "Sai", - "currentPaths": [ - "plugins/incubating/sai-vn.plugin-abi-fixture.json", - "web/fixtures/sai-vn-surface.json", - "web/fixtures/sai-vn-surface.conformance.json" - ], - "replacementProof": "Sai owns VN/Ink ABI describe, validate, project, lower, measure, and apply conformance cases." - } - ], - "contractInputs": [ - "gamecult.eve.plugin.v1", - "gamecult.eve.plugin_advertisement.v1", - "gamecult.eve.plugin_abi.v1", - "gamecult.eve.plugin_abi.request.v1", - "gamecult.eve.plugin_abi.response.v1", - "gamecult.eve.plugin_abi_fixture.v1", - "gamecult.eve.conformance_export.v1" - ], - "forbiddenImports": [ - "Aetheria provider state", - "renderer-native projection internals", - "runtime plugin projection internals", - "provider command acceptance or receipt authority" - ], - "requiredExternalProofs": [ - "Sai publishes the sai.vn sidecar ABI without depending on Eve source layout.", - "Sai owns VN/Ink story state, visual manifest, and story command fixtures.", - "Providers consume sai.vn through plugin advertisements and ABI operations.", - "Runtimes declare sai.vn projection support through runtime capability manifests." - ] -} diff --git a/plugins/incubating/sai-vn.plugin.json b/plugins/incubating/sai-vn.plugin.json deleted file mode 100644 index 38841ee..0000000 --- a/plugins/incubating/sai-vn.plugin.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "schema": "gamecult.eve.plugin.v1", - "pluginId": "sai.vn", - "title": "Sai Visual Novel", - "owner": "Sai", - "incubation": { - "ownerRepo": "Sai", - "currentHostRepo": "Eve", - "splitTarget": "Sai/sai-vn-plugin", - "graduationTrigger": "Split when VN/Ink semantics, story command fixtures, and ABI describe/validate/project/lower/measure/apply cases are stable." - }, - "componentKinds": [ - "vn.stage", - "panel.dialogue", - "text.dialogue", - "rail.actions" - ], - "commands": [ - { - "command": "story.continue", - "schema": "sai.vn.story_command.v1", - "effect": "advance-story" - }, - { - "command": "story.choose", - "schema": "sai.vn.story_command.v1", - "effect": "choose-branch" - }, - { - "command": "story.jump", - "schema": "sai.vn.story_command.v1", - "effect": "jump-to-knot" - } - ], - "runtime": { - "invocationModel": "executable-sidecar", - "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["cultmesh", "stdio"], - "authority": [ - "renderer-independent", - "no-provider-state-mutation", - "provider-accepts-or-denies-commands" - ], - "sidecar": { - "processKind": "long-running-daemon", - "protocol": "cultmesh-rpc-with-stdio-dev-transport", - "requestSchema": "gamecult.eve.plugin_abi.request.v1", - "responseSchema": "gamecult.eve.plugin_abi.response.v1", - "operations": ["describe", "validate", "project", "lower", "measure", "apply"], - "commandEnvelope": "gamecult.eve.command_invocation.v1", - "receiptSchema": "gamecult.eve.command_receipt.v1", - "stateAuthority": "proposes-plugin-state-only-provider-accepts" - } - }, - "stateSchemas": [ - "sai.vn.story_session.v1", - "sai.vn.visual_manifest.v1" - ], - "fixtures": [ - { - "fixtureId": "sai-vn", - "schema": "gamecult.eve.surface.v1", - "path": "web/fixtures/sai-vn-surface.json" - } - ], - "abiFixtures": [ - "plugins/incubating/sai-vn.plugin-abi-fixture.json" - ], - "capabilities": { - "requires": [ - "vn.stage", - "story.choose", - "story.continue", - "story.jump" - ], - "optionalPlugins": [ - { - "pluginId": "norn.graph", - "relationship": "optional-nested-composition", - "authority": "Sai can place an embed.norn surface when norn.graph is available; Norn remains the independent graph plugin owner and Sai must not import graph internals.", - "capabilities": [ - "embed.norn", - "graph.node.activate" - ] - }, - { - "pluginId": "tex.math", - "relationship": "optional-nested-composition", - "authority": "Sai can place an embed.tex surface when tex.math is available; TeX remains the independent math plugin owner and Sai must not import TeX internals.", - "capabilities": [ - "embed.tex", - "tex.inline", - "tex.block" - ] - } - ] - } -} diff --git a/scripts/run-plugin-handoff-smoke.ps1 b/scripts/run-plugin-handoff-smoke.ps1 index 7639aa4..b3f9929 100644 --- a/scripts/run-plugin-handoff-smoke.ps1 +++ b/scripts/run-plugin-handoff-smoke.ps1 @@ -1,6 +1,5 @@ param( [string[]] $HandoffPaths = @( - "plugins\incubating\sai-vn.plugin-handoff.json", "plugins\incubating\tex-math.plugin-handoff.json" ) ) diff --git a/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 b/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 index 26d5afe..bdec510 100644 --- a/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 +++ b/scripts/run-plugin-owner-conformance-consumer-smoke.ps1 @@ -44,20 +44,16 @@ node $consumerScript $consumerExport ` --expect-plugin sai.vn ` --expect-plugin norn.graph ` --expect-plugin tex.math ` - --expect-plugin-handoff sai.vn ` --expect-plugin-handoff tex.math ` - --expect-plugin-handoff-move sai.vn:plugin-manifest:current:exists:sai-vn.plugin.json ` - --expect-plugin-handoff-move sai.vn:abi-conformance:current:exists:sai-vn.plugin-abi-fixture.json ` --expect-plugin-handoff-move tex.math:plugin-manifest:current:exists:tex-math.plugin.json ` --expect-plugin-handoff-move tex.math:abi-conformance:current:exists:tex-math.plugin-abi-fixture.json ` --expect-plugin-operation sai.vn:describe ` --expect-plugin-operation sai.vn:validate ` --expect-plugin-operation sai.vn:project ` - --expect-plugin-operation sai.vn:lower ` - --expect-plugin-operation sai.vn:measure ` --expect-plugin-operation sai.vn:apply ` + --expect-plugin-operation sai.vn:open ` + --expect-plugin-operation sai.vn:jump ` --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:required ` --expect-plugin-operation norn.graph:describe ` @@ -79,14 +75,13 @@ node $consumerScript $consumerExport ` --expect-plugin-capability tex.math:tex.inline ` --expect-plugin-capability tex.math:tex.block ` --expect-plugin-runtime sai.vn:executable-sidecar ` - --expect-plugin-runtime-transport sai.vn:cultmesh ` + --expect-plugin-runtime-transport sai.vn:stdio ` --expect-plugin-runtime-authority sai.vn:no-provider-state-mutation ` --expect-plugin-runtime-field sai.vn:sidecar.processKind:long-running-daemon ` - --expect-plugin-runtime-field sai.vn:sidecar.protocol:cultmesh-rpc-with-stdio-dev-transport ` + --expect-plugin-runtime-field sai.vn:sidecar.protocol:stdio-ndjson ` --expect-plugin-runtime-field sai.vn:sidecar.requestSchema:gamecult.eve.plugin_abi.request.v1 ` --expect-plugin-runtime-field sai.vn:sidecar.responseSchema:gamecult.eve.plugin_abi.response.v1 ` - --expect-plugin-runtime-field sai.vn:sidecar.stateAuthority:proposes-plugin-state-only-provider-accepts ` - --expect-plugin-abi-field sai.vn:lower:expect.commandEnvelope:gamecult.eve.command_invocation.v1 ` + --expect-plugin-runtime-field sai.vn:sidecar.stateAuthority:sai-sidecar-owns-story-session-provider-owns-command-acceptance ` --expect-plugin-abi-field sai.vn:apply:expect.receiptSchema:gamecult.eve.command_receipt.v1 ` --expect-plugin-runtime norn.graph:executable-sidecar ` --expect-plugin-runtime-transport norn.graph:stdio ` diff --git a/tools/parity/parity-manifest.json b/tools/parity/parity-manifest.json index 7111a7a..5650449 100644 --- a/tools/parity/parity-manifest.json +++ b/tools/parity/parity-manifest.json @@ -432,41 +432,39 @@ { "pluginId": "sai.vn", "title": "Sai Visual Novel", - "kind": "external-owner-planned", + "kind": "external-owner", "ownerRepo": "Sai", - "repoRole": "plugin-incubating", - "splitTarget": "Sai/sai-vn-plugin", - "graduationTrigger": "Split when VN/Ink semantics, story command fixtures, and ABI project/apply/validate cases are stable.", + "repoRole": "plugin-owner", + "splitTarget": "Sai", + "graduationTrigger": "Graduated: Sai owns retained Ink playback, fixtures, ABI sidecar, and release lifecycle.", "capabilities": ["vn.stage", "story.choose", "story.continue", "story.jump"], "optionalPlugins": ["norn.graph", "tex.math"], "expectedRuntime": { "invocationModel": "executable-sidecar", "contract": "gamecult.eve.plugin_abi.v1", - "transports": ["cultmesh", "stdio"], + "transports": ["stdio"], "authority": ["renderer-independent", "no-provider-state-mutation", "provider-accepts-or-denies-commands"], "sidecar": { "processKind": "long-running-daemon", - "protocol": "cultmesh-rpc-with-stdio-dev-transport", + "protocol": "stdio-ndjson", "requestSchema": "gamecult.eve.plugin_abi.request.v1", "responseSchema": "gamecult.eve.plugin_abi.response.v1", "commandEnvelope": "gamecult.eve.command_invocation.v1", "receiptSchema": "gamecult.eve.command_receipt.v1", - "stateAuthority": "proposes-plugin-state-only-provider-accepts" + "stateAuthority": "sai-sidecar-owns-story-session-provider-owns-command-acceptance" } }, "requiredFixtures": ["sai-vn"], "schemaPath": "schemas/gamecult.eve.plugin.v1.schema.json", - "manifestPath": "plugins/incubating/sai-vn.plugin.json", - "abiFixturePath": "plugins/incubating/sai-vn.plugin-abi-fixture.json", - "handoffPath": "plugins/incubating/sai-vn.plugin-handoff.json", + "manifestPath": "../Sai/plugins/sai-vn.plugin.json", + "abiFixturePath": "../Sai/plugins/sai-vn.plugin-abi-fixture.json", "advertisementSchemaPath": "schemas/gamecult.eve.plugin_advertisement.v1.schema.json", - "advertisementPath": "plugins/incubating/sai-vn.plugin-advertisement.json", + "advertisementPath": "../Sai/plugins/sai-vn.plugin-advertisement.json", "expectedPaths": [ - "plugins/incubating/sai-vn.plugin.json", - "plugins/incubating/sai-vn.plugin-abi-fixture.json", - "plugins/incubating/sai-vn.plugin-advertisement.json", - "plugins/incubating/sai-vn.plugin-handoff.json", - "scripts/run-plugin-handoff-smoke.ps1" + "../Sai/plugins/sai-vn.plugin.json", + "../Sai/plugins/sai-vn.plugin-abi-fixture.json", + "../Sai/plugins/sai-vn.plugin-advertisement.json", + "../Sai/src/eve-sidecar.cjs" ] }, { diff --git a/web/fixtures/sai-vn-surface.conformance.json b/web/fixtures/sai-vn-surface.conformance.json index 78b768f..684a2a1 100644 --- a/web/fixtures/sai-vn-surface.conformance.json +++ b/web/fixtures/sai-vn-surface.conformance.json @@ -8,8 +8,8 @@ "transport": "local-json", "path": "web/fixtures/sai-vn-surface.json" }, - "purpose": "Proves Sai visual-novel semantics and optional nested placement of independently-owned Norn and TeX plugin surfaces before the plugins graduate.", - "exitCriteria": "Move to Sai when VN/Ink story state, story commands, projection fixtures, and plugin ABI cases stabilize.", + "purpose": "Proves a Sai-owned visual-novel plugin surface can compose independently-owned Norn and TeX nested surfaces.", + "exitCriteria": "Provider scenarios remain in Eve only as contract fixtures; Sai owns VN/Ink story state, commands, projection, and plugin ABI cases.", "asserts": [ "vn.stage component", "embed.norn component", @@ -25,5 +25,5 @@ "norn.graph", "tex.math" ], - "splitTarget": "Sai/sai-vn-plugin" + "splitTarget": "Sai" }