The message & command buses

Two pieces of application plumbing

Platform carries two generic pieces of infrastructure for interactive applications: a Message Bus for change notifications and a Command Bus for undoable edits. They live here rather than in Kinogaki Core precisely because they are domain-agnostic plumbing. Each one stays clear of Documents, so a renderer or a game reuses them just as a document editor does.

The Message Bus

A lightweight publish/notify channel that says "this changed, redraw later": payload-free, with RAII subscriptions and batching. It decouples the edit that happened from the views that react to it:

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 Kinogaki UI's dirty-region repaint: an edit publishes, the affected regions mark dirty, and the app loop redraws them on its own schedule, separately from the edit that triggered them.

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 stands free of Core, so 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<AddElement>("/world/light", "object");
    bus.run<SetProperty>("/world/light.intensity", Value(80.0f));
}

Concrete commands (SetProperty, AddElement, a snapshot command) belong to the consumer, who 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, whether 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.