diff --git a/README.md b/README.md index e2700ef..e92d92f 100644 --- a/README.md +++ b/README.md @@ -154,10 +154,18 @@ payloads as `mimir.eve_media_observation.v1`. accepted state, commands, and side effects. See `docs/cultmesh-streaming-ui-framework.md` for the target architecture. +See `docs/repo-strategy.md` for the kernel/plugin/runtime/provider ownership +boundary and graduation rules. See `docs/renderer-parity.md` for current browser/iOS/Android/Fensalir/Flutter renderer parity. See `docs/surface-contract-v1.md` for the shared CultUI/CultMesh surface and command contract. +Nested CultUI surfaces are documented there as `embeddedDocuments` / +`surface.slot`; the parity fixture is +`web/fixtures/cultui-embedded-surface.json`, and the runtime matrix is in +`docs/parity-testing-harness.md`. Renderer runtimes lower or preserve the slot +directly; Rust proves the same `gamecult.eve.surface.v1` contract at the +CultMesh typed document sync layer in CultLib. See `docs/eve-dsl-reactive-bindings.md` for the first Eve DSL and reactive CultMesh binding contract. See `docs/eve-multiverse.md` for the Eve MultiVerse philosophy and missing API @@ -172,9 +180,9 @@ Start the browser reference surface runner: powershell -ExecutionPolicy Bypass -File .\scripts\start-browser-reference.ps1 ``` -Open `http://127.0.0.1:8891/`. The page can spawn: +Open `http://127.0.0.1:8891/`. The page can render local fixture and +advertisement surfaces: -- `VoidBot Live`, connected to Mimir's `/eve/deck` broker. - `Fensalir Direct2D`, a fixture surface for the planned CultMesh-to-`AquariumUiDocument` lowering. - `Sai VN Surface`, a fixture for visual-novel scenes exported as @@ -186,6 +194,9 @@ Open `http://127.0.0.1:8891/`. The page can spawn: - `Reactive DSL`, a browser-reference fixture that compiles a small `.eve` composition language into the same surface contract and binds UI controls to live CultMesh-shaped vars, collections, and derived fields. +- `Embedded Surface Slot`, a CultUI fixture proving that a parent surface can + reserve layout while a child CultMesh document is resolved and rendered as a + nested surface. ## VoidBot CEF Stream @@ -195,8 +206,9 @@ Start the Starfire relay from `E:\Projects\VoidBot`: npm run swarm:eve-cef-relay -- --width 1620 --height 2160 --scale 2 --port 8792 ``` -EveCanvas connects to `ws://192.168.1.66:8792/stream`, displays binary JPEG -frames, and returns touch events to the relay. +EveCanvas displays binary JPEG frames and returns touch events only when a +stream lowering is configured through `EVE_STREAM_URLS`. The native app no +longer guesses a Starfire relay address. ## Mimir Sensor Uplink @@ -208,10 +220,11 @@ dotnet run --project E:\Projects\Mimir\src\Mimir.EveSensorReceiver\Mimir.EveSens dotnet run --project E:\Projects\Mimir\src\Mimir.EveSensorReceiver\Mimir.EveSensorReceiver.csproj -- --port 8794 --path /eve/mic --source-id eve-mic --type audio-block ``` -EveCanvas sends binary `mimir.eve_media_observation.v1` camera observations to -`ws://192.168.1.66:8793/eve/camera` and microphone observations to -`ws://192.168.1.66:8794/eve/mic`. Periwinkle sends camera, microphone, motion, -and touch observations through `ws://192.168.1.66:8796/eve/periwinkle`. +EveCanvas sends binary `mimir.eve_media_observation.v1` camera and microphone +observations only when `EVE_CAMERA_URLS` and `EVE_MIC_URLS` are configured. +Periwinkle sends camera, microphone, motion, and touch observations only when +launched with an explicit `org.gamecult.eve.SENSOR_URI`; the apps no longer +guess receiver URLs. ## Native Mimir Dashboard @@ -221,12 +234,12 @@ Start the dashboard authority on Starfire: dotnet run --project E:\Projects\Mimir\src\Mimir.EveDashboard\Mimir.EveDashboard.csproj -- --port 8795 ``` -EveCanvas connects first to `ws://192.168.1.66:8795/eve/deck`, with -`/eve/dashboard` kept as a compatibility fallback. The Starfire broker sends -native retained `dashboard-state` snapshots. This is the current CultNet-shaped -surface document for provider id, title, scene nodes, selection, visibility, -transform, size, health, detail text, identity ids, and avatar URLs. EveCanvas -sends compact commands back: +EveCanvas connects to the Mimir dashboard WebSocket lowering for native retained +`dashboard-state` snapshots. That lowering renders the daemon-owned CultMesh +dashboard state; it is not provider discovery authority. Live provider discovery +belongs to Odin/CultMesh advertisements. Native iOS dashboard lowerings must be +configured through `EVE_DASHBOARD_URLS`; missing discovery stays visible instead +of falling back to LAN constants. EveCanvas sends compact commands back: - `select` - `move` @@ -254,11 +267,13 @@ Build the Android proof APK from Starfire: powershell -ExecutionPolicy Bypass -File .\scripts\build-android.ps1 ``` -Install to Periwinkle: +Install to Periwinkle, then launch it. If Odin/CultMesh has provided dashboard +and sensor endpoints, pass them explicitly; otherwise the app starts with those +network paths disabled instead of guessing LAN addresses. ```powershell & "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" -s bad9dd01 install -r .\artifacts\android\eve-debug.apk -& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" -s bad9dd01 shell monkey -p org.gamecult.eve -c android.intent.category.LAUNCHER 1 +& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" -s bad9dd01 shell am start -n org.gamecult.eve/.MainActivity --es org.gamecult.eve.DASHBOARD_URI "ws:///eve/deck/cultmesh" --es org.gamecult.eve.SENSOR_URI "ws:///eve/periwinkle" ``` On Xiaomi/MIUI devices, ADB install may require enabling developer setting diff --git a/docs/cultmesh-streaming-ui-framework.md b/docs/cultmesh-streaming-ui-framework.md index 9bf0b1e..239bd4a 100644 --- a/docs/cultmesh-streaming-ui-framework.md +++ b/docs/cultmesh-streaming-ui-framework.md @@ -132,18 +132,19 @@ Fensalir Direct2D: ## Current Proof -The current iOS app consumes Mimir's `/eve/deck` WebSocket broker. That broker is -already shaped like the future API: provider manifests, retained dashboard -state, provider switching, commands, and typed node metadata. The VoidBot -provider proves that Eve can render an app-specific native cockpit from a -structured mesh snapshot: CTB rail, avatar images, selected Persona/status pane, -state tree, and detail panel. +The current native app consumes Mimir's dashboard WebSocket lowering for retained +dashboard state. That lowering is shaped like the future API: retained dashboard +state, provider switching, commands, and typed node metadata. It is a renderer +path over daemon-owned state, not provider discovery authority. Live provider +discovery belongs to Odin/CultMesh advertisements. The Android proof under `android/` builds directly against the installed Android -SDK and runs on Periwinkle. It is deliberately small: display Eve's role, poll -the Mimir broker health endpoint, and show timestamped motion/touch samples. -It is a device-edge proof while the browser reference and Flutter/native shared -client are still being cut. +SDK and runs on Periwinkle. It is deliberately small: display Eve's role, render +a configured CultMesh dashboard lowering when one is provided, and capture +timestamped motion/touch/media samples. It does not bake in Mimir dashboard or +sensor URLs; missing discovery stays visible until Odin/CultMesh provides the +endpoints. It is a device-edge proof while the browser reference and +Flutter/native shared client are still being cut. The public site now reflects the same pressure. The integrated dossier frames CultMesh as typed distributed state. The Week 07 damage report records Fensalir diff --git a/docs/eve-dsl-reactive-bindings.md b/docs/eve-dsl-reactive-bindings.md index 0053bdf..23eb439 100644 --- a/docs/eve-dsl-reactive-bindings.md +++ b/docs/eve-dsl-reactive-bindings.md @@ -36,22 +36,39 @@ metric "Opacity" bind program.Field(x => x.Layers[1].Opacity) Today the lower substrate exposes reactive document changes through CultMesh / CultNet database watch streams. The field-level POCO binding handle is the -next ergonomic cut. Until that lands, Eve documents should still carry explicit -binding descriptors: +next ergonomic cut. Eve documents now carry explicit +`CultMeshStateBindingDescriptor` values on each component so renderers do not +have to infer provider state from string props: -- document schema; -- document id, key, or named handle; -- field path; -- value kind; -- access mode; -- authority label; -- optional command id for writes; -- freshness, prediction, denial, and reconciliation metadata where available. +- `targetProp`, the component prop that receives the live value; +- `pointerId`, the stable typed CultMesh state pointer; +- `sourceId`, the provider/CultMesh source, record, witness, or field id; +- `schemaId`, the state schema; +- `routeKind` and `routeDescription`, so runtimes can prefer in-process, + shared-memory, IPC, network, or WASM paths without app glue. This keeps the DSL honest. The visual language can name a field; the provider and CultMesh decide whether that field is readable, writable, predicted, accepted, denied, stale, or missing. +Commands follow the same rule. Eve command templates carry +`CultMeshOperationBindingDescriptor` values so a button or menu item points at +a typed operation id, optional request schema, label, and route hint. The DSL +may provide friendly `button` sugar, but the compiled surface should not make a +free-floating command string the canonical operation boundary or public +runtime construction path. + +When a renderer fires that command, the request carries a +`CultMeshOperationInvocationDescriptor`. That invocation preserves operation id, +request schema, preferred route, and optional idempotency through the renderer +boundary so Aetheria, Bifrost, Unity, Electron, and browser runtimes do not each +invent a local command envelope. The request payload is a +`CultMeshOperationPayload`, so renderers can ingest surface props at the edge +while command handlers read scalar fields through shared typed helpers. New +runtime code should construct requests from the invocation descriptor and +payload primitive directly; raw command strings and dictionary payloads are +serialization details, not live APIs. + Discovery of those backing documents should come from a provider advertisement when available. See [provider-advertisement-contract.md](./provider-advertisement-contract.md) for diff --git a/docs/parity-testing-harness.md b/docs/parity-testing-harness.md index 399038a..4dcb76a 100644 --- a/docs/parity-testing-harness.md +++ b/docs/parity-testing-harness.md @@ -85,27 +85,65 @@ fixture claiming to render CultUI while the retained tree no longer contains the partitions, bindings, tokens, or slider anatomy the renderer is supposed to lower. +The fixture matrix also includes `embedded-surface`, which proves that nested +CultMesh document slots survive the shared surface contract. The web reference, +Flutter parity body, Unity UI Toolkit lowerer, iOS UIKit renderer, and native +Android Kotlin dashboard renderer all need to understand +`surface.slot`/`embeddedDocuments`. Rust participates at the CultMesh document +sync layer: it must preserve the same `gamecult.eve.surface.v1` slot contract +through typed document replication even when it is not painting pixels. + +Nested surface support is a required feature for every active GUI runtime in +`tools/parity/parity-manifest.json`. Active runtimes list +`requiredFixtures: ["embedded-surface"]` and +`supportedFeatures: ["embeddedDocuments"]`; the semantic report prints both so a +runtime cannot quietly fall out of the contract. Runtime entries also use +`expectedSourceSymbols` for the renderer files that must contain the slot +lowering path, so a runtime cannot keep a green body merely because its source +file exists. The shared fixture is `web/fixtures/cultui-embedded-surface.json`, +and renderer-specific tests should load that fixture rather than hand-authoring +a local substitute. + ## Runtime Status The harness tracks every target runtime: - Web reference: active semantic and screenshot target through Chrome headless - using the provider query parameter. + using the provider query parameter. Required nested-surface evidence: + `node --test web\eve-dsl.test.mjs` plus the `embedded-surface` fixture in + `tools/parity/run-parity.mjs`. - Web responsive layout: Chrome headless emits phone, tablet, and desktop PNGs. - iOS / UIKit: screenshot target through SSH and EveCanvas' `/var/mobile/Library/EveCanvas/capture-request` service. Current iOS capture - is fixed-device until a simulator or device-resize adapter exists. + is fixed-device until a simulator or device-resize adapter exists. Required + nested-surface evidence: run `scripts/run-parity-smoke.ps1 -ProviderId + gamecult.eve.embedded-demo` against the device target. - Windows / Flutter: screenshot target through the Flutter parity golden smoke, - with phone, tablet, and desktop goldens. + with phone, tablet, and desktop goldens. Required nested-surface evidence: + `flutter test --plain-name embedded_surface_fixture_contract` plus + `scripts/capture-flutter-parity.ps1 -FixtureId + gamecult.eve.embedded-demo`. - Linux / Flutter: screenshot target through Nightwing over SSH. The smoke stages `flutter/eve_parity`, runs Flutter goldens on Nightwing, and pulls back - phone, tablet, and desktop PNGs. + phone, tablet, and desktop PNGs. Required nested-surface evidence: + `scripts/capture-linux-flutter-parity.ps1 -FixtureId + gamecult.eve.embedded-demo`. - Android / Flutter: screenshot target through the same Flutter renderer, packaged as a debug APK, installed on Periwinkle through `adb`, and captured with optional `adb shell wm size`, orientation control, and `adb exec-out screencap`; the script restores device size and rotation after each viewport. -- Android / Kotlin device edge: compatibility body for CultMesh dashboard and - sensor experiments. It is not the GUI parity target. + Required nested-surface evidence: `scripts/capture-android-flutter-parity.ps1 + -FixtureId gamecult.eve.embedded-demo`. +- Android / Kotlin device edge: lightweight native CultMesh dashboard and + sensor host. Required nested-surface evidence: + `android/app/src/main/java/org/gamecult/eve/MainActivity.kt` renders + `surface.slot` with a content description containing the embedded slot + identity, and `node tools/parity/run-parity.mjs` reports + `embeddedDocuments` support for `android-kotlin`. +- Rust / CultMesh: typed document runtime rather than a CultUI renderer. + Required nested-surface evidence: `cargo test -p cultnet-rs + rust_preserves_cultui_embedded_surface_slots_through_typed_document_sync` + in CultLib. - Fensalir Direct2D: specialized native target, adapter/capture still missing. Pending runtimes are allowed. Silent fake parity is not. diff --git a/docs/provider-advertisement-contract.md b/docs/provider-advertisement-contract.md index 0dd4305..9dbeeac 100644 --- a/docs/provider-advertisement-contract.md +++ b/docs/provider-advertisement-contract.md @@ -167,12 +167,12 @@ Transport routes are separate from service identity: ```json { "kind": "cultnet", - "address": "cultnet://10.77.0.4:3075", + "address": "cultmesh://asgard.yggdrasil.streampixels/transport/cultnet", "carries": [ "asgard.yggdrasil.streampixels/eve/tui", "asgard.yggdrasil.streampixels/eve/gui" ], - "note": "CultNet reliable UDP route for this located service." + "note": "Odin/CultMesh-discovered CultNet reliable UDP route for this located service." } ``` diff --git a/docs/renderer-parity.md b/docs/renderer-parity.md index b65afeb..c7d32bc 100644 --- a/docs/renderer-parity.md +++ b/docs/renderer-parity.md @@ -17,17 +17,27 @@ enough that Repixelizer remains itself across runtimes. The shared fixture/report path lives in [parity-testing-harness.md](./parity-testing-harness.md). That harness is the current evidence surface for semantic parity and runtime capture gaps. +The nested CultUI surface feature is tracked as fixture `embedded-surface`, +loaded from `web/fixtures/cultui-embedded-surface.json`, and must be understood +by every renderer that claims `gamecult.eve.surface.v1` GUI parity. +Runtime discovery for the feature is in `tools/parity/parity-manifest.json`: + active GUI runtimes advertise `supportedFeatures: ["embeddedDocuments"]` and +require the `embedded-surface` fixture. Native Android/Kotlin makes a narrower +active claim: it preserves and displays embedded slot identity in its dashboard +renderer while Android Flutter remains the responsive screenshot target. Rust +proves the same contract at the CultMesh typed document sync layer. ## Current State | Renderer | Status | Proof | Gap | | --- | --- | --- | --- | -| Web reference | Active reference/debug renderer | `web/` renders live VoidBot and fixture surfaces through the provider picker; compiles indentation CultUI; lowers partitions, field rows, and slider anatomy; Chrome headless capture emits phone/tablet/desktop PNGs | Needs command round-trip tests | -| Windows / Flutter | Active shared graphical smoke target | `flutter/eve_parity` loads exported `gamecult.eve.surface.v1` fixture JSON and emits phone/tablet/desktop golden PNGs through `capture-flutter-parity.ps1` | Needs native window capture and tighter text/style normalization | -| Linux / Flutter | Active shared graphical smoke target | Nightwing runs the Flutter parity goldens over SSH and returns phone/tablet/desktop PNGs | Needs native window capture and runner health checks | -| Android / Flutter | Active shared graphical smoke target | The same Flutter parity app is built as an APK, installed on Periwinkle, and captured at phone/tablet/desktop plus native physical panel orientations | Needs live provider picker and command transport beyond fixture assets | -| iOS / UIKit | Active native screenshot target | SSH capture stages selected fixture JSON, EveCanvas renders it, and emits a PNG from `/var/mobile/Library/EveCanvas/latest-screenshot.png` | Needs real scene composition for `vn.stage`, Repixelizer token fidelity, and responsive/simulator capture | -| Android / Kotlin device edge | Compatibility body | Native APK consumes CultMesh dashboard/sensor documents for edge experiments | Not the GUI CultUI parity target unless direct Android ownership earns its keep | +| Web reference | Active reference/debug renderer | `web/` renders local provider advertisements and fixture surfaces through the provider picker; compiles indentation CultUI; lowers partitions, field rows, slider anatomy, and `surface.slot`; Chrome headless capture emits phone/tablet/desktop PNGs | Needs live Odin/CultMesh provider feed and command round-trip tests | +| Windows / Flutter | Active shared graphical smoke target | `flutter/eve_parity` loads exported `gamecult.eve.surface.v1` fixture JSON, including `embedded-surface`, and emits phone/tablet/desktop golden PNGs through `capture-flutter-parity.ps1` | Needs native window capture and tighter text/style normalization | +| Linux / Flutter | Active shared graphical smoke target | Nightwing runs the Flutter parity goldens, including embedded surface slots, over SSH and returns phone/tablet/desktop PNGs | Needs native window capture and runner health checks | +| Android / Flutter | Active shared graphical smoke target | The same Flutter parity app is built as an APK, installed on Periwinkle, and captured at phone/tablet/desktop plus native physical-panel orientations | Needs live provider picker and command transport beyond fixture assets | +| iOS / UIKit | Active native screenshot target | SSH capture stages selected fixture JSON, EveCanvas renders it, and emits a PNG from `/var/mobile/Library/EveCanvas/latest-screenshot.png`; `embedded-surface` is part of the required fixture matrix | Needs real scene composition for `vn.stage`, Repixelizer token fidelity, and responsive/simulator capture | +| Android / Kotlin device edge | Active lightweight renderer | Native APK consumes CultMesh dashboard/sensor documents and preserves `surface.slot` / `embeddedDocuments` identity in the dashboard renderer | Needs automated native dashboard capture | +| Rust / CultMesh | Document-sync contract runtime | CultLib replicates the `gamecult.eve.surface.v1` embedded slot contract through typed document sync | Not a pixel renderer | | Fensalir Direct2D | Specialized native/game-runtime landing zone | Existing `AquariumUiDocument` and `DirectWriteOverlay` path | Needs adapter from Eve surface document to `AquariumUiDocument`, DirectWrite/Direct2D token lowering, and a clear reason to stay separate from Flutter for desktop UI | ## Spawned Surfaces @@ -35,8 +45,6 @@ current evidence surface for semantic parity and runtime capture gaps. The browser reference runner now exposes local advertisements through the provider picker: -- `VoidBot Live`: connects to Mimir's `/eve/deck` broker and opens - `voidbot.swarm`. - `Repixelizer`: loads `web/fixtures/repixelizer.provider-advertisement.json` and `web/fixtures/repixelizer.eve-surface.json`. - `Fensalir Direct2D`: loads `web/fixtures/fensalir-client-surface.json`, a @@ -47,9 +55,11 @@ provider picker: - `CultUI Inspector`: compiles `web/fixtures/cultui-slider-inspector.eve` and proves partition/field-row/slider-anatomy lowering in the web reference. -The remaining temporary part is the local provider list itself. The runtime app -target is the same picker fed by live `gamecult.eve.provider_advertisement.v1` -documents through CultMesh/Odin. +The remaining temporary part is the local fixture provider list itself. The +runtime app target is the same picker fed by live +`gamecult.eve.provider_advertisement.v1` documents through CultMesh/Odin; the +browser reference no longer opens live providers by dialing Mimir's deck broker +directly. Start it with: diff --git a/docs/surface-contract-v1.md b/docs/surface-contract-v1.md index 77a6f40..8e3bef9 100644 --- a/docs/surface-contract-v1.md +++ b/docs/surface-contract-v1.md @@ -79,7 +79,9 @@ Every component has: "id": "stable.local.id", "kind": "panel.dialogue", "props": {}, - "children": [] + "children": [], + "stateBindings": [], + "embeddedDocuments": [] } ``` @@ -102,6 +104,46 @@ If a renderer does not know a specialized kind, it should fall back through the kind path: `panel.dialogue` may render as `panel`; `image.sprite` may render as `image`. +`stateBindings` are explicit `CultMeshStateBindingDescriptor` values attached +to component props. They keep provider state identity out of ad-hoc renderer +stores and out of string-only prop conventions. A binding names: + +- `targetProp`: component prop receiving the live value, usually `value`. +- `pointerId`: stable typed CultMesh state pointer id. +- `sourceId`: provider/CultMesh source, record, witness, or field id. +- `schemaId`: schema of the source state. +- `routeKind`: preferred locality such as `in-process`, `shared-memory`, + `ipc`, `network`, or `wasm`. +- `routeDescription`: optional diagnostics for tools and operators. + +Renderers may still honor compatibility props such as `valueRef`, but new +CultUI/Eve runtimes should use `stateBindings` as the canonical contract and +let the CultMesh runtime resolve, watch, predict, or deny the value. Eve does +not define a parallel binding DTO; the live surface contract imports the shared +CultMesh primitive directly. + +### Embedded Documents + +`embeddedDocuments` are explicit CultMesh document slots attached to a component. +Use them when a provider wants one surface to own layout while a nested region +remains a separately synced document. Inventory panels, inspectors with live +subdocuments, tab bodies, drag/drop overlays, and remote tool panes should use +slots instead of copying child state into a parent DTO. + +Each slot names: + +- `slotId`: stable local slot identity inside the parent component. +- `documentId`: CultMesh document id to resolve and subscribe to. +- `schemaId`: expected schema, commonly `gamecult.eve.surface.v1` or a + provider-specific surface document schema. +- `presentationKind`: semantic lowering hint such as `inventory.dropdown`. +- `routeHint`: optional CultMesh locality hint for resolving the child. + +Renderers lower normal `children` first, then resolve and mount +`embeddedDocuments` through their CultMesh document resolver. A renderer that +cannot resolve a slot must preserve the slot identity in diagnostics or a +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 @@ -216,6 +258,24 @@ Standard command names: - `transform.rotate` Providers may add command names, but they must advertise them in `commands`. +Live Eve command templates carry `CultMeshOperationBindingDescriptor` values: +the operation id is the canonical command identity, `schemaId` may name the +typed request body, `label` names the visible affordance, and `routeHint` +describes the preferred invocation locality. Compatibility fields such as +`command` and `transport` may still be projected for old renderers, but they +are not the authoritative live command model and should not appear as public +runtime construction APIs. + +Renderer command requests carry `CultMeshOperationInvocationDescriptor` values. +That invocation descriptor is the canonical operation identity at click/change +time and preserves request schema, preferred route, and optional idempotency. +Renderer command requests also carry `CultMeshOperationPayload`, a shared +payload value with typed scalar readers. Legacy `command` strings and string +payload fields may be serialized while old documents migrate, but live +CultUI/Eve runtimes route from the shared CultMesh invocation descriptor and +read scalar fields through the shared payload primitive. Renderer code should +construct requests from `CultMeshOperationInvocationDescriptor` and +`CultMeshOperationPayload`, not from command strings plus raw dictionaries. ## Synchronized Style