|
|
||
|---|---|---|
| artifacts | ||
| bin | ||
| design-plans | ||
| docs | ||
| harness | ||
| out | ||
| portal | ||
| scripts | ||
| sites | ||
| skills | ||
| tests | ||
| tools | ||
| video | ||
| ~ | ||
| .gitignore | ||
| architecture.html | ||
| cli.py | ||
| events.db | ||
| lab42-conditions.html | ||
| README.md | ||
| requirements.txt | ||
| simbiot-presentation.html | ||
| Studio_Participation_Agreement_2026-09.pdf | ||
| tasks.db | ||
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 sideharness/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
доработка доставляется снова. Формат: «✅ Готово: