Brokkr/surfaces/unity/README.md
Meta Vens be0cc3683f Brokkr advertisement: drop Eve surface URIs and eve.*.publish capabilities; Eve is deprecated
Per thing2:ruling:eve-dashboards-quarantined. Removes eveSurfaces from the provider advertisement and its schema, the two surface URIs, the eve.gui/eve.tui publish capabilities, and Eve wording in docs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 20:14:59 +02:00

153 lines
6.7 KiB
Markdown

# Brokkr Unity Adapter
This package lets the Unity Editor publish its scene, component, asset, command,
receipt, and Quest state as typed CultCache documents synced through
CultMesh.
## Install By Local Path
Add this package to a Unity project's `Packages/manifest.json`:
```json
"com.gamecult.brokkr": "file:F:/Projects/Brokkr/surfaces/unity/Packages/com.gamecult.brokkr"
```
The package ships no assemblies. Its CultCache, CultNet and CultMesh runtime
comes from `org.gamecult.cultlib`, which the host manifest must also resolve:
```json
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.60"
```
Then open `GameCult > Brokkr`.
## Local Smoke
In Unity:
1. Open `GameCult > Brokkr`.
2. Confirm `Broker URI` is `cultmesh://brokkr`.
3. Confirm `CultMesh Cache` points at `.brokkr/unity-editor.ccmp`.
4. Click `Start CultMesh Mirror`.
5. Click `Capture Snapshot`.
6. Click `Publish Mirror`.
7. To create a ScriptableObject through the mirror (tick `Agent Commands` first, and add `createScriptableObject` to `Allowed Actions`), fill `ScriptableObject Type`,
`Asset Name`, and `Asset Path`, then click `Create ScriptableObject Asset`.
8. To instantiate or variant a prefab through the mirror, fill `Prefab Asset
Path`, optional `Instance Name`, and optional `Variant Path`, then click the
matching prefab command.
9. To publish object sync policy, select a GameObject, set the object lane
toggles including transform, parent, active state, material, and property
lanes, then click `Publish Object Sync`.
10. With the mirror running, run `brokkr-daemon sync-once` or `sync-loop`; the window
shows the latest daemon
sync pass receipt.
11. To publish an ad hoc sync variable, fill `Ad Hoc Sync Var` with a binding id
or leave it blank for a generated id, set kind/paths/authority/interpolation,
then click `Publish Sync Var`.
The Unity adapter writes the latest editor snapshot to:
```text
unity/host/current
```
Brokkr daemon sync receipts are read from:
```text
sync/receipts/{receiptId}
```
Ad hoc sync variables are written to:
```text
sync/vars/{syncVarId}
```
Verse-side command clients write `brokkr.unity.command_intent.v0` documents to:
```text
unity/commands/{commandId}
```
The editor service pulls the store about once a second while `Agent Commands` is on, admits each intent through the project policy, mutates the editor, and publishes receipts
to:
```text
unity/receipts/{commandId}
```
Recognized Unity asset commands include:
- `instantiatePrefab`
- `createPrefabVariant`
- `createScriptableObject`
The Unity plugin is still an adapter. Unity owns Unity editor truth; Brokkr owns
provider discovery; CultCache and CultMesh own the live mirror lane.
## Agent Commands
The editor executes intents that other processes write into `.brokkr/` only
while `Agent Commands` is ticked in the Brokkr window. It is off for every
project until you tick it, and the host snapshot reports the flag. Nothing
listens on the network: callers reach the editor through the directory store
at `.brokkr/unity-editor.ccmp`.
`Allowed Actions` lists what an agent may run. The default allows scene
mutation and editor lifecycle; `createScriptableObject`, `createPrefabVariant`
and `saveScene` are off until you add them. A refused intent gets a receipt
with `status: denied`. Captures land under `.brokkr/captures/`.
From a shell, with the project's cache path:
```powershell
dotnet run --project F:/Projects/Brokkr/brokkr-command/Brokkr.Command.csproj -- --unity-cache <project>/.brokkr/unity-editor.ccmp --action readHost
dotnet run --project F:/Projects/Brokkr/brokkr-command/Brokkr.Command.csproj -- --unity-cache <project>/.brokkr/unity-editor.ccmp --action createGameObject --name Marker
```
Turning `Agent Commands` on expires every intent already in `.brokkr/`: each
gets a receipt with `status: expired` and none runs, so enabling the sink
cannot execute anything you did not see. The expiry is one commit that only
lands if the store is exactly what the editor just read; an intent that arrives
mid-enable makes it read again, and if writers never let the store settle
(eight tries) the enable fails with a message and the sink stays off. Intents
that arrive after the tick are fresh, whatever clock wrote them. With about
2000 waiting intents the tick takes several seconds (the store writes one
receipt each); after that the editor handles at most 16 intents per update
tick.
The tick also writes an enable marker into `.brokkr/unity-editor.ccmp`, and the
editor keeps the matching token in its own preferences. The sink runs only
while the store carries that marker. If you re-clone the project, or copy a
`.brokkr/` folder in, the marker is missing or foreign, so the editor turns the
sink off and logs why; tick `Agent Commands` again to run intents from that
store. The token is not authentication and does not identify who wrote an
intent: anyone who can write `.brokkr/` can write intents, and `Allowed
Actions` is what limits them. Restoring a backup, checking out `.brokkr/` from
git, or a sync-conflict copy of the editor's own store carries a valid marker
and can bring back intents that were already answered, which then run again.
Before the editor runs an intent it writes a receipt with `status: attempted`.
If the editor stops, or cannot record the result, that intent is reported as
`interrupted` and is not run again automatically. Check the project first:
`interrupted` does not say whether the action happened, and some actions are
not idempotent. Re-sending `createGameObject` after an `interrupted` receipt
can create the object twice; a domain reload during `refreshAssets` can also
end as `interrupted` although the refresh completed. If the editor could not
write the `attempted` receipt, the intent normally never started and is retried
on the next tick; if the store fails in a way that leaves the marker behind,
it is reported as `interrupted` instead.
Receipts are kept for the newest 1000 answered intents, and no receipt is
deleted before it is ten minutes old, whatever the count (`brokkr-command`
refuses a `--wait-ms` over five minutes, so the receipt a caller waits on is
always still there). Older intents beyond the count are deleted together with
their receipts, at most 128 per tick. A `--command-id` is refused only while
its receipt exists, so an id can be reused after its receipt has been pruned.
`brokkr-command` exits 0 when the receipt is `accepted`, 1 for any other
receipt status (`failed`, `denied`, `expired`, `interrupted`), and 2 for bad
usage, a timeout, a store that cannot be opened, or any other failure. A
`--command-id` that already has a receipt is refused with exit 2; the check and
the write are two steps, so two callers naming the same new id in the same
instant can still collide.