Simbiot Harness — ритмичный агент кооператива 42
Find a file
2026-10-09 16:12:04 +03:00
artifacts session_productize: 5-й тик — product_create всё ещё 500, карточка id 13 жива (t-261009110039) 2026-10-09 15:04:20 +03:00
bin hour tick 22:41: bin/simbiot in-repo обёртка + SIMBIOT_RAG_DB (миграция второго инстанса), digest 2110/1720 закоммичены, deferred-restart arm-скрипт, AUM burn 2658 2026-10-02 23:02:55 +00:00
design-plans skills/ui: вендор ui-skills (improve-ui, baseline-ui, a11y/metadata/motion-fixes) + frontend-design (anthropic) + improve-animations (emilkowalski) с атрибуцией; design-plans: improve-ui аудит simbiot.cil.by (P0 noscript-reveal, P1 focus/og, P2 reduced-motion — фиксы применены и задеплоены) 2026-10-02 22:32:23 +00:00
docs market simulation: logit конкуренция + сегменты + сценарии входа, MC 400 trials, E[dAUM] по сценариям + чувствительность (t-261009123019-a32bb3) 2026-10-09 16:12:04 +03:00
harness feat(scheduler): fetch origin + детектор дрейфа репо в дневном тике (t-261007082307-2e2294) — _repo_sync_check: git fetch + behind/ahead замер RepoSynced (1/день, дедуп), эскалация при behind>0 два дня ПОДРЯД (счётчик из истории стора — рестарт демона не сбрасывает); fetch-fail фиксируется честно (behind=unknown), тик не валит; порог SIMBIOT_REPO_SYNC_MAX_AGE_DAYS (default 2); тест 17 проверок hermetic (git-песочница), весь сюит 20/20 зелёный; живой прогон: behind=0 ahead=13, baseline записан 2026-10-08 10:32:05 +03:00
portal hour tick 22:41: bin/simbiot in-repo обёртка + SIMBIOT_RAG_DB (миграция второго инстанса), digest 2110/1720 закоммичены, deferred-restart arm-скрипт, AUM burn 2658 2026-10-02 23:02:55 +00:00
scripts market simulation: logit конкуренция + сегменты + сценарии входа, MC 400 trials, E[dAUM] по сценариям + чувствительность (t-261009123019-a32bb3) 2026-10-09 16:12:04 +03:00
sites/landing landing(sites): аудит-фиксы конверсии (t-261008082527-ae7b47): CTA-петля → presale.cil.by (живой Stripe, paid=1), social proof из стора (580k+ подписанных событий, 280k+ sec-тиков, 1 платник), contact-hint кликабелен (портал), FAQ первый открыт, canonical/og:url → simbiot.cil.by; проверено: HTML-валидатор 0 ошибок, якоря целы, туннель отдаёт обновлённую версию 2026-10-08 12:12:58 +03:00
skills merge origin/master (32 коммита портального инстанса) + burn-fallback в смерженном aum.py 2026-10-07 11:18:05 +03:00
tests feat(scheduler): fetch origin + детектор дрейфа репо в дневном тике (t-261007082307-2e2294) — _repo_sync_check: git fetch + behind/ahead замер RepoSynced (1/день, дедуп), эскалация при behind>0 два дня ПОДРЯД (счётчик из истории стора — рестарт демона не сбрасывает); fetch-fail фиксируется честно (behind=unknown), тик не валит; порог SIMBIOT_REPO_SYNC_MAX_AGE_DAYS (default 2); тест 17 проверок hermetic (git-песочница), весь сюит 20/20 зелёный; живой прогон: behind=0 ahead=13, baseline записан 2026-10-08 10:32:05 +03:00
tools voice: звук из TG-видео (t-261004152714) + tools/tui_chat.py в репо (t-261004153216) 2026-10-04 16:08:52 +00:00
~/.ssh merge origin/master (32 коммита портального инстанса) + burn-fallback в смерженном aum.py 2026-10-07 11:18:05 +03:00
.gitignore t-261004113351: изоляция памяти инстанса — SIMBIOT_HOME (репо = чистый код) 2026-10-04 12:34:45 +00:00
architecture.html feat: эскалации (min→hour→day) + фикс хвоста событий в CLI 2026-09-29 16:13:23 +00:00
cli.py merge origin/master (32 коммита портального инстанса) + burn-fallback в смерженном aum.py 2026-10-07 11:18:05 +03:00
events.db feat(tg-cmd): без-LLM команды бота /лестница /статус /задачи /помощь — мгновенные ответы сек-рефлексом + setMyCommands (t-260929210755-9bf6a6) 2026-09-30 02:30:27 +00:00
lab42-conditions.html t-261002131628-420ef8: TG-реплаи — reply_to_message_id + reply_to_text в MessageReceived, якоря «в ответ на ...» в батче триажа 2026-10-02 13:18:04 +00:00
README.md t-261004113351: изоляция памяти инстанса — SIMBIOT_HOME (репо = чистый код) 2026-10-04 12:34:45 +00:00
requirements.txt t-261002193628-1d1e5f: установка одной командой + визард первого запуска 2026-10-02 19:52:19 +00:00
simbiot-presentation.html feat(gate): гейт важности LLM-тика по per-level порогу + model в событиях 2026-09-30 08:29:54 +00:00

Simbiot Harness

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

Установка одной командой (t-261002193628-1d1e5f, как hermes)

curl -fsSL https://raw.cil.by/simbiot/install.sh | bash

Что делает scripts/install.sh: клонирует репо в ~/simbiot-harness, создаёт venv (Python 3.11+), ставит зависимости, кладёт обёртку ~/.local/bin/simbiot (чистый env: unset PYTHONPATH/PYTHONHOME → exec venv/bin/python cli.py), тихо инициализирует стор и проверяет simbiot status. Флаги: --dir DIR, --repo URL, --wizard / --no-wizard, --systemd (юнит, только root), -q (тихо).

Если в каталоге установки остался битый venv (python без pip — частый кейс WSL/старых клонов), скрипт пересоздаёт его и ставит зависимости (при недоступном ensurepip — системным pip3 в site-packages venv). В конце установки предлагается следующий шаг: портал https://cil.by — залогиниться и взять ключ API, затем simbiot wizard --router-key <КЛЮЧ>.

Первый запуск — визард настройки (токен TG-бота, ключ 9router, модель):

simbiot wizard                # интерактивно
simbiot wizard --noninteractive --router-key KEY --model auto

.env в корне репо читается стартапом (SIMBIOT_TG_TOKEN, SIMBIOT_TG_ALLOWED, ROUTER_KEY, SIMBIOT_MODEL и др.); в systemd-режиме scripts/simbiot-harness.service подхватывает его сам.

Главная цель (фиксация Alex, 2026-09-30)

Метрика харнеса — максимизация долгосрочной AUM (доход/ресурс всех проектов кооператива в длинном горизонте). Главный вопрос к любому уровню и любой задаче: «добавит ≥1% к AUM в горизонте год+?» — что приносит короткий доход, но съедает долгосрочную базу, приоритет ниже. На этой цели стоит автоприоритизация доски задач (t-260929161138; уточнение автоприоритизации день+час — t-260930153845, задача e-260930161330).

Механика (t-260929161138, docs/aum.md): cli.py aum --record — снапшот метрики (AUM из docs/aum/balances.json + burn 9router за сутки/неделю) → событие AumMeasured → policy.aum_target → «ЦЕЛЬ (AUM)» инжектится в контекст каждого тика. Пилот петли оптимизации (симуляции + генетический отбор конфигураций burn, отчёт-адвокат): cli.py aum-pilot — песочница, без авто-применения.

Криптоаудит (t-260930083716)

Каждое событие подписывается при записи приватным ключом харнеса (ed25519, .audit/ed25519.key 0600), события сцеплены по prev_sig (тампер-цепочка); команды CLI — конверты audit-command/verify-command; проекции отвергают подделанный хвост, полный аудит — cli.py verify (выход 0/2), публичный ключ — cli.py audit-key / .audit/ed25519.pub. Подробно: docs/audit.md.

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

