---
name: investpilot-silent-outage-2026-07-27
description: КодИнвест молчал 2.5 суток — NameError в _bucket убил планировщик + третья потеря ключей в .env; нет watchdog «давно не было скана»
metadata:
  node_type: memory
  type: project
  originSessionId: 6f344612-b945-4107-b457-8ad2163cd988
  modified: 2026-07-27T07:03:48.537Z
---

Жалоба владельца «бот не шлёт рекомендаций, может со стратегией что-то не
так» (2026-07-27) оказалась ДВУМЯ инфраструктурными поломками, стратегия
ни при чём. См. Obsidian Changelog «ИНЦИДЕНТ: бот молчал 2.5 суток».

**1. Мой регресс (2026-07-23).** `scheduler.py` импортировал
`explain_gate_reason as _explain_reason`, а `_bucket()` в последней строке
звал `explain_gate_reason` → `NameError` → упал вечерний отчёт 24.07 и
**сканов не было 25/26/27 июля**, при живом процессе и зелёном тайле
ops_dashboard. Тесты не поймали: все причины в тесте матчились ранними
ветками `_bucket`, до fallback-строки исполнение не доходило.

**Урок (важнее самого бага):** когда функция — цепочка `if ... return`,
тест «функция работает» ничего не значит для НЕ пройденных веток. При
добавлении fallback-ветки писать тест ИМЕННО на неё. И проверять, что
новый тест реально ловит баг (воспроизвести поломку → увидеть падение →
вернуть фикс), а не просто «зелёный после фикса».

**2. Третья потеря ключей в `.env`** (после D38 про `rsync --delete`):
пропали `INVESTPILOT_OMNIROUTE_API_KEY` и `INVESTPILOT_NVIDIA_API_KEY` →
401 на ВСЕХ моделях. Важная деталь: `research/*` (CebersResearch) тоже
ломается без omni-ключа — роутер (`llm/router.py::_route`) отдаёт им
`self._omni_key`. Восстановление: `source ~/.codex/omniroute.env`, оттуда
`OMNIROUTE_API_KEY` и `DELOR_IMAGE_API_KEY` (→ NVIDIA), с бэкапом
`.env.bak.*`. Диагностика в один шаг: `sed "s/=.\{0,4\}.*/=***/" .env` —
сравнить список ключей с `config.py::Settings`.

**Открытая дыра, НЕ закрыта:** планировщик встал молча. `_maybe_llm_chain_alert`
не сработал ни разу — счётчик отказов растёт только ВНУТРИ ветки скана, а
сканов не было вовсе. Нужен watchdog «N часов без успешного скана в
торговый день → алерт владельцу»; ops_dashboard тоже зелёный (смотрит
живой PID, а не свежесть работы). Обсудить с владельцем.

**How to apply:** при жалобе «бот молчит» — СНАЧАЛА проверять факты в
таком порядке: (1) когда был последний УСПЕШНЫЙ скан в логе, (2) ошибки
после него, (3) наличие ключей в `.env`, (4) живой пинг моделей, и только
потом думать на стратегию/гейты. Зелёный тайл ops_dashboard и живой
процесс НЕ означают, что бот работает.
