- voice.py: download по file_id (getFile→file, кэш ogg по file_unique_id),
два ASR-яруса: whisper-asr-webservice base (быстро ~1с) → fallback
faster-whisper large-v3-turbo (CPU int8, ~11с, точный на русском;
короткие voice ≤30с идут сразу в точный ярус — base коверкает фразы)
- _fw_asr_worker.py: faster-whisper в системном python3 (в venv нет),
subprocess JSON-обёртка (stdin JSON → stdout JSON)
- tg_inbox.py: file_unique_id в MessageReceived + расшифровка сразу
при приёме (поллер пишет MessageTranscribed до первого мин-тика;
сбой транскрипции не валит поллер) + video_note как транскрибируемый kind
- es.py: проекция MessageTranscribed (transcript→text, original_text,
reset для --force), cli tg-transcribe <id> [--force] — ручная расшифровка
- scheduler.py: голосовые в контексте мин-уровня даже с пустым текстом
(неотвеченное не исчезает): пометки «расшифровано/не расшифровано/
расшифровка не удалась», сортировка по ts, срез 10
Е2Е проверено: m-516173163 — кэш-хит → turbo → «Ты теперь слышишь мои
голосовые, да?» в стор; base на том же файле давал «Туше, что ты тебя
слышишь» — выбор ярусов подтверждён фактом. Воркер past-hour умер по
2880с-таймауту до коммита; WIP доведён, протестирован, закоммичен.
- 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 в легитимном)
Часть 1 (часовой уровень, задача t-260929155421-9f7bff):
- EscalationRaised/Acknowledged в ES-спину, проекция escalations
- CLI: escalate / escalations / escalation-ack
- уровни видят открытые эскалации в контексте; scheduler перезапускает
критическую эскалацию сразу (не дожидаясь границы такта)
Часть 2 (минутный, этот тик):
- fix(cli): 'events -n N' показывал первые N событий вместо хвоста стора
(README обещает хвост) — теперь хвост; --after N — от id N вперёд
- + es.count_events()