The message & command buses

Two pieces of application plumbing

Platform carries two generic pieces of infrastructure that every interactive application needs and that are not document concepts: a Message Bus for change notifications and a Command Bus for undoable edits. They live here, not in Prism Core, precisely because they are domain-agnostic plumbing — neither knows anything about Prism documents, so a renderer or a game reuses them just as a document editor does.

The Message Bus

A lightweight publish/notify channel — "this changed, redraw later" — with no payload, RAII subscriptions, and batching. It decouples the thing that changed from the things that react:

events::Bus bus;
auto sub = bus.subscribe(Channel::Selection, [&]{ rebuildPanels(); });  // RAII; unsubscribes on scope exit
bus.publish(Channel::Selection);                                        // fan out
{
    events::Batch b(bus);          // coalesce a burst of changes into one notification
    /* many edits … */
}                                  // one publish on scope exit

It is the signal that drives Prism UI's dirty-region repaint: an edit publishes, the affected regions mark dirty, and the app loop redraws them on its own schedule — never synchronously from inside the edit.

The Command Bus

A header-only, fully generic CommandBus<Ctx> providing apply / undo / redo and transactions over any context type, with an after-run hook. It has zero dependency on Core — you parameterise it on your own document type:

command::CommandBus<Document> bus;
bus.onAfterRun = [&]{ /* publish a change, redraw */ };

bus.run<SetProperty>("/world/ball.radius", Value(2.0f));   // applies + records for undo
bus.undo();                                                 // and back
{
    command::Transaction tx(bus);     // group several commands into one undo step
    bus.run<AddPrim>("/world/light", "object");
    bus.run<SetProperty>("/world/light.intensity", Value(80.0f));
}

Concrete commands (SetProperty, AddPrim, a snapshot command) are not in Platform — the consumer writes them against CommandBus<MyDocument>. The bus provides the apply/undo/redo machinery and the transaction grouping; you provide what a command does.

Why this is the editing seam

Together the two buses are how an application edits its document uniformly. The Editor runs CommandBus<Document> so every change — a UI control, a typed source edit, or an agent's tool call over MCP — is one undoable command, and onAfterRun publishes on the Message Bus so the panels rebuild. Because the command bus is generic and the message bus is payload-free, this exact pattern works for any C++ application built on Platform — which is the point of putting them here rather than welding them to one document model.