Initial Brokkr scaffold
This commit is contained in:
commit
16adc98447
16 changed files with 675 additions and 0 deletions
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
target/
|
||||||
|
.brokkr/
|
||||||
|
.brokkr-smoke/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
Library/
|
||||||
|
Temp/
|
||||||
|
Obj/
|
||||||
|
Build/
|
||||||
|
Builds/
|
||||||
|
Logs/
|
||||||
|
UserSettings/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
114
Cargo.lock
generated
Normal file
114
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.102"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "brokkr-daemon"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.150"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.117"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = [
|
||||||
|
"brokkr-daemon"
|
||||||
|
]
|
||||||
|
|
||||||
44
README.md
Normal file
44
README.md
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Brokkr
|
||||||
|
|
||||||
|
Brokkr is the GameCult creative-tool broker daemon: a CultMesh service that lets
|
||||||
|
Unity, Blender, and future editor runtimes expose their live authoring surfaces
|
||||||
|
to the Verse without pretending those runtimes are the same machine.
|
||||||
|
|
||||||
|
The name earns its keep twice. Brokkr is the dwarf at the forge bellows in the
|
||||||
|
Eddic treasure contest, holding the work steady while the artifact takes shape.
|
||||||
|
Brokkr is also the broker: the daemon that routes typed editor observations,
|
||||||
|
capabilities, commands, and Eve/CultUI surfaces between tool runtimes and the
|
||||||
|
Verse.
|
||||||
|
|
||||||
|
## Authority
|
||||||
|
|
||||||
|
- Brokkr owns the broker contract, provider advertisement, routing policy, and
|
||||||
|
typed command receipts.
|
||||||
|
- Unity owns Unity editor truth: scenes, assets, selection, play mode, imports,
|
||||||
|
build settings, and editor-side side effects.
|
||||||
|
- Blender owns Blender editor truth: scenes, objects, assets, operators, add-ons,
|
||||||
|
render settings, and editor-side side effects.
|
||||||
|
- Eve owns rendering of Brokkr surfaces.
|
||||||
|
- Odin owns discovery of Brokkr as a Verse provider.
|
||||||
|
- CultCache owns durable `.cc` witnesses and command receipts.
|
||||||
|
|
||||||
|
Plugins are adapters. They do not own Verse state. They connect their host editor
|
||||||
|
to Brokkr, publish editor observations, and execute admitted commands from the
|
||||||
|
broker.
|
||||||
|
|
||||||
|
## Surfaces
|
||||||
|
|
||||||
|
- `surfaces/unity/Packages/com.gamecult.brokkr`: Unity editor package scaffold.
|
||||||
|
- `surfaces/blender/brokkr_bridge`: Blender add-on scaffold.
|
||||||
|
- `brokkr-daemon`: Rust daemon skeleton that emits Brokkr's provider
|
||||||
|
advertisement and command policy.
|
||||||
|
|
||||||
|
## First Smoke
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cargo run -p brokkr-daemon -- provider
|
||||||
|
```
|
||||||
|
|
||||||
|
The first smoke prints the typed provider advertisement. That is deliberately
|
||||||
|
small: discovery shape first, live sockets second.
|
||||||
|
|
||||||
11
brokkr-daemon/Cargo.toml
Normal file
11
brokkr-daemon/Cargo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "brokkr-daemon"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
|
||||||
170
brokkr-daemon/src/main.rs
Normal file
170
brokkr-daemon/src/main.rs
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
const PROVIDER_SCHEMA: &str = "gamecult.brokkr.provider_advertisement.v0";
|
||||||
|
const PROVIDER_ID: &str = "brokkr.creative_tool_broker";
|
||||||
|
const CULTMESH_BASE_URI: &str = "cultmesh://brokkr";
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct ProviderAdvertisement {
|
||||||
|
schema: &'static str,
|
||||||
|
provider: ProviderIdentity,
|
||||||
|
authority: Authority,
|
||||||
|
transports: Vec<Transport>,
|
||||||
|
tool_surfaces: Vec<ToolSurface>,
|
||||||
|
eve_surfaces: Vec<EveSurface>,
|
||||||
|
command_policy: CommandPolicy,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct ProviderIdentity {
|
||||||
|
id: &'static str,
|
||||||
|
title: &'static str,
|
||||||
|
description: &'static str,
|
||||||
|
version: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct Authority {
|
||||||
|
owner: &'static str,
|
||||||
|
role: &'static str,
|
||||||
|
state_owner: &'static str,
|
||||||
|
presentation_owner: &'static str,
|
||||||
|
discovery_owner: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct Transport {
|
||||||
|
kind: &'static str,
|
||||||
|
base_uri: &'static str,
|
||||||
|
status: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct ToolSurface {
|
||||||
|
id: &'static str,
|
||||||
|
title: &'static str,
|
||||||
|
tool_kind: &'static str,
|
||||||
|
adapter: &'static str,
|
||||||
|
capabilities: Vec<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct EveSurface {
|
||||||
|
id: &'static str,
|
||||||
|
title: &'static str,
|
||||||
|
cult_mesh_uri: &'static str,
|
||||||
|
schema: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct CommandPolicy {
|
||||||
|
mode: &'static str,
|
||||||
|
envelope_schema: &'static str,
|
||||||
|
receipt_schema: &'static str,
|
||||||
|
notes: Vec<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let command = std::env::args()
|
||||||
|
.nth(1)
|
||||||
|
.unwrap_or_else(|| "provider".to_string());
|
||||||
|
|
||||||
|
match command.as_str() {
|
||||||
|
"provider" => print_provider(),
|
||||||
|
"smoke" => print_provider(),
|
||||||
|
_ => {
|
||||||
|
eprintln!("usage: brokkr-daemon [provider|smoke]");
|
||||||
|
std::process::exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_provider() -> Result<()> {
|
||||||
|
let advertisement = build_provider_advertisement();
|
||||||
|
println!("{}", serde_json::to_string_pretty(&advertisement)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_provider_advertisement() -> ProviderAdvertisement {
|
||||||
|
ProviderAdvertisement {
|
||||||
|
schema: PROVIDER_SCHEMA,
|
||||||
|
provider: ProviderIdentity {
|
||||||
|
id: PROVIDER_ID,
|
||||||
|
title: "Brokkr",
|
||||||
|
description: "GameCult creative-tool broker for Unity, Blender, and future editor runtimes.",
|
||||||
|
version: env!("CARGO_PKG_VERSION"),
|
||||||
|
},
|
||||||
|
authority: Authority {
|
||||||
|
owner: "Brokkr",
|
||||||
|
role: "CultMesh broker for creative editor observations, command admission, receipts, and Eve/CultUI projection.",
|
||||||
|
state_owner: "Brokkr typed CultCache witnesses; host editors own host-local scene and asset truth.",
|
||||||
|
presentation_owner: "Eve/CultUI lowers Brokkr surfaces without owning editor truth.",
|
||||||
|
discovery_owner: "Odin discovers Brokkr through CultMesh provider advertisements.",
|
||||||
|
},
|
||||||
|
transports: vec![Transport {
|
||||||
|
kind: "cultmesh",
|
||||||
|
base_uri: CULTMESH_BASE_URI,
|
||||||
|
status: "scaffold",
|
||||||
|
}],
|
||||||
|
tool_surfaces: vec![
|
||||||
|
ToolSurface {
|
||||||
|
id: "brokkr.unity_editor",
|
||||||
|
title: "Unity Editor",
|
||||||
|
tool_kind: "unity-editor",
|
||||||
|
adapter: "surfaces/unity/Packages/com.gamecult.brokkr",
|
||||||
|
capabilities: shared_capabilities(),
|
||||||
|
},
|
||||||
|
ToolSurface {
|
||||||
|
id: "brokkr.blender_editor",
|
||||||
|
title: "Blender Editor",
|
||||||
|
tool_kind: "blender-editor",
|
||||||
|
adapter: "surfaces/blender/brokkr_bridge",
|
||||||
|
capabilities: shared_capabilities(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
eve_surfaces: vec![
|
||||||
|
EveSurface {
|
||||||
|
id: "brokkr.eve.tool_broker.v0",
|
||||||
|
title: "Creative Tool Broker",
|
||||||
|
cult_mesh_uri: "cultmesh://brokkr/eve/tool-broker",
|
||||||
|
schema: "gamecult.eve.surface.v1",
|
||||||
|
},
|
||||||
|
EveSurface {
|
||||||
|
id: "brokkr.eve.command_receipts.v0",
|
||||||
|
title: "Command Receipts",
|
||||||
|
cult_mesh_uri: "cultmesh://brokkr/eve/command-receipts",
|
||||||
|
schema: "gamecult.eve.surface.v1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
command_policy: CommandPolicy {
|
||||||
|
mode: "policy-gated",
|
||||||
|
envelope_schema: "gamecult.brokkr.command_request.v0",
|
||||||
|
receipt_schema: "gamecult.brokkr.command_receipt.v0",
|
||||||
|
notes: vec![
|
||||||
|
"Plugins are adapters and do not own Verse provider truth.",
|
||||||
|
"All host mutations must produce command receipts.",
|
||||||
|
"Unity and Blender commands share one envelope shape.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shared_capabilities() -> Vec<&'static str> {
|
||||||
|
vec![
|
||||||
|
"host.status.read",
|
||||||
|
"scene.tree.read",
|
||||||
|
"selection.read",
|
||||||
|
"asset.catalog.read",
|
||||||
|
"command.palette.read",
|
||||||
|
"command.execute",
|
||||||
|
"receipt.read",
|
||||||
|
]
|
||||||
|
}
|
||||||
86
docs/architecture.md
Normal file
86
docs/architecture.md
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Brokkr Architecture
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
Expose creative editor runtimes to the Verse through one coherent CultMesh broker
|
||||||
|
daemon, beginning with Unity and Blender plugin surfaces.
|
||||||
|
|
||||||
|
## Current Mechanism
|
||||||
|
|
||||||
|
Brokkr starts as a Rust daemon skeleton that can emit a provider advertisement.
|
||||||
|
Unity and Blender each have a thin plugin scaffold with host-local metadata and
|
||||||
|
connection settings. The live transport is intentionally not claimed yet; the
|
||||||
|
first contract establishes owner, inputs, outputs, command policy, and surface
|
||||||
|
names.
|
||||||
|
|
||||||
|
## Invariants
|
||||||
|
|
||||||
|
- Editor hosts keep editor truth. Brokkr never becomes the canonical scene,
|
||||||
|
asset, object, import, or build database.
|
||||||
|
- Brokkr owns Verse-facing broker identity, command admission, routing receipts,
|
||||||
|
and durable witness publication.
|
||||||
|
- Unity and Blender commands share the same command envelope and receipt shape.
|
||||||
|
- Eve/CultUI surfaces are projections over Brokkr/provider state and host
|
||||||
|
observations, not separate dashboards with their own truth.
|
||||||
|
- JSON is tolerated only as a schema/debug/export boundary. Durable state should
|
||||||
|
become CultCache `.cc` witnesses as the runtime grows.
|
||||||
|
|
||||||
|
## Intended Change
|
||||||
|
|
||||||
|
The Unity idea is widened into a general creative-tool broker: Unity and Blender
|
||||||
|
are peers behind one broker contract. Tool-specific plugins stay boring and
|
||||||
|
replaceable. Brokkr becomes the stable Verse organ.
|
||||||
|
|
||||||
|
## Cut Line
|
||||||
|
|
||||||
|
Do not build separate Unity and Blender Verse providers unless a future invariant
|
||||||
|
proves they need independent authority. Do not give plugins their own discovery
|
||||||
|
truth, command policy, or dashboard summaries. They delegate to Brokkr.
|
||||||
|
|
||||||
|
## Owner Map
|
||||||
|
|
||||||
|
Owner: Brokkr owns tool-to-Verse brokerage.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
|
||||||
|
- Host observations from Unity and Blender plugins.
|
||||||
|
- Operator commands admitted through Brokkr's command policy.
|
||||||
|
- Odin discovery queries.
|
||||||
|
- Eve/CultUI surface requests.
|
||||||
|
- CultCache witness stores.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
|
||||||
|
- `gamecult.brokkr.provider_advertisement.v0`
|
||||||
|
- `gamecult.brokkr.tool_host_snapshot.v0`
|
||||||
|
- `gamecult.brokkr.command_request.v0`
|
||||||
|
- `gamecult.brokkr.command_receipt.v0`
|
||||||
|
- Eve/CultUI surface documents for host status, selection, assets, scene/object
|
||||||
|
trees, command palette, and receipt history.
|
||||||
|
|
||||||
|
Derived State:
|
||||||
|
|
||||||
|
- Unity package settings are adapter configuration, not Verse authority.
|
||||||
|
- Blender add-on preferences are adapter configuration, not Verse authority.
|
||||||
|
- Editor selection and scene summaries are observations until command receipts
|
||||||
|
confirm an accepted mutation.
|
||||||
|
|
||||||
|
Forbidden Writers:
|
||||||
|
|
||||||
|
- Unity editor callbacks cannot write Verse provider truth directly.
|
||||||
|
- Blender operators cannot write Verse provider truth directly.
|
||||||
|
- Eve renderers cannot admit commands directly to editor hosts.
|
||||||
|
- Odin discovery records cannot decide command permissions.
|
||||||
|
|
||||||
|
Shared Paths:
|
||||||
|
|
||||||
|
- Unity commands, Blender commands, programmatic commands, UI-triggered commands,
|
||||||
|
and replayed command receipts must use the same command envelope.
|
||||||
|
- Host snapshots from all tools must carry host id, tool kind, project path,
|
||||||
|
observed-at timestamp, capabilities, and authority owner.
|
||||||
|
|
||||||
|
Deletion Line:
|
||||||
|
|
||||||
|
If a plugin grows its own command policy, provider advertisement, or durable
|
||||||
|
state ledger, cut it back into an adapter and move the authority into Brokkr.
|
||||||
|
|
||||||
27
docs/provider-contract.md
Normal file
27
docs/provider-contract.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Brokkr Provider Contract
|
||||||
|
|
||||||
|
Provider id: `brokkr.creative_tool_broker`
|
||||||
|
|
||||||
|
CultMesh base URI: `cultmesh://brokkr`
|
||||||
|
|
||||||
|
Primary Eve surface id: `brokkr.eve.tool_broker.v0`
|
||||||
|
|
||||||
|
## Tool Kinds
|
||||||
|
|
||||||
|
- `unity-editor`
|
||||||
|
- `blender-editor`
|
||||||
|
|
||||||
|
## Capability Families
|
||||||
|
|
||||||
|
- `host.status.read`
|
||||||
|
- `scene.tree.read`
|
||||||
|
- `selection.read`
|
||||||
|
- `asset.catalog.read`
|
||||||
|
- `command.palette.read`
|
||||||
|
- `command.execute`
|
||||||
|
- `receipt.read`
|
||||||
|
|
||||||
|
The scaffold advertises command execution as policy-gated. No host command
|
||||||
|
should execute unless the host plugin recognizes the command family and Brokkr
|
||||||
|
has issued a command request with a receipt id.
|
||||||
|
|
||||||
17
schemas/brokkr-provider-advertisement.v0.schema.json
Normal file
17
schemas/brokkr-provider-advertisement.v0.schema.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "gamecult.brokkr.provider_advertisement.v0",
|
||||||
|
"title": "Brokkr Provider Advertisement",
|
||||||
|
"type": "object",
|
||||||
|
"required": ["schema", "provider", "authority", "transports", "toolSurfaces", "eveSurfaces", "commandPolicy"],
|
||||||
|
"properties": {
|
||||||
|
"schema": { "const": "gamecult.brokkr.provider_advertisement.v0" },
|
||||||
|
"provider": { "type": "object" },
|
||||||
|
"authority": { "type": "object" },
|
||||||
|
"transports": { "type": "array" },
|
||||||
|
"toolSurfaces": { "type": "array" },
|
||||||
|
"eveSurfaces": { "type": "array" },
|
||||||
|
"commandPolicy": { "type": "object" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
80
surfaces/blender/brokkr_bridge/__init__.py
Normal file
80
surfaces/blender/brokkr_bridge/__init__.py
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
bl_info = {
|
||||||
|
"name": "Brokkr",
|
||||||
|
"author": "GameCult",
|
||||||
|
"version": (0, 1, 0),
|
||||||
|
"blender": (4, 0, 0),
|
||||||
|
"location": "View3D > Sidebar > Brokkr",
|
||||||
|
"description": "Blender adapter for the Brokkr CultMesh creative-tool broker.",
|
||||||
|
"category": "System",
|
||||||
|
}
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
PROVIDER_ID = "brokkr.blender_editor"
|
||||||
|
TOOL_KIND = "blender-editor"
|
||||||
|
DEFAULT_BROKER_URI = "cultmesh://brokkr"
|
||||||
|
|
||||||
|
|
||||||
|
class BrokkrPreferences(bpy.types.AddonPreferences):
|
||||||
|
bl_idname = __name__
|
||||||
|
|
||||||
|
broker_uri: bpy.props.StringProperty(
|
||||||
|
name="Broker URI",
|
||||||
|
default=DEFAULT_BROKER_URI,
|
||||||
|
description="CultMesh broker URI for Brokkr",
|
||||||
|
)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
layout.prop(self, "broker_uri")
|
||||||
|
|
||||||
|
|
||||||
|
class BROKKR_PT_status(bpy.types.Panel):
|
||||||
|
bl_label = "Brokkr"
|
||||||
|
bl_idname = "BROKKR_PT_status"
|
||||||
|
bl_space_type = "VIEW_3D"
|
||||||
|
bl_region_type = "UI"
|
||||||
|
bl_category = "Brokkr"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
prefs = context.preferences.addons[__name__].preferences
|
||||||
|
layout.label(text=f"Provider: {PROVIDER_ID}")
|
||||||
|
layout.label(text=f"Tool Kind: {TOOL_KIND}")
|
||||||
|
layout.label(text=f"Broker: {prefs.broker_uri}")
|
||||||
|
layout.operator("brokkr.capture_snapshot")
|
||||||
|
|
||||||
|
|
||||||
|
class BROKKR_OT_capture_snapshot(bpy.types.Operator):
|
||||||
|
bl_idname = "brokkr.capture_snapshot"
|
||||||
|
bl_label = "Capture Host Snapshot"
|
||||||
|
bl_description = "Scaffold command: report the current Blender host snapshot to the console"
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
snapshot = {
|
||||||
|
"schema": "gamecult.brokkr.tool_host_snapshot.v0",
|
||||||
|
"providerId": PROVIDER_ID,
|
||||||
|
"toolKind": TOOL_KIND,
|
||||||
|
"projectPath": bpy.data.filepath,
|
||||||
|
"scene": context.scene.name if context.scene else "",
|
||||||
|
}
|
||||||
|
print(f"Brokkr snapshot scaffold: {snapshot}")
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
classes = (
|
||||||
|
BrokkrPreferences,
|
||||||
|
BROKKR_PT_status,
|
||||||
|
BROKKR_OT_capture_snapshot,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def register():
|
||||||
|
for cls in classes:
|
||||||
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
|
|
||||||
|
def unregister():
|
||||||
|
for cls in reversed(classes):
|
||||||
|
bpy.utils.unregister_class(cls)
|
||||||
|
|
||||||
10
surfaces/blender/docs/install.md
Normal file
10
surfaces/blender/docs/install.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Blender Add-on Scaffold
|
||||||
|
|
||||||
|
Install `surfaces/blender/brokkr_bridge` as a Blender add-on directory during
|
||||||
|
local development.
|
||||||
|
|
||||||
|
The scaffold adds a Brokkr panel to the 3D View sidebar. It does not open a live
|
||||||
|
transport yet. Its first job is to preserve the adapter boundary: Blender emits
|
||||||
|
host snapshots and executes admitted Brokkr commands; Brokkr owns Verse-facing
|
||||||
|
broker state and receipts.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace GameCult.Brokkr.Editor
|
||||||
|
{
|
||||||
|
internal static class BrokkrSettings
|
||||||
|
{
|
||||||
|
internal const string ProviderId = "brokkr.unity_editor";
|
||||||
|
internal const string ToolKind = "unity-editor";
|
||||||
|
internal const string DefaultBrokerUri = "cultmesh://brokkr";
|
||||||
|
|
||||||
|
internal static string BrokerUri
|
||||||
|
{
|
||||||
|
get => EditorPrefs.GetString("GameCult.Brokkr.BrokerUri", DefaultBrokerUri);
|
||||||
|
set => EditorPrefs.SetString("GameCult.Brokkr.BrokerUri", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace GameCult.Brokkr.Editor
|
||||||
|
{
|
||||||
|
public sealed class BrokkrWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private string brokerUri = BrokkrSettings.DefaultBrokerUri;
|
||||||
|
|
||||||
|
[MenuItem("GameCult/Brokkr")]
|
||||||
|
public static void Open()
|
||||||
|
{
|
||||||
|
GetWindow<BrokkrWindow>("Brokkr");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
brokerUri = BrokkrSettings.BrokerUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField("Provider", BrokkrSettings.ProviderId);
|
||||||
|
EditorGUILayout.LabelField("Tool Kind", BrokkrSettings.ToolKind);
|
||||||
|
brokerUri = EditorGUILayout.TextField("Broker URI", brokerUri);
|
||||||
|
|
||||||
|
if (GUILayout.Button("Save Settings"))
|
||||||
|
{
|
||||||
|
BrokkrSettings.BrokerUri = brokerUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
EditorGUILayout.HelpBox(
|
||||||
|
"Scaffold only: this adapter should publish Unity editor observations to Brokkr and execute admitted broker commands with receipts.",
|
||||||
|
MessageType.Info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GameCult.Brokkr
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class BrokkrHostSnapshot
|
||||||
|
{
|
||||||
|
public string schema = "gamecult.brokkr.tool_host_snapshot.v0";
|
||||||
|
public string providerId = "brokkr.unity_editor";
|
||||||
|
public string toolKind = "unity-editor";
|
||||||
|
public string projectPath = "";
|
||||||
|
public string observedAt = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
11
surfaces/unity/Packages/com.gamecult.brokkr/package.json
Normal file
11
surfaces/unity/Packages/com.gamecult.brokkr/package.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "com.gamecult.brokkr",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"displayName": "Brokkr",
|
||||||
|
"description": "Unity Editor adapter for the Brokkr CultMesh creative-tool broker.",
|
||||||
|
"unity": "2022.3",
|
||||||
|
"author": {
|
||||||
|
"name": "GameCult"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
12
tools/check.ps1
Normal file
12
tools/check.ps1
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
Push-Location (Split-Path -Parent $PSScriptRoot)
|
||||||
|
try {
|
||||||
|
cargo fmt --check
|
||||||
|
cargo test --workspace
|
||||||
|
cargo run -p brokkr-daemon -- provider | Out-Null
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in a new issue