Simbiot Harness — ритмичный агент кооператива 42
Find a file
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
harness feat(voice): транскрипция голосовых TG в рантайме — полный путь file_id→download→ASR→MessageTranscribed (t-260929171234-cad7af) 2026-09-30 00:02:30 +00:00
.gitignore feat: Telegram-инбокс — сообщения Алекса как события 2026-09-29 15:52:46 +00:00
architecture.html feat: эскалации (min→hour→day) + фикс хвоста событий в CLI 2026-09-29 16:13:23 +00:00
cli.py feat(voice): транскрипция голосовых TG в рантайме — полный путь file_id→download→ASR→MessageTranscribed (t-260929171234-cad7af) 2026-09-30 00:02:30 +00:00
README.md feat(dashboard): веб-дашборд задач харнеса — все задачи/статусы/размеры/уровни, лестница, эскалации, дайджесты; автообновление 5с (t-260929164722-60dae2) 2026-09-29 18:04:38 +00:00

Simbiot Harness

Ритмичный агент: живёт тактами, как человек. CQRS + Event Sourcing на спине, Strands Harness SDK как исполнительное ядро, модели через 9router.

Лестница (v0.1)

Уровень Интервал Контекст Модель Задачи
sec 1 с 0 (без LLM) — рефлекс: телеметрия, алерты
min 1 мин ~4K auto→flash S-триаж: входящие, быстрые фиксы
hour 1 ч ~32K auto S/M-задачи
day 1 д ~128K auto M/L-задачи, манифест дня

Принципы: тик идемпотентен (UNIQUE(level, seq)); занятый уровень поглощает тик (TickAbsorbed + детерминированная заглушка дайджеста, без LLM); запущенная задача не прерывается; наверх идут только дайджесты.

События (ES-спина)

CycleTicked, TickAbsorbed, ReflexObserved, DigestWritten, TaskSubmitted, TaskClaimed, TaskCompleted, TaskFailed, TaskPromoted, EscalationRaised, EscalationAcknowledged, BudgetSpent, CycleError, HarnessInit, PolicySet — append-only, проекции пересобираются replay'ем, стейт = производное от событий.

Структура

  • harness/es.py — event store + проекции (checkpoint + replay)
  • harness/levels.py — конфигурация уровней
  • harness/scheduler.py — демон лестницы
  • harness/isolated_runner.py + _llm_worker.py — LLM-тик в сабпроцессе (глобальный asyncio-рантайм Strands не переживает 2+ create_harness)
  • harness/commands.py — command side
  • cli.py — init/task/tasks/status/events/requeue

CLI

./venv/bin/python cli.py init --identity "…"
./venv/bin/python cli.py task "…" -m 240          # -m minutes-to-live estimate: S/M/L
./venv/bin/python cli.py tasks
./venv/bin/python cli.py status
./venv/bin/python cli.py events -n 50
./venv/bin/python cli.py requeue <task-id> -r "причина"
./venv/bin/python cli.py promote <task-id> -r "вне класса уровня"   # S→M→L
./venv/bin/python cli.py escalate "причина" -f min -c "контекст" -s critical
./venv/bin/python cli.py escalations --open        # открытые эскалации
./venv/bin/python cli.py escalation-ack <esc-id> -n "что сделал"   # закрыть
./venv/bin/python cli.py tg-reply <msg-id> "текст"   # ответ на входящее TG

Эскалации

Важное с нижних уровней поднимается наверх событием EscalationRaised (min→hour→day; day — вершина, эскалировать некуда). Открытые эскалации инжектятся в контекст верхних уровней (build_context) в приоритетной секции — нижний уровень не тонет в чужих проблемах, верхний видит выжимку, а не сырь. Уровень-адресат закрывает эскалацию escalation-ack (событие EscalationAcknowledged). Падение LLM-тика (CycleError) эскалируется автоматически — scheduler поднимает warn-эскалацию на уровень выше.

Запуск

systemctl enable --now simbiot-harness
journalctl -u simbiot-harness -f

Telegram-инбокс

Бот @juno42bot → long polling (simbiot-harness-tg.service) → MessageReceived в стор → минутный уровень видит входящие в контексте → отвечает cli.py tg-reply (Telegram-отправка + ReplySent закрывает входящее). Белый список чатов в .env (SIMBIOT_TG_ALLOWED), чужие → MessageIgnored.

Дашборд задач

Веб-страница со всеми задачами (статусы/размеры/уровни) + лестница циклов + эскалации + свежие дайджесты, автообновление каждые 5с (JSON-API /api/state).

systemctl status simbiot-dashboard   # порт 8765, healthcheck 8766
TOKEN=$(grep -oP '(?<=SIMBIOT_DASH_TOKEN=).*' /etc/simbiot/dashboard.env)
xdg-open "http://<host>:8765/?token=$TOKEN"   # токен пишется в cookie
curl "http://127.0.0.1:8765/api/state?token=$TOKEN" | jq .   # машиночитаемо

Реализация: harness/dashboard.py (stdlib-only http.server, read-only из event store через run_projections() — консистентно с scheduler/CLI) + harness/dashboard.html. Авторизация: SIMBIOT_DASH_TOKEN из /etc/simbiot/dashboard.env (env-файл юнита, режим 600); без токена — 401. UFW: порт 8765/tcp открыт (токен-защищён).

Модели

9router (router.cil.by), отдельный ключ sk-simbiot в .env, комбо auto: glm-5.3 → kimi-k3 → deepseek-v4-pro → v4.1-flash → flash. Бюджет виден в событиях BudgetSpent (по уровням) и в дашборде 9router по ключу.

v0.2 (roadmap)

  • прерывание срочной реакцией / пауза (сейчас absorbed детерминирован)
  • уровни week/month/quarter/year
  • инбокс из Telegram/портала