Decision

Control messages are never retained

A retained MQTT control message replays to every client that reconnects, which would make a loco move with nobody asking. Control topics are always published unretained.

Status
accepted
Decided
Affects
Layout Orchestration, ESP Layout Controller

Context

MQTT can retain a message, so the broker hands the last value to anything that subscribes later. That’s useful for state: a new UI client immediately sees every block and point without polling. For a command it’s dangerous.

Decision

Control topics are never retained. A controller that restarts receives no stale throttle command, so there’s no ghost movement. It recovers the last known loco state from the retained state topics instead.

The same idea carries over to the throttle’s WebSocket connection. A state snapshot received on reconnect updates the display and is never replayed as commands, because it describes what the layout believes, including locos this device didn’t start.

Consequences

Source: docs/mqtt-contract.md, “QoS and Retained” and esp-layout-controller CLAUDE.md.