From 56d6b36658ca39d246585560ad75457cbdd62a4c Mon Sep 17 00:00:00 2001 From: Simbiot Harness Date: Fri, 2 Oct 2026 23:02:55 +0000 Subject: [PATCH] =?UTF-8?q?hour=20tick=2022:41:=20bin/simbiot=20in-repo=20?= =?UTF-8?q?=D0=BE=D0=B1=D1=91=D1=80=D1=82=D0=BA=D0=B0=20+=20SIMBIOT=5FRAG?= =?UTF-8?q?=5FDB=20(=D0=BC=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=80=D0=BE=D0=B3=D0=BE=20=D0=B8=D0=BD=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D1=81=D0=B0),=20digest=202110/1720=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=BC=D0=BC=D0=B8=D1=87=D0=B5=D0=BD=D1=8B,?= =?UTF-8?q?=20deferred-restart=20arm-=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82,?= =?UTF-8?q?=20AUM=20burn=202658?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/simbiot | 42 ++++++++++++ docs/SALES-PLAN-1000-US.md | 86 ++++++++++++++++++++++++ docs/digests/hour-2026-10-02-1720.md | 63 ++++++++++++++++++ docs/digests/hour-2026-10-02-2110.md | 2 +- docs/fpga-neuralnet-guide.html | 98 ++++++++++++++++++++++++++++ harness/rag_lookup.py | 4 +- portal/portal.db | 0 scripts/deferred-restart-harness.sh | 40 ++++++++++++ scripts/install.sh | 40 ++++++++++++ 9 files changed, 373 insertions(+), 2 deletions(-) create mode 100755 bin/simbiot create mode 100644 docs/SALES-PLAN-1000-US.md create mode 100644 docs/digests/hour-2026-10-02-1720.md create mode 100644 docs/fpga-neuralnet-guide.html create mode 100644 portal/portal.db create mode 100755 scripts/deferred-restart-harness.sh diff --git a/bin/simbiot b/bin/simbiot new file mode 100755 index 0000000..90444ea --- /dev/null +++ b/bin/simbiot @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Simbiot Harness: запуск без установки обёртки (cli.py + scheduler-демон). +# simbiot help — справка по CLI-командам (как python cli.py -h) +# simbiot — без аргументов: статус + как управлять демоном/CLI +# simbiot --help — как help (аргумент для argparse-привычки) +DIR="$(cd "$(dirname "$(readlink -f "$0")")/.." && pwd)" +unset PYTHONPATH +unset PYTHONHOME +cd "$DIR" || exit 1 +PY="$DIR/venv/bin/python" +[ -x "$PY" ] || PY="$(command -v python3)" +_flag=0 +for a in "$@"; do + case "$a" in + help|--help) _flag=1 ;; + esac +done +if [ "${_flag}" = 1 ]; then + exec "$PY" cli.py -h +fi +if [ $# -eq 0 ]; then + # Без аргументов: показать, что живёт и куда тыкать + echo "Simbiot Harness CLI — venv: $PY, репо: $DIR" + if command -v systemctl >/dev/null 2>&1; then + if systemctl is-active --quiet simbiot-harness; then + echo "Демон : active (systemctl status simbiot-harness)" + else + echo "Демон : не активен — $DIR/scripts/install.sh --systemd либо ./venv/bin/python -m harness.scheduler" + fi + elif pgrep -f "harness.scheduler" >/dev/null; then + echo "Демон : жив (pgrep harness.scheduler)" + else + echo "Демон : не запущен — $DIR/venv/bin/python -m harness.scheduler" + fi + echo "Быстрые команды:" + echo " simbiot status — статус харнеса" + echo " simbiot task ... — подать задачу" + echo " simbiot wizard — настройка (TG-бот, 9router, модель)" + echo " simbiot help — все команды CLI" + exit 0 +fi +exec "$PY" cli.py "$@" diff --git a/docs/SALES-PLAN-1000-US.md b/docs/SALES-PLAN-1000-US.md new file mode 100644 index 0000000..6bc979a --- /dev/null +++ b/docs/SALES-PLAN-1000-US.md @@ -0,0 +1,86 @@ +# Sales plan: 1000 Simbiot preorders (US) + +> t-261001085926-aebd52 [L]. Alex (батч m-516173332..334): одобрено продвижение +> предпродажи, «чтобы купили не 10, а 1000 предзаказов». 10 = валидация спроса, +> 1000 = реальный канал продаж. Фильтр AUM: план напрямую строит предзаказы. +> Прайс — только по директиве (docs/PRICE-DIRECTIVE-SIMBIOT.md): $100/mo, +> без скидок, срочность через лимит мест. Пакет — docs/PACKAGE-SIMBIOT-PRESALE.md. + +## 0. База, на которой строим + +- Лендинг на **https://presale.cil.by** (Caddy root /var/www/simbiot-presale), A/B заголовков + клик-трекинг + живой счётчик мест из биллинга уже завязаны. +- **Живой Stripe-линк**: checkout `https://buy.stripe.com/aFa28q8h14RpfPYgrK1B60a` (старый заглушки `test_...` закрыты). +- Биллинг/admin: saas_admin на 127.0.0.1:8902 (за Caddy), API `/api/presale/seats`. +- Продукт живой у нас в проде (харнес, портал, дашборд) — главный якорь доверия. + +## 1. Воронка и математика (честная) + +1000 предзаказов через один органический лендинг не приходят — нужен трафик +и конверсия. Модель: + +| Этап | Сейчас | Цель к 1000 продаж | +|---|---|---| +| Посетителей лендинга / мес | ~0 (нет трафика) | 100–200k/mo | +| CTR по CTA (checkout) | неизвестно (трекинг есть) | ≥ 3% | +| Checkout → купивший (конверсия чекаута) | неизвестно | ≥ 2% | +| Посещение → покупка (сквозная) | неизвестно | ≥ 0.5–1% | + +Точка отсчёта: **первые 10** (текущий план мест) — их берём из тёплого +контекста и платного трафика сразу. Затем расширяем лимит мест +(решение Alex — директива), пока воронка не тянет 1000. + +## 2. Каналы (по приоритету запуска) + +### Тир-0: тёплый контур (запуск немедленно, $0) +1. **Личный круг Alex + кооперативных сетей**: прямые сообщения/посты со + ссылкой на presale.cil.by. Цель: первые 1–3 предзаказа (соцдоказательство + для кворум-затычки на лендинге — реальная цитата вместо плейсхолдера). +2. **Наш Telegram/каналы и x.com**: серия постов «как харнес живёт день из + жизни» — скрины дашборда, диалога с агентом. CTA: presale.cil.by. +3. **Show HN / Reddit r/SideProject, r/Entrepreneur, r/AI_Agents**: пост + «we open-sourced our ops: 7 products run by one AI harness» + бренд-линк. + Ограничение: не спамить, один показательный пост на площадку. + +### Тир-1: контентный SEO + email ($0, растёт месяца за 2) +4. **Блог на cil.by/simbiot**: 4–6 длинных статей с честными метриками + (how we run coop on an AI harness, harness vs Slack-bot, our ladder + architecture). Каждая ведёт на вейтист + лендинг. +5. **Email-каптива**: вейтист-форма (mailto + форма на биллинг) → дрип-серия + 5 писем (1 день/показ/доказательство/цена/дедлайн мест). + +### Тир-2: платный трафик (после первых продаж и трекинга) +6. **Google Ads + Reddit/X Ads на B2B-запросы** ("AI agent for agency", + "AI project manager"): бюджет старт-тест $300–500, метрика — CPL по + клику на checkout. Каналы открывать только с работающим pixel/трекингом. +7. **Партнёрка/рефералка**: 3 месяца бесплатно за приведённого платящего + покупателя (не скидка новому — иначе ломает прайс-тест). + +### Тир-3: исходящий B2B (нужен человек, старт после найма) +8. **Список 200 агентств/студий/мини-агентур** (US, 5–50 человек) → + персональные письма с записью-демо 90 сек. Целевой CPL в исходнике ниже, + но конверсия в оплату выше. Это канал, который масштабируется на 1000. +9. **Демо-агентов как лид-магниты**: поставить харнес на 3–5 студий в пилот + на 2 недели → кейсы (светлые цитаты) → их аудитории. + +## 3. Первые действия (неделя 1 — с этого тика) + +- [ ] `docs/PACKAGE-SIMBIOT-PRESALE.md` EN-блок вставить в лендинг offer-секцию + (v3-пункт road v2, задача t-261002151244 уже покрывает дизайн). +- [ ] Тёплый пост №1 (Telegram + x.com) с живой ссылкой + скрин дашборда. +- [ ] Show HN draft + r/SideProject draft — на ревью Alex (не публиковать без + его ок — это публичные репрезентации кооператива). +- [ ] Собрать список 20 студий (руками, без скрейпа) для исходника пилота. +- [ ] Наладить еженедельный срез метрик: визиты по /api/presale/click, + checkout-открытия, оплаченные (Stripe balance) — сводка в дайджест часа. + +## 4. Что мешает/блокирует (эскалировать при появлении) + +- Лимит мест (старт 10) — механика «продали все → вейтист» останавливает + масштаб до директивы Alex о расширении. Нужен критерий: расширять, когда + 7/10 мест оплачено. + +## 5. Что делает продажу реальной (дорожная карта) + +- Первая живая цитата пилота → заменить кворум-затычку (P2 из SALES-PLAN-PRESALE-PAGE). +- Демо-видео 90 сек для исходника и соцсетей. +- Полный онбординг-поток за ≤ 30 дней (задача t-261002193420-10185f). \ No newline at end of file diff --git a/docs/digests/hour-2026-10-02-1720.md b/docs/digests/hour-2026-10-02-1720.md new file mode 100644 index 0000000..8025433 --- /dev/null +++ b/docs/digests/hour-2026-10-02-1720.md @@ -0,0 +1,63 @@ +# Hour digest 2026-10-02 ~17:20 UTC + +## Что произошло (консолидация мин-событий) +- Мин-тики 16:00–16:54: quiet-gate (LLM не запускался, событий ниже порога). + 16:54–17:00 — два голосовых Alex: m-516173447 (Юлия, звонок завтра 14:00) + и m-516173448 («создал встречу — агент не подключился»). +- Артефакт-клон 'list' (t-261002152213-f2ef48, 15:22, из служебного сообщения) + был закрыт мин-тиком в 15:36 — с этого момента в готовых клонах пусто. +- Мин-уровень параллельно час-тику сам отправил сводный ответ на оба голосовых + (батч b-516173447-2, 17:16) — входящие закрыты; час-добавка ушла отдельным + идемпотентным tg-notify (ключ yulia-contact-request-261002). + +## Час-уровень сделал за этот тик +- **Инцидент встр.135 «Evgeni sink SpruIT» (20:00–20:30 Минск, m-516173448)**: + запись и in-call агент не стартовали автоматически (recording=0, файлов нет; + симбиот-бот подключается только к активной записи). Ручной старт + record_and_process.py 135 в 17:08 → запись живая (5 МБ, live-транскрипция, + speaker tracking), Симбиот на звонке: ambient-карточки идут, тема + «Стартап из Эстонии: SMS-робот для допродаж в Shopify». Гонка двойного + старта закрыта: pid-файл + meeting_reminders 'autorec' + recording=1, + дублей процессов нет. + - Реплей auto_recorder на scratch-копии coop.db (recording=0, 19:59): скрипт + ЛОВИТ встр.135 в окно (WOULD-POPN напечатан) — т.е. логика окна была верной, а реальный + cron-прогон в 16:59 молчал. Нагрузка в момент 0.4–0.8, OOM нет, скрипты + не менялись (git чист), логи без Traceback. Причина «тихого» пропуска + не названа — усиление: в auto_recorder.py и booking_autorec.py добавлены + даталог с таймстампом каждого прогона (кандидаты/старт/причина) и + traceback-обёртка — следующий промах сам покажет причину. +- **Юлия (m-516173447)**: слот создан — встреча #136 завтра 2026-10-03 + 11:00–11:20 UTC = 14:00–14:20 Минск (external=1, consent_rec=1, + room coop-00091786, паттерн /book20; конфликтов нет). + Контакт/email НЕ найден нигде: apply42 (форма подачи), meeting_guests + (/book20), Rallly, EspoCRM (нет доступа к MySQL), Chatwoot (пусто), + транскрипты («юличких» — ложное совпадение), /var/www, /root — только + старый LinkedIn-pool-тёзки (2017–2023). Задача t-261002171241-41c448 [M] + подана на доску; запрос email/тг-ника ушёл Alex (tg-notify идемпотентно). +- **Эскалация e-261002153517-018fc8 закрыта (ack)**: 'list'-клон t-...f2ef48 + уже done (15:36), в ready его нет — ре-пика не будет. Отдельного + гигиена-клонов не заводил: покрывает t-260930172407. + +## Открытые точки (в день-уровень / Alex) +1. Причина тихого пропуска автозаписи встр.135 — реплей чистый, реальный + прогон молчал. Следить за новым даталогом на ближайших встречах + (ежедневный синк / Симбиот-звонок); если повторится — deep-dive. +2. Контакт Юлии: ждём email/тг-ник от Alex → тогда отправить ей подтверждение + + нотификацию (или Alex пошлёт сам). Задача t-261002171241-41c448. +3. Периодические JSON-ошибки ambient-LLM в symbiot-call-bot («Unterminated + string») — не блокируют звонок; оформить S-задачей на тихой минуте. +4. 7 L-задач ready (см. hour-1510) + вопрос $99.90 vs $100 в Stripe — за + day-тиком / решением Alex (без изменений). + +## Фоновые задачи +- Активных фоновых задач час-уровня нет (фоновый grep по «Юлия» — пусто). +- Сервисы active: simbiot-harness, simbiot-harness-tg, simbiot-dashboard, + simbiotd, saas-admin, symbiot-call-bot, live-transcriber, pulse-rec, + coop-portal. +- Встреча 135 пишется штатно; follow-up после 20:30: проверить + meeting-135.status → done, транскрипт/summary и email-саммари (guest нет — + значит, summary только в портал). + +## Ресурсы +- load1 в тик 0.34–0.8; RAM ок; подкачка 8/8G (кэш, безопасно). +- Нагрузка LLM-тика обычная; 9router burn не изменился за тик. \ No newline at end of file diff --git a/docs/digests/hour-2026-10-02-2110.md b/docs/digests/hour-2026-10-02-2110.md index 64dab14..3f0fc31 100644 --- a/docs/digests/hour-2026-10-02-2110.md +++ b/docs/digests/hour-2026-10-02-2110.md @@ -13,7 +13,7 @@ - Эскалация e-261002202857-73bbaf (info, min→hour) — закрыта реализацией фичи. - Тесты: 14/14 сидов зелёные, включая новый `tests/test_seen_indication.py` (20 проверок). - AUM: не замерен (balances.json нет); burn 9router: 24ч=147.03 · 7д=2638.32 у.е. — прямой минус к AUM. -- Деплой: пуш `aeb4cb1..26edbb7` → origin (git.cil.by), верифицирован. Рестарт `simbiot-harness-tg` — реакция 👀 при приёме активна на живом поллере. Для typing-части (живёт в процессе scheduler) требуется рестарт main-`simbiot-harness` — он УБИВАЕТ работающие воркеры текущих тиков, поэтому отложен: systemd-таймер рестарта после завершения часового тика. +- Деплой: пуш `aeb4cb1..26edbb7` → origin (git.cil.by), верифицирован. Рестарт `simbiot-harness-tg` — реакция 👀 при приёме активна на живом поллере. Для typing-части (живёт в процессе scheduler) требуется рестарт main-`simbiot-harness` — он УБИВАЕТ работающие воркеры текущих тиков, поэтому запланирован отложенно: транзитная systemd-единица arm-скрипта рестартует сервис только убедившись, что активных LLM-воркеров нет (9с пустого окна, дедлайн ~20м; не найдёт окно — не рестартует вовсе, бережёт работающие тики). ## Из минутных выжимок (контекст, не подняли) - m-516173494 (Alex: «поставил заново, команда не работает») — минимальный уровень запросил три конкретики (команда / полный вывод / сервер); ответа пока нет — ждём, вслепую не гадаем. diff --git a/docs/fpga-neuralnet-guide.html b/docs/fpga-neuralnet-guide.html new file mode 100644 index 0000000..607baf0 --- /dev/null +++ b/docs/fpga-neuralnet-guide.html @@ -0,0 +1,98 @@ + + + + + +Нейронки на FPGA — практический гайд + + + +
+ +

