Three alert signals had no UI subscribers — gameplay failures vanished
silently. Now all three feed AlertsLog via translator handlers that
forward to the generic alert_added sink.
- EventBus: new no_stockpile_accepts(item_type, tile) and
bill_blocked(recipe_label, reason, focus_tile) signals.
- HaulingProvider: per-item-type 30s cooldown; emits when find_best_for
scan finishes with viable items but no destinations.
- CraftingProvider: per-(workbench, reason) 60s cooldown; emits at the
skill_too_low and missing_ingredient continue sites. no_workbench
reason declared for future use but not emitted (the iteration shape
has no natural site for it).
- AlertsLog: connect + disconnect for all three signals using the same
has_signal-guarded pattern; translator handlers convert to localized
alert_added(severity, text, focus_tile).
- AlertsLog catch-up: room_too_large emits during World init, before
this CanvasLayer mounts. _catch_up_room_too_large() in _ready scans
World.rooms for rooms > ROOM_AUTOROOF_CAP and replays them, so the
pre-built cabin's 24-tile-too-large warning lands in the log on every
boot. Hauling/bill signals fire at runtime so they need no catch-up.
Verified runtime: cabin warning shows up in AlertsLog with severity
'warn' and focus_tile (45, 24) — the cabin top-left.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>