busy в read model всегда False — истинная занятость живёт в памяти
планировщика, событий для неё нет. Срез показывал «ожидает», пока
часовой уровень держал running-задачу. TaskClaimed закрепляет уровень
за задачей в проекции — теперь срез показывает «занят (running-задача)».
- tg_inbox.notify_chat(): отправка в чат харнеса без входящего-родителя
(чат = последний MessageReceived от Alex)
- tg_inbox.ladder_snapshot(): срез лестницы — занятость/тики/ошибки уровней,
готово/в работе, открытые эскалации; read-only через run_projections()
- scheduler._notify_busy(): уровень сообщает в TG о взятии задачи
(анти-спам 15м на уровень) — TaskClaimed в scheduler.run_level_tick
- cli.py: команда ladder + tg-notify; /лестница|/ladder|/статус|/status
в tg-reply заменяется на срез лестницы — запрос из TG самодостаточен
- guard в __main__ tg_inbox: единственный легитимный поллер — systemd-сервис
(раньше python -m harness.tg_inbox с любыми аргументами поднимал
конкурирующего поллера → 409 Conflict в легитимном)