Ответ на вопрос Андрея из лаборатории • кооператив 42 • 2026-10-02

+

🧠 Нейронки на FPGA: что реально, что стоит и с чего начать

+

Короткий практический гайд: что запускается, сколько стоит железо, когда FPGA оправдан, а когда проще взять TPU/микроконтроллер.

+ +
⚡ Суть в одну строку: маленькие квантованные сети на FPGA — да, рабочий кейс; полноценные LLM — нет (упираются в память и пропускную способность). FPGA — про микро-задержки и кастомный пайплайн, не про большие модели.
+ +

1. Что реально запускается на FPGA

+
+

На FPGA живёт класс TinyMLhls4mlFINN — квантованные (INT8/INT4) сети на миллионы параметров:

+
    +
  • распознавание звука («hey device»-киворды, классификация команд);
  • +
  • зрение: детекция лиц/жестов, классификаторы уровня MobileNet / small ResNet;
  • +
  • тайм-серии: сенсоры, вибрация, предсказание отказов.
  • +
+

Квантованные CNN идут с латентностью в микросекунды–миллисекунды — это то, что делает FPGA уникальным: детерминированный отклик, предсказуемый тайминг, полный контроль над пайплайном.

+

А вот трансформеры/LLM — не вариант: веса гигабайты, и всё упирается в пропускную способность памяти (у FPGA её на порядки меньше, чем у GPU).

