Brokkr/docs/provider-contract.md
Meta Vens 673da3e62f A5: advertise the three editor capabilities the Unity actions now provide
editor.assets.refresh, editor.lifecycle.write and editor.view.capture join
the Unity surface, in the provider contract and the advertisement test. The
donor's prefab mirror rows are not taken; that pipeline is parked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 14:49:09 +02:00

10 KiB

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

  • cultcache.mirror.publish
  • cultcache.intent.watch
  • host.status.read
  • scene.tree.read
  • component.state.read
  • selection.read
  • asset.catalog.read
  • asset.scriptable_object.create
  • asset.prefab.instantiate
  • asset.prefab.variant.create
  • gameobject.create
  • component.attach
  • component.property.write
  • editor.assets.refresh
  • editor.lifecycle.write
  • editor.view.capture
  • command.receipt.publish
  • eve.gui.publish
  • eve.tui.publish

Mirror Documents

  • brokkr.unity.host_snapshot.v0 at unity/host/current
  • brokkr.unity.command_intent.v0 at unity/commands/{commandId}
  • brokkr.unity.command_receipt.v0 at unity/receipts/{commandId}
  • brokkr.unity.snapshot_receipt.v0 at unity/receipts/snapshots/{observedAt}
  • brokkr.unity.quest_route.v0 at unity/quest-routes/{routeId}
  • brokkr.unity.warped_video_frame.v0 at unity/quest/video/{frameId}
  • brokkr.blender.host_snapshot.v0 at blender/host/current
  • brokkr.blender.command_intent.v0 at blender/commands/{commandId}
  • brokkr.blender.command_receipt.v0 at blender/receipts/{commandId}
  • brokkr.sync.session.v0 at sync/sessions/{sessionId}
  • brokkr.sync.object_binding.v0 at sync/bindings/objects/{bindingId}
  • brokkr.sync.var.v0 at sync/vars/{syncVarId}
  • brokkr.sync.timeline_binding.v0 at sync/bindings/timelines/{bindingId}
  • brokkr.sync.receipt.v0 at sync/receipts/{receiptId}

Sync Organ

Brokkr owns sync correspondence and policy documents. Editor hosts still own scene mutation. A sync record can request or describe a lane, but it is not real editor state until Unity or Blender publishes accepted command receipts and a fresh host snapshot.

Primary sync documents:

  • brokkr.sync.session.v0: shared sync session and mode.
  • brokkr.sync.object_binding.v0: Unity GameObject to Blender object/collection correspondence.
  • brokkr.sync.var.v0: per-lane sync options such as transform, parent, material, component property, custom property, timeline frame, camera lens, or Cinemachine virtual camera. Editor surfaces may also publish ad hoc sync vars with an explicit kind, paths, authority, enabled flag, and interpolation. The daemon executes implemented kinds and preserves unsupported kinds as typed sync policy for external consumers.
  • brokkr.sync.timeline_binding.v0: Blender scene/action timeline to Unity Timeline/Cinemachine correspondence.
  • brokkr.sync.receipt.v0: daemon sync pass receipts.

Operational commands:

  • dotnet run --project brokkr-command/Brokkr.Command.csproj -- --unity-cache .brokkr/unity-editor.ccmp --action readHost
  • dotnet run --project brokkr-command/Brokkr.Command.csproj -- --unity-cache .brokkr/unity-editor.ccmp --action createGameObject --name Marker --local-position 0,1,0
  • brokkr-daemon sync-once --unity-cache .brokkr/unity-editor.ccmp --blender-cache .brokkr/blender-editor.ccmp
  • brokkr-daemon sync-loop --unity-cache .brokkr/unity-editor.ccmp --blender-cache .brokkr/blender-editor.ccmp --interval-ms 500

brokkr-command is a caller. Each invocation writes one intent through the directory store (every intent field has a --kebab-case option; --view and --output fill the capture fields), waits for the receipt, and exits 0 for accepted, 1 for any other status, and 2 for a usage error or a timeout. It never writes receipts, host snapshots or the agent-commands flag.

sync-loop owns scheduling only. It repeatedly invokes the same sync decision primitive as sync-once, writes command intents and sync receipts through the mirrors, and prints per-pass telemetry to stdout.

Each daemon pass writes the same brokkr.sync.receipt.v0 document into both editor mirror stores at sync/receipts/{receiptId}. Unity and Blender editor panels may display the latest receipt, but the daemon remains the owner of pass status.

Implemented sync lanes:

  • Missing counterpart materialization for enabled object bindings. When an authority side has an object and the target side does not, Brokkr emits createObject or createGameObject and waits for the next host snapshot before applying per-lane mutations.
  • Unity GameObject transform to Blender object transform.
  • Unity GameObject active state to Blender object visibility.
  • Unity GameObject parent id to Blender object parent through setObjectParent.
  • Unity Renderer material name to Blender object material assignment through assignMaterial.
  • Blender object visibility to Unity GameObject active state through setGameObjectActive.
  • Blender object parent name to Unity GameObject parent through setGameObjectParent. The Blender parent must have an object binding so Brokkr can resolve the Unity parent object id.
  • Unity serialized component property to Blender object custom property through setObjectCustomProperty. The syncvar kind may be component-property or custom-property; authority and paths determine direction. It uses unityPropertyPath = Component.Type::propertyPath and blenderPropertyPath = customProperties.name.
  • Blender object transform to Unity GameObject transform.
  • Blender object material name to Unity Renderer material assignment through assignMaterial.
  • Blender scene frame to Unity timeline time through setComponentProperty.
  • Blender scene camera transform/FOV to a Unity Cinemachine virtual camera GameObject/component. The FOV write uses componentType = Cinemachine.CinemachineVirtualCamera and property path m_Lens.FieldOfView.
  • Blender object custom property to Unity serialized property through setComponentProperty. The syncvar kind may be custom-property or component-property; authority and paths determine direction. It uses blenderPropertyPath = customProperties.name and unityPropertyPath = Component.Type::propertyPath when a Unity component should receive the value.

Unity Command Actions

All Unity writes use brokkr.unity.command_intent.v0 and receive brokkr.unity.command_receipt.v0.

  • createGameObject
  • attachComponent
  • setGameObjectTransform
  • setGameObjectActive
  • setGameObjectParent
  • setComponentProperty
  • instantiatePrefab
  • createPrefabVariant
  • assignMaterial
  • createScriptableObject
  • refreshAssets
  • setEditorPlayState
  • setEditorPaused
  • captureEditorView
  • saveScene

Unity owns the mutation. Brokkr advertises the command surface; Verse clients write typed command intents; Unity executes recognized intents and publishes receipts. setComponentProperty writes the target object by default; when componentType is present, Unity resolves that component on the target GameObject and writes the serialized property there. setGameObjectActive uses targetObjectId and boolean value. setGameObjectParent uses targetObjectId and parentObjectId; an empty parentObjectId reparents the GameObject to the scene root. instantiatePrefab uses assetPath as the source prefab, name as the optional instance name, and parentObjectId as the optional parent. createPrefabVariant uses assetPath as the source prefab and value as the destination prefab path. createScriptableObject uses componentType as the ScriptableObject type and assetPath as the destination asset path. refreshAssets forces an AssetDatabase refresh. setEditorPlayState and setEditorPaused take boolean value; the editor service restarts from [InitializeOnLoad] after the resulting domain reload and keeps draining. captureEditorView renders viewKind (scene or game) to a PNG at width by height (0 means the camera size, at most 8192). outputPath is a plain relative path ending in .png, resolved under <project>/.brokkr/captures/; anything else is denied. saveScene saves the open scenes.

Admission

Before any intent runs, BrokkrCommandPolicy checks it against the project's allowed-action list (window field "Allowed Actions", per project). By default scene mutation and editor lifecycle actions are allowed; the asset-writing actions createScriptableObject and createPrefabVariant, and saveScene, are not, and an action the list does not name is denied. A denied intent gets a receipt with status: denied and the reason in message, so a refusal is as visible as an acceptance. requestedBy on the intent names the caller and is echoed on the receipt; admission never reads it. The window's buttons write intents like any other caller, so the operator and an agent pass the same gate.

Unity Command Transport

Commands reach the editor through the project's directory store at <project>/.brokkr/unity-editor.ccmp (.records/ beside it). There is no network listener: admission starts at filesystem permissions, and the editor sees a written intent on its next pull, about once a second.

The editor executes intents only while the operator has enabled agent commands for that project (window toggle "Agent Commands"). The flag is off by default and installing the package never turns it on. The host snapshot carries it as agentCommandsEnabled, so a caller can see why nothing executes.

A command id is single-use. Every writer mints a fresh commandId for each act, and a receipt at unity/receipts/{commandId} answers exactly that id. Once an id has a receipt, the editor never executes it again, whatever is later written under it: reusing an answered id is a caller defect, and its receipt is the answer that stands. A writer that repeats an intent mints a new id for each repetition.

Blender Command Actions

All Blender writes use brokkr.blender.command_intent.v0 and receive brokkr.blender.command_receipt.v0.

  • createObject
  • deleteObject
  • setObjectTransform
  • setObjectVisibility
  • setObjectParent
  • setObjectCustomProperty
  • selectObject
  • assignMaterial

Blender owns the mutation. Brokkr advertises the command surface; Verse clients write typed command intents; Blender executes recognized intents and publishes receipts. setObjectParent uses targetObjectName and optional parentObjectName; an empty parent reparents the object to the Blender scene root.

Eve/CultUI Lowerings

Unity publishes lowerable Eve/CultUI documents through CultMesh. GUI and TUI clients render those documents as views over the same mirrored state:

  • scene graph
  • component state
  • asset library
  • command affordances
  • command receipts

These documents are interface state over Unity observations and receipts. They do not own editor truth.