simbiot-harness/scripts/migrate_to_home.sh
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

140 lines
7.3 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# ============================================================================
# Simbiot — перенос памяти инстанса из репо в SIMBIOT_HOME (t-261004113351).
#
# Репозиторий становится чистым кодом: ES-база, .env, ключи аудита, балансы,
# выжимки, штампы каналов переезжают в один каталог-хом (по умолчанию
# /var/lib/simbiot-harness). Идемпотентен: повторный запуск — SKIP уже
# перенесённого.
#
# БЕЗОПАСНОСТЬ: скрипт сам ждёт «тихого окна» (нет живых LLM-воркеров —
# паттерн scripts/safe-restart.sh), останавливает три сервиса харнеса,
# переносит файлы, добавляет SIMBIOT_HOME в systemd-юниты и обёртки,
# поднимает сервисы и проверяет здоровье. Откат: см. конец файла.
#
# scripts/migrate_to_home.sh [HOME] # по умолчанию /var/lib/simbiot-harness
# ============================================================================
set -u
REPO="$(cd "$(dirname "$(readlink -f "$0")")/.." && pwd)"
HOME_DIR="${1:-/var/lib/simbiot-harness}"
SERVICES="simbiot-harness.service simbiot-harness-tg.service simbiot-dashboard.service"
LOG="${SIMBIOT_MIGRATION_LOG:-/tmp/simbiot-migrate-to-home.log}"
MAX_WAIT="${SIMBIOT_MIGRATION_WAIT:-1800}"
PAT='/harness/_llm_worker\.py$'
log() { echo "[$(date -u '+%F %T')] $*" >> "$LOG"; echo "$*"; }
# ── 0) тихое окно: мигрировать можно только когда ни один тик не пишет в БД ─
deadline=$(( $(date +%s) + MAX_WAIT ))
while :; do
if ! pgrep -f "$PAT" > /dev/null; then
sleep 3
if ! pgrep -f "$PAT" > /dev/null; then
log "тихое окно поймано — начинаю миграцию в $HOME_DIR"
break
fi
fi
if [ "$(date +%s)" -ge "$deadline" ]; then
log "тихого окна нет ${MAX_WAIT}s — отмена (повторить позже)"
exit 0
fi
sleep 10
done
# ── 1) структура хома (audit НЕ создаём: туда переедет каталог целиком) ─────
mkdir -p "$HOME_DIR"/{db,env,inbox,digests,run,voice,docs/aum}
log "home создан: $HOME_DIR"
moved() { # mv если источник есть и цель отсутствует
[ -e "$1" ] || { [ -L "$1" ] && rm -f "$1"; return 0; }
if [ -e "$2" ]; then log "SKIP (цель есть): $2"; return 0; fi
mkdir -p "$(dirname "$2")"
mv "$1" "$2" && log "moved: $1 → $2"
}
copied() { # cp если источник есть (переносить нельзя: git-трекается)
[ -e "$1" ] || return 0
if [ -e "$2" ]; then log "SKIP (цель есть): $2"; return 0; fi
mkdir -p "$(dirname "$2")"
cp -a "$1" "$2" && log "copied: $1 → $2"
}
# ── 2) стоп сервисов (писателей больше нет — mv БД с WAL безопасен) ─────────
systemctl stop $SERVICES
log "сервисы остановлены: $SERVICES"
# ── 3) перенос памяти ───────────────────────────────────────────────────────
moved "$REPO/harness/harness.db" "$HOME_DIR/db/harness.db"
moved "$REPO/harness/harness.db-wal" "$HOME_DIR/db/harness.db-wal"
moved "$REPO/harness/harness.db-shm" "$HOME_DIR/db/harness.db-shm"
moved "$REPO/.env" "$HOME_DIR/env/.env"
moved "$REPO/.audit" "$HOME_DIR/audit" # ключи ed25519
copied "$REPO/docs/aum/balances.json" "$HOME_DIR/docs/aum/balances.json"
copied "$REPO/out" "$HOME_DIR/digests/out" # выжимки-файлы
copied "$REPO/portal/inbox/.channel-last" "$HOME_DIR/inbox/.channel-last"
for f in "$REPO"/harness/channel_*.json; do
[ -e "$f" ] && { cp -a "$f" "$HOME_DIR/run/" && log "copied: $f"; }
done
[ -f "$HOME_DIR/env/.env" ] && chmod 600 "$HOME_DIR/env/.env"
# ── 4) SIMBIOT_HOME в юнитах и обёртках ─────────────────────────────────────
# RAG-корпус кооператива (/root/rag/rag.db) — общая инфраструктура хоста,
# его индексируют и другие инструменты (board hook): основному инстансу
# оставляем точечное переопределение, иначе SIMBIOT_HOME уведёт поиск на
# пустой <home>/rag/rag.db (t-261004113351).
RAG_KEEP=""
if [ -e /root/rag/rag.db ]; then
RAG_KEEP="/root/rag/rag.db"
fi
for svc in $SERVICES; do
f="/etc/systemd/system/$svc"
[ -f "$f" ] || continue
if ! grep -q "^Environment=SIMBIOT_HOME=" "$f"; then
sed -i "/^\[Service\]/a Environment=SIMBIOT_HOME=$HOME_DIR" "$f"
log "юнит обновлён: $f (+SIMBIOT_HOME)"
fi
if [ -n "$RAG_KEEP" ] && ! grep -q "^Environment=SIMBIOT_RAG_DB=" "$f"; then
sed -i "/^Environment=SIMBIOT_HOME=/a Environment=SIMBIOT_RAG_DB=$RAG_KEEP" "$f"
log "юнит обновлён: $f (+SIMBIOT_RAG_DB=$RAG_KEEP)"
fi
done
systemctl daemon-reload
for w in "$REPO/bin/simbiot" /root/.local/bin/simbiot; do
[ -f "$w" ] || continue
if ! grep -q "SIMBIOT_HOME" "$w"; then
sed -i "3a export SIMBIOT_HOME=\"\${SIMBIOT_HOME:-$HOME_DIR}\"" "$w"
log "обёртка обновлена: $w"
fi
done
# ── 5) подъём и проверка здоровья ───────────────────────────────────────────
systemctl start simbiot-harness.service simbiot-harness-tg.service simbiot-dashboard.service
sleep 8
health="FAIL"
if systemctl is-active --quiet simbiot-harness.service \
&& [ -s "$HOME_DIR/db/harness.db" ] \
&& ! ls "$REPO/harness/harness.db" >/dev/null 2>&1; then
health="OK"
fi
log "health: $health (db: $(du -h "$HOME_DIR/db/harness.db" 2>/dev/null | cut -f1))"
# контрольный прогон CLI из хома (не должен пересоздавать репо-базу)
SIMBIOT_HOME="$HOME_DIR" "$REPO/venv/bin/python" "$REPO/cli.py" status >/dev/null 2>&1 \
&& log "cli status: OK" || log "cli status: FAIL"
[ -e "$REPO/harness/harness.db" ] && log "ВНИМАНИЕ: репо-база пересоздана чем-то!"
# отчёт + идемпотентное уведомление (не curl — защита от дублей в cli.py)
cat > "$HOME_DIR/migration-report.json" <<EOF
{"task": "t-261004113351-2858c1", "home": "$HOME_DIR",
"health": "$health", "ts": "$(date -u '+%F %T')"}
EOF
SIMBIOT_HOME="$HOME_DIR" "$REPO/venv/bin/python" "$REPO/cli.py" tg-notify \
"📦 Память харнеса изолирована в $HOME_DIR (репо = чистый код). Здоровье: $health" \
-k t-261004113351-migrated 2>/dev/null || true
log "миграция завершена: $health"
# ОТКАТ (если что-то не так): systemctl stop $SERVICES;
# mv "$HOME_DIR"/db/harness.db* "$REPO/harness/"; mv "$HOME_DIR/env/.env" "$REPO/.env";
# убрать Environment=SIMBIOT_HOME из юнитов; systemctl daemon-reload; start
exit 0