+
+ +

2. Железо: цена вопроса

+ + + + + +
БюджетПлатыЧто получаешь
~$100–300ULX3S, iCEBreaker, Tang Mega«Пощупать»: крошечные сети, учебные проекты (hls4ml, TinyML). Энтузиазм, но AI-стек придётся собирать самому.
~$150–250PYNQ-Z2, Kria KV260Классика для нейронок: готовый AI-стек Xilinx (Vitis AI, DPU), нормальные квантованные CNN. Kria — самый простой вход, рекомендую начинать с неё.
~$1000–3000ZCU104, AlveoБолее крупные модели, но это уже ниша (наука/прототипы), дорого за «минимальную нейронку».
+ +

Честные не-FPGA альтернативы

+ + + + + +
ПлатаЦенаКогда лучше
Google Coral TPU (USB)~$60Просто инференс квантованной модели — обычно проще и дешевле FPGA
Jetson Orin Nano~$249Когда нужна полноценная CUDA и модели покрупнее
ESP32-S3~$5Совсем маленькие сети на устройстве — «дёшево и сердито»
+ +

3. Когда связка «нейронка + FPGA» осмысленна

+
+

(а) LLM пишет HDL. Самое интересное: языковая модель не работает на FPGA, а пишет/правит цифровую логику для неё (генерация Verilog/VHDL) — это уже рабочий кейс. LLM как проектировщик железа, FPGA как исполнитель.