Уровень Интервал Контекст Модель Задачи
sec 1 с 0 (без LLM) — рефлекс: телеметрия, алерты
min 1 мин 256K auto (effort low) S-триаж: входящие, быстрые фиксы
hour 1 ч 512K auto (medium) S/M-задачи, дайджест часа
day 1 д 1M auto (high) M/L-задачи, манифест дня

Конфиг согласован Алексом (e-261001082710): min 256k → hour 512k → day 1M (ctx_tokens в harness/levels.py); week/month/quarter/year — в roadmap v0.2.

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

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

CycleTicked, TickAbsorbed, ReflexObserved, DigestWritten, TaskSubmitted, TaskClaimed, TaskCompleted, TaskFailed, TaskPromoted, TaskAwaitDelivery, DeliverySent, InitiativeSent, 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
  • harness/tg_commands.py — без-LLM команды бота (сек-рефлекс)
  • harness/paths.py — карта персистентных путей (SIMBIOT_HOME)
  • cli.py — init/task/task-await/tasks/status/events/requeue

Изоляция памяти инстанса — SIMBIOT_HOME (t-261004113351)

Память агента — данные, не код: при переносе инстанса другому владельцу (мультитенантность) он не должен «думать» чужими проектами. Всё, что живёт дольше процесса — ES-база, RAG-индекс знаний, .env, ключи аудита, выжимки, штампы каналов, доки инстанса — размещается в одном каталоге-хоме, репо остаётся чистым кодом. Свежие установки: ~/.simbiot-data (install.sh проставляет в обёртку и systemd-юнит автоматически).

SIMBIOT_HOME=/path/to/home venv/bin/python cli.py status
файл назначение
<home>/db/harness.db ES-база (события, проекции, delivery-леджер)
<home>/rag/rag.db RAG-индекс знаний инстанса
<home>/env/.env секреты (токены, ключи роутера), 0600
<home>/docs/ проектные документы владельца (aum/balances.json)
<home>/digests/ файлы-выжимки уровней
<home>/audit/ ключи крипто-аудита ed25519
<home>/inbox/, <home>/run/, <home>/voice/ каналы, штампы, кэш ASR

Приоритет: точечная env (SIMBIOT_DB, SIMBIOT_RAG_DB, …) → SIMBIOT_HOME → legacy-пути из корня репо (обратная совместимость: не задан SIMBIOT_HOME — всё работает по-старому).

Новый инстанс (например, для Юры): scripts/init_instance.py — чистая база + идентичность владельца + его доки (+RAG-индексация) + опциональный селективный импорт выжимок/доков из инстанса-источника. Тест изоляции: tests/test_instance_isolation.py (поднять копию с пустой памятью — контекст тика и RAG не содержат чужих проектов, 14 проверок). Перенос существующего инстанса в хом: scripts/migrate_to_home.sh (ждёт тихое окно без LLM-воркеров, идемпотентен).

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 task "…" -a              # автодоставка результата в TG при готовности
./venv/bin/python cli.py task-await <task-id>     # пометить существующую: доставить в TG
./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
# батч-режим (t-260930064924): один сводный ответ закрывает несколько входящих
./venv/bin/python cli.py tg-reply m-1,m-2,m-3 -c "текст"   # ReplySent на каждое, одна отправка
# идемпотентные уведомления/файлы (t-260930083937): повтор — SKIP, дублей в чат нет
./venv/bin/python cli.py tg-notify "текст" -k <ключ>
./venv/bin/python cli.py tg-deliver-file <путь> -c "подпись" [--force]

Автодоставка артефактов (t-260929205927)

Задача, заказанная из TG (cli.py task -a / task-await), помечается TaskAwaitDelivery. При завершении (TaskCompleted) результат (answer) уходит в чат сам — DeliverySent, без повторного запроса. Push в тике (сразу после завершения) + pull-страховка (delivery-демон каждые 15с: досылает недоставленное, если тик умер между завершением и отправкой). Идемпотентно: один раз доставлено — повторно не шлётся; после requeue доработка доставляется снова. Формат: «✅ Готово: