The cassette-state beacon was published only once at bootstrap, so after a
cash-out dispense the operator's view stayed frozen at the bootstrap snapshot
(still 20x4/50x7 after dispensing) — the ATM decremented its local HAL counts
but never told the operator. Coord 2026-06-21 (post cash-out leg).
- operator-config.ts: extract publishCassettesState() (the live, ungated
publish) out of the one-shot bootstrap; expose it on OperatorConfigService;
also fire it after an operator-config apply (the "on reload" case).
- atm.ts: republish after each cash-out dispense (complete + partial), once the
decremented counts are persisted. kind-30078 is replaceable (latest wins) and
the operator already consumes every update — no operator-side change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>