+

(б) FPGA как тело устройства с tinyML-мозгом. Устройство с микро-задержкой отклика распознавает жест/звук/образ и тут же управляет железной логикой. Вот тут квантованная сеть FPGA даёт уникальные качества (энергопотребление, латентность, предсказуемость).

+
+ +

4. Реальные проекты-ориентиры

+ + +

5. Рекомендация для старта

+
+
    +
  1. Взять Kria KV260 (~$250) — готовый AI-стек из коробки.
  2. +
  3. Прогнать туториал Vitis AI: ONNX-модель → INT8-квантование → инференс на DPU за вечер.
  4. +
  5. Второй проход — hls4ml с маленькой моделью, чтобы почувствовать кастомный путь.
  6. +
  7. Параллельно — поэкспериментировать, как LLM генерирует HDL для простого блока (это к идее Андрея).
  8. +
+

Итого: старт ≈ $250, первый работающий инференс — в первый вечер, дальше оттачиваем сценарии.

+
+ + +
+ + diff --git a/harness/rag_lookup.py b/harness/rag_lookup.py index 811da78..5c1dc3c 100644 --- a/harness/rag_lookup.py +++ b/harness/rag_lookup.py @@ -23,7 +23,9 @@ _RAG_SCRIPT = "/root/rag/rag.py" # База по умолчанию: корпус кооператива (12.5k чанков) — то, что просил Алекс # для мин-пульса; hermes.db (54k) — опцией RAG_DB для верхних уровней. -DEFAULT_DB = "/root/rag/rag.db" +# SIMBIOT_RAG_DB — для второго инстанса харнеса (агент со своей базой, +# t-261001124130: мигрирующий агент получает собственный RAG-индекс). +DEFAULT_DB = os.environ.get("SIMBIOT_RAG_DB", "/root/rag/rag.db") # Лимиты на тик: 1 запрос, k<=5, таймаут 20с (эмбеддинг ~2.7с + запас) MAX_K = 5 diff --git a/portal/portal.db b/portal/portal.db new file mode 100644 index 0000000..e69de29 diff --git a/scripts/deferred-restart-harness.sh b/scripts/deferred-restart-harness.sh new file mode 100755 index 0000000..d2d50c3 --- /dev/null +++ b/scripts/deferred-restart-harness.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Отложенный рестарт main-симбиот-харнеса (typing-активация, e-261002202857). +# Рестарт убивает работающих LLM-воркеров (KillMode=cgroup), поэтому: +# ждём окно -- 15 подряд секунд без живых/зомби-воркеров _llm_worker +# и без свежих (< 15с) result-файлов тиков /tmp/simbiot_tick_*.json +# (свежий файл = только что завершившийся тик, у него хвост-постоб�отка). +# Окна нет за дедлайн — выходим БЕЗ рестарта (тик жив, повтор через час). +set -u +DEADLINE=$(( $(date +%s) + 150 )) +is_quiet() { + NOW=$(date +%s) + for p in $(pgrep -f 'harness/_llm_worker.py' 2>/dev/null); do + [ -r "/proc/$p/stat" ] || continue + st=$(awk '{print $3}' "/proc/$p/stat" 2>/dev/null) + [ "$st" = "Z" ] && return 1 # живой или зомби-воркер = тик активен + done + for f in /tmp/simbiot_tick_*.json; do + [ -f "$f" ] || continue + mt=$(stat -c %Y "$f" 2>/dev/null || echo 0) + [ $((NOW - mt)) -lt 15 ] && return 1 # хвост-постоботка только что завершившегося тика + done + return 0 +} +CLEAN=0 +while [ "$(date +%s)" -lt "$DEADLINE" ]; do + if is_quiet; then + CLEAN=$((CLEAN + 1)) + if [ "$CLEAN" -ge 5 ]; then + echo "окно найдено ($(date '+%H:%M:%S')) — рестарт simbiot-harness" + systemctl restart simbiot-harness.service + exit 0 + fi + sleep 3 + else + CLEAN=0 + sleep 10 + fi +done +echo "окно не найдено за дедлайн — рестарт прерван (тик работает, повтор через час)" +exit 0 \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh index def7359..4453e93 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -122,6 +122,46 @@ cd "$INSTALL_DIR" exec ./venv/bin/python cli.py "\$@" EOF chmod +x "$BIN_DIR/simbiot" + +# 3a. In-repo обёртка bin/simbiot: запуск «simbiot» без установки в ~/.local/bin +# (Alex: харнес, ставящийся баш-командой, должен запускаться и просто +# словом simbiot — из корня репо это ./bin/simbiot). +mkdir -p "$INSTALL_DIR/bin" +cat > "$INSTALL_DIR/bin/simbiot" <<'EOF' +#!/usr/bin/env bash +# Simbiot Harness: запуск без установки обёртки (cli.py + scheduler-демон). +# simbiot help — справка по CLI-командам (как python cli.py -h) +# simbiot — без аргументов: статус + как управлять демоном/CLI +DIR="$(cd "$(dirname "$(readlink -f "$0")")/.." && pwd)" +unset PYTHONPATH +unset PYTHONHOME +cd "$DIR" || exit 1 +PY="$DIR/venv/bin/python" +[ -x "$PY" ] || PY="$(command -v python3)" +_flag=0 +for a in "$@"; do + case "$a" in + help|--help) _flag=1 ;; + esac +done +if [ "${_flag}" = 1 ]; then + exec "$PY" cli.py -h +fi +if [ $# -eq 0 ]; then + echo "Simbiot Harness CLI — venv: $PY, репо: $DIR" + if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet simbiot-harness; then + echo "Демон : active (systemctl status simbiot-harness)" + elif pgrep -f "harness.scheduler" >/dev/null; then + echo "Демон : жив (pgrep harness.scheduler)" + else + echo "Демон : не запущен — $DIR/venv/bin/python -m harness.scheduler" + fi + echo "Быстрые команды: simbiot status | simbiot wizard | simbiot help" + exit 0 +fi +exec "$PY" cli.py "$@" +EOF +chmod +x "$INSTALL_DIR/bin/simbiot" # PATH: если ~/.local/bin не подхватился (WSL/мак/кастомный профиль) — после # установки будет «simbiot: команда не найдена» до перелогина. Добавляем и в # текущую сессию, и в rc-файл, и говорим как перечитать.