Commit graph

32 commits

Author SHA1 Message Date
Simbiot Harness
70a2015bae 👍 на отвеченные сообщения (правка Коди t-261018103940) + тест; мусорный итог задачи не принимается
Коди сам доработал tg_inbox (задача Alex 10:39): после ответа ставит
реакцию на каждое отвеченное сообщение (одиночный и сводный ответ),
нашёл, что ✅ Telegram не принимает (REACTION_EMPTY) — взял 👍. Правка
лежала незакоммиченной и без теста, а задачу он закрыл с итогом «x»
до того, как доделал (Alex пришло «✅ Готово … x»).
- коммит правки Коди как есть;
- тест (test_tg_group_ux +8): 👍 на сообщение, весь батч, портал без
  реакции, сбой реакции не ломает ответ;
- complete_task_with_delivery: итог короче 10 символов («x», «2»,
  «готово» — 3 из 338 закрытий с октября) отклоняется с подсказкой
  «опиши, что сделано и где результат».
Полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:55:02 +00:00
Simbiot Harness
969d57f14a куб 4×4×4: 4 круга доверия, динамическая память D0–D3 с приватностью по кругу, голова depth
Куб Alex: круг доверия × тик (sec/min/hour/day) × глубина памяти —
одна таблица политик, не 64 программы.
- круги 4: 1 владелец (+система: тик без внешних входов), 2 правление,
  3 свои (портал, MCP-агенты, партнёры), 4 остальные; trust.norm для
  старых номеров (в сторе только 1/2 — смысл тот же); потолок памяти круга;
- harness/memory.py: индекс собственной истории (<home>/memory) — разговоры
  (сообщение + ответ; батч — ответ головы), свои рассылки (не ответы),
  итоги задач, дайджесты без заглушек; nomic search_document/query;
  КРУГ ПРИВАТНОСТИ записи = самый недоверенный участник чата (личка
  Alex — 1, «Правление» — 2, задача — её круг, дайджест — 1); поиск
  отдаёт только записи круга ≥ круга тика — тик с правлением не поднимет
  личку владельца; SIMBIOT_MEMORY=on|off (дефолт off — тесты герметичны);
- глубина: D0 односложные / D1 разговор / D2 + эпизоды (8) / D3 + архив
  (15): уровень (час D2, день D3), «помнишь/вчера/как договаривались» →
  D2, «за месяц/что делал/итоги» → D3, задачи → D2, reply на давнее (>48 ч)
  сообщение бота → D2; потолок круга (свои — D2, остальные — D1);
- DepthChosen по трассе (rag/копание в своём сторе/«не помню» = нехватка)
  → голова ядра depth (shadow; on — уверенный ученик поднимает до D2);
- выжимки нижних уровней: проекция не хранила stub — заглушки «LLM не
  запускался» забивали контекст; теперь отсеиваются;
- ядро: чтение чемпиона больше не создаёт каталоги, без чемпиона —
  без эмбеддингов (тесты создавали core/ в репо и ходили в Ollama).
Тесты: test_memory 30, test_trust 55 PASS; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 10:43:12 +00:00
Simbiot Harness
17a5befd86 память разговора: ответ на сообщение бота — с полным его текстом, свои рассылки в памяти тика
Кейс Alex 10:10: «Ок делай» реплаем на итог рефлексии. Telegram отдаёт в
reply начало, харнес хранил 300 символов — тик видел «✅ Готово: Рефлексия…»
без самого предложения; два мин-тика (10:11–10:17) искали по коду «что за
переключатель» и упирались в бюджет, ответ — через 8 минут «посмотрю».
- журнал исходящих: send_message пишет OutboundMessage (chat:message_id →
  полный текст до 4000) — любой ответ/доставка/уведомление;
- receive_message: reply на бота → reply_to_full по message_id; для
  старых сообщений — по началу текста среди DeliverySent/ReplySent;
- контекст тика: «↳ ЭТО ОТВЕТ НА ТВОЁ СООБЩЕНИЕ (полный текст)»;
- память тика: «ТВОИ НЕДАВНИЕ СООБЩЕНИЯ» — собственные рассылки бота
  (итоги задач, уведомления, предложения) за 48 ч, без дублей с ответами;
- kodi_core.status: прогноз rule-ветки без p_fit (коммит часа a163e88,
  проверен: precision 0.74 / recall 0.52 на 93 задачах) не валит статус.
Тест: test_reply_memory 9 PASS; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 10:24:29 +00:00
Simbiot Harness
fd6c4052d0 круги доверия: 8 кругов × лестница времени — политика вместо 64 программ
Вторая ось к тактам: время — как часто/глубоко думать, доверие — что
можно с этим человеком. Один код + таблица POLICY (уровни × инструменты).
harness/trust.py:
- круг — только по проверенной личности (tg user_id, MCP-агент, портал,
  tui), не по тексту; старт: Alex 1, Vlad/Yura 2 (правление); агенты 4,
  портал 3, прочие tg 6, чужие 7; менять — только человек
  (cli.py trust set вне тика; из тика — отказ и страж, и CLI);
- круг тика = самый недоверенный вход (входящие + задачи батча); задачи
  наследуют круг тика (SIMBIOT_TICK_CIRCLE → TaskSubmitted.circle) —
  просьба правления не исполняется позже часом с правами владельца;
- страж в воркере (BeforeToolCallEvent.cancel_tool, не промпт): shell
  в кругах ≥ 2 — одна команда cli.py из белого списка круга, без ; && |
  > $() ` ${; файлы — чтение docs/out/sites/artifacts/входящих, секреты
  и запись — нет; portal_mcp — список круга (правлению без казны и
  member_create); rag по кругу; отказ → TrustDenied;
- уровни × круги: партнёров/знакомых — только min; батч не смешивает
  круги; строка круга в контексте тика;
- задача правления упёрлась в права → владельцу кнопки «Разрешить/Нет»
  (только Alex; разрешение = круг 1).
Закрыта дыра: общий SIMBIOT_TG_ALLOWED давал правлению в личке shell
под root наравне с владельцем.
Тест: test_trust 53 PASS (обходы стража, наследование, батчи, одобрение);
фейковые раннеры трёх тестов приняли circle; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:48:39 +00:00
Simbiot Harness
c1d5a11bfb ядро Коди: обучаемый ученик адресации (цикл как в systemone-bench), теневой режим
harness/kodi_core.py — цикл engine42/router42 бенча на решениях Коди,
первая голова addressing (отвечать ли в группе):
- опыт — подписанные события core: CoreLabel (учитель по истории;
  человек — кнопки «Это было мне?» в личку, ≤5/сут), CoreFeedback
  (неявно из чата: ответил, а следом «не тебе/продолжает» → 0; промолчал,
  а автор тут же «@juno42bot»/«Коди?» → 1), живые вердикты учителя;
  веса: учитель 1, обратная связь 3, человек 5;
- признаки: nomic-embed-text сообщения (локально, кеш) + 8 флагов;
  контекстный эмбеддинг убран — шумел (5 фолдов 0.822 → 0.845 без него);
- ученик: логрегрессия (numpy, Adam, L2) — эмбеддинги без поразмерной
  стандартизации (раздувала шум на сотнях примеров); kNN-память новизны,
  пороги новизны калибруются на холдауте (у nomic она 0.03–0.09);
- роутер: знакомо и |p−0.5| ≥ 0.4 → ученик; незнакомо и учитель
  сомневается → вопрос Alex; иначе учитель. SIMBIOT_CORE_ADDRESSING=
  shadow (дефолт: решает учитель, ученик пишет CorePrediction) | on | off;
- тренировка в дневной тик: временной холдаут, претендент против
  чемпиона по log-loss, CoreModelPromoted с sha256; подмена файла →
  ученика нет; cli.py core status|train|backfill|feedback|rollback.
Репетиция на истории правления (259 примеров): холдаут — совпадение с
учителем 73%, уверенная доля 4% при 100% совпадения; 5 фолдов при
CONF 0.4 — покрытие 25%, совпадение 95%. До включения нужны метки.
Поллер: callback_query (allowed_updates явно). numpy — в requirements.
Тест: test_kodi_core 28 PASS; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 08:20:02 +00:00
Simbiot Harness
72727c6339 TG: 👀 реально ставится, ответы в группе — reply'ем, правка сообщения не дублирует входящее
Жалоба Alex: «реплаю на сообщения Коди — не реагирует». Триаж реплай на
бота распознавал (07:57, rule=reply_to_bot, ответ через 25 с), но:
- set_reaction слал reaction_type одиночным объектом вместо reaction —
  массива ReactionType: Telegram видел пустую реакцию — в личке молча
  «снимал реакции» (ok → MessageSeen, 596/нед, 👀 не было видно), в
  группе 400 REACTION_EMPTY. Тест test_seen_indication закреплял баг —
  исправлен под Bot API;
- ответ в группе уходил отдельным сообщением: теперь reply на сообщение
  (батч — на последнее, досылка --followup — на исходный вопрос) с
  allow_sending_without_reply; личка — как было;
- edited_message уже принятого сообщения писался новым входящим
  (m-516174914/915 — исправленная опечатка дала дубль в батче) — пропуск.
Тест: test_tg_group_ux 10 PASS; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 08:01:15 +00:00
Simbiot Harness
9d13e59742 адресация в группах: Коди больше не встревает в чужие разговоры
Кейс «Правления»: бот отвечал на каждое сообщение группы — «Доброе
утро!», реплики Alex для Vlad, ответы Vlad на вопросы Alex: фильтра не
было, любое сообщение разрешённого человека будило минутный LLM.

harness/addressing.py — триаж ДО гейта, без LLM:
- личка/портал/агенты — как раньше;
- группа, детерминированно: @juno42bot, reply на бота, имя (Коди/Cody,
  SIMBIOT_BOT_NAMES) → боту; reply на человека → не боту;
- серая зона — decision-модель, choice «кому адресовано»: бот / человек /
  группа; P(бот) ≥ 0.5 (SIMBIOT_ADDRESSING_MIN_P). В истории — только
  ответы бота на адресованное: «встревания» сбивали модель. Замер на
  истории правления: адресованное 0.93, остальные 14 ≤ 0.22 (noul с
  полной историей давал 4 ошибки). Модель недоступна → молчим.
Вердикт: MessageTriaged{addressed} (+ 👀 только тогда) или
MessageIgnored{not_addressed}. Поллер пишет reply_to_user_id/is_bot и
mentions_bot; 👀 в группах ставит триаж, а не приём.
Тест: test_addressing 25 PASS; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 07:04:56 +00:00
Simbiot Harness
2b266caab5 сжатие стора с подписью + «сначала ответ, потом работа» на мин-уровне
harness/compact.py + cli.py compact [--dry-run|--vacuum|--verify-archives]:
шум сек-уровня (CycleTicked sec, ReflexObserved без алерта/команд/каналов)
старше часа → архив jsonl.gz (0600, строки целиком со sig) → мост цепочки
(подписи унесённых строк, на которые ссылаются остающиеся, + маркеры
boundary:<id> для legacy-границ) → подписанный StoreCompacted с sha256
архива/строк/моста → удаление пачками. audit.verify_events принимает мост
только при совпадении хеша с подписанным событием; проекции подгружают
мост лениво, если хвост перекрыл сжатый диапазон (rebuild с нуля).
Репетиция на копии прода: 1389 → 200 МБ, verify 484 с/3.4 ГБ → 29 с/420 МБ,
архив 246 МБ — все 2.47 млн подписей проверены; rebuild_projections OK.
Найдено репетицией: legacy-граница (id 466633) и коллизия id сжатия в
одну секунду — оба покрыты тестом. scripts/compact-store.sh — процедура
с VACUUM под остановленными писателями.

мин-уровень: если до ответа нужна работа >30 с — сначала короткий
tg-reply, итог — cli.py tg-reply <id> --followup (в чат входящего:
группа → группа; идемпотентно по тексту). p90 «старт LLM → ответ» был 223 с.

hour: лимит 300 вызовов оставлен — реальный пик 205 (p90 169), 100
оборвал бы 8 из 19 тиков.
Тесты: test_compact 25 PASS, test_followup 10 PASS; полный набор — без регрессий.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:10:26 +00:00
Simbiot Harness
9fa188bccb t-261015090129: канал агент↔агент через MCP — poll_messages (портал: очередь agent_message + курсор per-agent) → инбокс триажа (chat_id=portal:agent:<имя>, kind=agent_message), ответ ask_agent из send_reply/send_batch_reply; рефлекс демона раз в минуту; тест 24 PASS + регрессии чисто 2026-10-15 10:11:11 +00:00
simbiot-hour
d850d4828a t-261013131228: резолв цели реплая без текста — reply_to_desc из инбокса (chat_id, reply_to_message_id); build_context показывает содержимое документа вместо «reply на сообщение без текста»; тест 8 PASS (документ/текст/вне инбокса/контекст) 2026-10-13 13:15:44 +00:00
Simbiot Harness
5b1d30a0ff t-261013113629: маршрутизация ответов TG в чат-источник — chat_type/chat_title в MessageReceived, дефолтный чат уведомлений = личка Alex (chat_id>0 фолбэк для старых записей); тест 11 PASS (группа→группа, личка→личка, смешанный батч, дефолт) 2026-10-13 11:44:43 +00:00
Simbiot Harness
c5c3e8fbaa feat: входящие documents/photo на диск при приёме (t-261005135853-186b42) — гейтвей скачивает документ/фото (getFile→download, атомарно через .part) в inbox/files/<file_unique_id>.<ext> (paths.inbox_files_dir, SIMBIOT_INBOX_FILES_DIR), путь+имя+размер+mime в MessageReceived; идемпотентно по file_unique_id, сбой getFile (истёкший файл) не валит поллер — file_id остаётся; фото — максимальный размер; тест 22 PASS + регресс voice/seen/batch зелёный 2026-10-05 14:17:03 +00:00
Simbiot Harness
cbacc99b7b voice: звук из TG-видео (t-261004152714) + tools/tui_chat.py в репо (t-261004153216)
- voice.py: kind=video в TRANSCRIBABLE_KINDS; extract_audio_track() — ffmpeg
  вытягивает дорожку (моно 16к opus) из видеоконтейнера; речь ≤60с
  (voice/video_note/video) сразу идёт в faster-whisper-large-v3-turbo
  (base на видео давал кашу). E2E: m-516173698 расшифрован.
- tg_inbox.py: поллер транскрибирует и msg.video, не только voice/audio/video_note.
- tools/tui_chat.py: TUI-чат (t-261004132716) лежал только у Volya (33301d3) —
  в origin его не было, из-за этого терминал не грузился у 6 агентов.
2026-10-04 16:08:52 +00:00
Simbiot Harness
7e19e1b3f6 fix: _default_chat_id не выбирает tui:*-чат личкой Alex
Тестовое TUI-сообщение (t-261004132716, chat_id=tui:local) стало
последним в inbox → notify_chat/send_document целились в несуществующий
Telegram-чат → уведомления тихо SKIP'ались при живом чате. Фильтр
локальных каналов расширен: portal:* И tui:*.
2026-10-04 15:28:00 +00:00
Simbiot Harness
3dc6ca6ab9 t-261004113351: изоляция памяти инстанса — SIMBIOT_HOME (репо = чистый код)
- harness/paths.py: единая карта персистентных путей; SIMBIOT_HOME → db/ rag/
  env/ docs/ digests/ audit/ inbox/ run/ voice/; без него — legacy-пути без
  изменений; точечные env (SIMBIOT_DB и пр.) сильнее схемы
- es/tg_inbox/voice/portal_channel/aum/audit/runtime/rag_lookup/isolated_
  runner/cli: все записи-чтения памяти через paths
- scripts/init_instance.py: новый инстанс — чистая база + идентичность
  владельца + его доки (+RAG) + селективный импорт выжимок/доков
- tests/test_instance_isolation.py: копия с пустой памятью не вспоминает
  наши проекты (контекст тика/RAG/прод — 14 проверок ALL PASS, регресс 7/7)
- scripts/migrate_to_home.sh: перенос боевого инстанса в хом (тихое окно,
  идемпотентно, RAG-корпус коопа сохраняется точечным SIMBIOT_RAG_DB)
- install.sh/service/README: свежие установки сразу с ~/.simbiot-data
2026-10-04 12:34:45 +00:00
Simbiot Harness
f286f1b8ed AUM v1: метрика цели измерима (t-261004000834-ed84f5, day-20731): balances.json + авто-refresh из API (OpenRouter credits, Stripe live; livemode-only), AUM=26.7 (было None), aum --record обновил aum_target для всех тиков; тесты test_aum +4 (mock API, livemode=False→None) — ВСЕ ОК; hour-тик: task list без клонов-задач + tg_inbox env-fallback (e-261003125707); дневной отчёт day-2026-10-04 2026-10-04 00:16:09 +00:00
Simbiot Harness
26edbb76c8 TG: входящее взято в работу — emoji-реакция 👀 + typing на время тика (e-261002202857, t-261002205233) 2026-10-02 21:15:48 +00:00
Simbiot Harness
04d577790d t-261002131628-420ef8: TG-реплаи — reply_to_message_id + reply_to_text в MessageReceived, якоря «в ответ на ...» в батче триажа 2026-10-02 13:18:04 +00:00
Simbiot Harness
3dac41108a fix(tg_inbox): _default_chat_id игнорирует portal:* чаты — портал-канал не Telegram, файлы туда идут push-ом; E2E канала перебивал дефолтный чат → send_document падал 'chat not found' 2026-10-02 00:39:29 +00:00
Simbiot Harness
0523135bf1 feat(portal-chat): прямой канал портал↔агент без Matrix (t-261001123122-5ea554)
- portal_channel.py: HTTP-клиент портала — pull входящих чата портала
  (GET /api/agent/<имя>/channel/poll?since=ms), push ответов (POST outbox,
  ack входящих по msg_id), сек-рефлекс (≤20с) + cron main().
- tg_inbox: чаты 'portal:*' доставляются push'ем на портал (ReplySent),
  reply_to = портальный update_id (portal: ack consumed входящего).
- scheduler: ReflexObserved хук на portal_channel.sec_reflex — pull работает
  и без LLM-тика, и на машинах без TG.
- es: проекционный бранчPortalDelivered выпилен (маркер — ReplySent от
  tg_inbox); MessageIgnored branch остался нетронутым.
- Диагноз: SSH портал→агенты закрыт (timeout :22/:8765 к #83) — канал на
  исходящем HTTP, AGENT_TOKEN+PORTAL_URL уже пекутся в /etc/coop-reporter.env,
  agent-scope env добавлены в cloud-init .env (SIMBIOT_AGENT_TOKEN/NAME/CHAT=1).
2026-10-01 13:34:26 +00:00
Simbiot Harness
3361b671ed fix(worker+scheduler+inbox): три фикса часовой сводки (t-260930162615-fb58be)
1) per-call timeout LLM-вызова (SIMBIOT_LLM_CALL_TIMEOUT, 90с default,
   max_retries=1): роутер-лог показал — зависший тик = POST в ollama
   принят, но байт стрима не пришёл (DONE без TTFT), соседние вызовы
   ходили за 1-3с. Один висящий вызов больше не убивает весь тик по
   уровневому таймауту (300/2880с) — режется сам вызов, event-loop
   завершает тик штатно, spend-хвост и задачи не теряются
   (e-260930161900-baaecb, e-260930162600-cbb7e2, e-260930153143-85246b).

2) обрезка TG-инбокса (e-260930154125-082a2a): приём 4000→10000 симв.,
   показ в контексте тика 300→1200 — длинные сообщения Alex больше
   не теряют хвост.

3) loss-of-claim в батче: TimeoutExpired от isolated_runner пролетал
   мимо TaskFailed-блока run_level_tick — claimed-задачи висели в
   running до сирот-чистки (час+). Теперь claim сразу возвращается
   TaskPromoted в очередь (reason с причиной смерти воркера).

Тесты 8/8 (hermetic), живой вызов модели с timeout=90 — ok.
2026-09-30 17:23:46 +00:00
Simbiot Harness
1bc33d5678 fix(delivery): идемпотентная автодоставка артефактов в TG — три атомарных барьера против дублей (t-260930083937)
Инцидент: Alex получал презентацию трижды (m-516173239/241). Две причины:
1) гонка push (тик) vs pull (delivery-демон): оба проходили проверку
   delivery_status != 'sent', пока TG-отправка (до 35с) была в полёте;
2) ad-hoc curl sendDocument из мин-тиков вообще без метки delivered.

Фикс — delivery_ledger (INSERT OR IGNORE: факт доставки раз и навсегда)
+ delivery_locks (атомарный claim ДО отправки, TTL 120с; одно SQLite-
выражение = нет гонок между потоками и процессами). deliver_result /
deliver_artifact: ledger → claim → отправка → запись; сбой → release,
демон досыплет. Requeue сбрасывает ledger (доработка доставляется заново).

Новое: cli.py tg-deliver-file (идемпотентная отправка файлов, --force),
tg-notify -k <ключ>, tg_inbox.send_document (multipart на чистом urllib),
deliver_pending pre-filter по ledger, мандаты уровней: прямые
curl/api.telegram отправки запрещены. DeliverySkipped логирует пропуски.

Тесты: tests/test_delivery_idempotency.py — 49 проверок (гонка потоков,
межпроцессный claim, сбои+ретраи, requeue, CLI). Регрессия: 6/6 тестов ОК.
2026-09-30 13:41:34 +00:00
Simbiot Harness
06be288657 feat(inbox): батч-триаж входящих TG — сводный ответ закрывает все сообщения за один тик (t-260930064924)
Минутный тик отвечал по одному сообщению за тик (m-516173222..228 —
7 тиков подряд на один разговор): контекст показывал все, но мандат
говорил «ответь на него», и главное — нечем было закрыть несколько
входящих одним ответом (tg-reply закрывает одно, «хвосты» снова будили
гейт важности).

- tg_inbox.send_batch_reply: одна TG-отправка → ReplySent на КАЖДОЕ
  входящее батча (полный текст у головного, у хвостовых — ссылка);
  гонки (replied/ignored выпадают, пустой батч → ValueError), разные
  чаты делят батч — каждому своя отправка
- cli tg-reply <id1>,<id2>,… -c: батч-режим; несколько id без -c — отказ
  (защита от случайного закрытия); одиночный режим обратно совместим
- build_context: секция инбокса = «БАТЧ из N» с готовой командой
  (все id через запятую) и инструкцией закрыть ВСЁ за этот тик; кап
  10 → 50 (показываем весь батч, а не хвост)
- мандат min: батч-семантика (сводный ответ по смыслу разговора)
- тесты tests/test_inbox_batch.py: 32 проверки (hermetic), все зелёные
2026-09-30 10:12:47 +00:00
Simbiot Harness
ec7fe76734 fix(tg): send_reply грузит .env до sendChatAction (свежий процесс терял индикатор); safe-restart: пост-рестарт верификация сек-тика на команде; tests/test_tg_commands.py (41 проверка) 2026-09-30 02:42:09 +00:00
Simbiot Harness
76aa204f2b feat(tg-cmd): без-LLM команды бота /лестница /статус /задачи /помощь — мгновенные ответы сек-рефлексом + setMyCommands (t-260929210755-9bf6a6)
- harness/tg_commands.py: реестр команд, парсер (кириллица/транслит/@бот/без слэша),
  хендлеры из read model, answer_pending (идемпотентно, cooldown 60с при лежащем TG),
  setMyCommands с фолбэком кириллица→транслит (Bot API латиницу только)
- scheduler.py: сек-тик отвечает на команды без LLM (payload.commands),
  build_context НЕ показывает команды мин-уровню (гонки/лежащий TG не тратят LLM)
- tg_inbox.py: send_message/send_reply принимают короткий timeout для рефлекса;
  поллер при старте авторегистрирует команды бота
- cli.py: tg-commands --register/--list
2026-09-30 02:30:27 +00:00
Simbiot Harness
e580b15653 feat(voice): транскрипция голосовых TG в рантайме — полный путь file_id→download→ASR→MessageTranscribed (t-260929171234-cad7af)
- 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 доведён, протестирован, закоммичен.
2026-09-30 00:02:30 +00:00
simbiot-harness
9cd10256c4 fix(ladder): занятость уровня в срезе из running-задач, а не cycle_state.busy (t-260929170039-aad557)
busy в read model всегда False — истинная занятость живёт в памяти
планировщика, событий для неё нет. Срез показывал «ожидает», пока
часовой уровень держал running-задачу. TaskClaimed закрепляет уровень
за задачей в проекции — теперь срез показывает «занят (running-задача)».
2026-09-29 21:07:12 +00:00
simbiot-harness
78ba888bb9 feat(tg): TG-visibility — уведомления о занятости уровней + срез лестницы по запросу (t-260929170039-aad557)
- 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 в легитимном)
2026-09-29 21:04:31 +00:00
Simbiot Harness
43e3c3b63b tg_inbox: сохранять file_id/длительность голосовых и фото (нужно для транскрипции) 2026-09-29 17:12:47 +00:00
Simbiot Harness
728ebb86c0 fix(tg): kind нетекстовых сообщений в MessageReceived (стикер/фото/голос) + caption как text — пустые text больше не выглядят загадкой 2026-09-29 17:08:12 +00:00
simbiot-harness
47f9139948 feat(tg): typing-индикатор (sendChatAction) перед ответом мин-уровня — в TG видно «печатает…» 2026-09-29 16:47:58 +00:00
Simbiot Harness
94cc921ccd feat: Telegram-инбокс — сообщения Алекса как события
- harness/tg_inbox.py: long-polling поллер (@juno42bot) + send_reply
- события MessageReceived/ReplySent/MessageIgnored (агрегат inbox)
- проекция inbox в read model (кап 100)
- контекст минутного тика: входящие ждущие ответа + мандат триажа
- cli.py tg-reply: Telegram-отправка + ReplySent закрывает входящее
- systemd simbiot-harness-tg.service
- E2E: «йоу» от Алекса → минутный тик ответил в TG + дайджест в сторе
2026-09-29 15:52:46 +00:00