c76038d076
Закрывает дыру #6 из аудита журналирования 23.05.2026. Что: * `scheduler_heartbeats` таблица (SaaS-level, PK=command_name, без RLS) * `SchedulerHeartbeatTracker` сервис — UPSERT через pgsql_supplier (BYPASSRLS), recordRun(callable) + recordRunResult(name, success, error, ms) * `routes/console.php` — 11 cron-задач обёрнуты onSuccess/onFailure хуками (минимально-инвазивно, без правки самих джобов) * `scheduler:check-heartbeats` команда — hourly МСК: - алертит при пропавшем пульсе (>2× ожидаемого интервала) - алертит при consecutive_failures >= 3 - dedup 60 мин, пишет incidents_log (severity=high) + Mail на kdv1@bk.ru * `SchedulerHeartbeatMissingMail` mailable + blade NB: используется `onSuccess()` а не `after()` — `after()` срабатывает при любом исходе и ложно обновлял бы last_success_at при failure (правильный поведенческий паттерн = onSuccess + onFailure). consecutive_failures корректно растёт через ON CONFLICT DO UPDATE +1. Schema bump v8.29→v8.30. +1 слово в cspell-words.txt (FQCN). Тесты: 8/8 passed (24 assertions, ~1.6s) — recordRun success/failure, SchedulerCheckHeartbeats missing pulse + failure spike + dedup + Mailable. Plan: docs/superpowers/plans/2026-05-23-7-holes-overview.md (#6).