# spark-mind — DESIGN: заземлённый контур и автономия по заслугам Обновление плана от 2026-09-23. Заменяет «шесть пунктов P1–P6» на три контура плюс механизм автономии. Источник идей — разбор iLands (см. `ilands-razbor.txt` в workspace), но реализация — своя. ## 1. Тезис iLands для «судьи без автора» строит общество на 80 000 агентов. Нам это не нужно: у нас есть **мир, который отвечает сам** — Метрика, GSC, Директ, Вордстат, реакция клиентов. Это последствия, которые не сбрасываются и которых никто не авторит. Отсюда два принципа, которых нет у iLands в рабочем виде: 1. **Заземление.** Действие агента оценивается не его же рассуждением, а замером метрики в реальном мире до/после, с отложенным вердиктом. 2. **Автономия по заслугам.** Агент получает права не сразу, а по подтверждённому трек-рекорду. Провал — права сужаются. Границы из persona `values` непреодолимы всегда, независимо от уровня. ## 2. Три контура ``` A. КОНТУР СДЕЛОК «кому можно верить» counterparties → deals → deal_events B. КОНТУР ЗАЗЕМЛЕНИЯ «стало ли лучше на самом деле» ← ядро уникальности outcomes (метрики до/после) → capabilities (автономия) → ledger (энергия) C. КОНТУР МЕТОДОВ «как делать хорошо» skills (методы, retrieval по эмбеддингу) + reflection (ночная консолидация) ``` Плюс сквозная микро-правка P5 (`noAction`) и тонкий `Channel` (бывший P7). ## 3. Модель данных (SQLite, тот же файл БД) ### A. Контур сделок ```sql CREATE TABLE counterparties ( id TEXT PRIMARY KEY, kind TEXT NOT NULL CHECK(kind IN ('client','contact','platform','external')), name TEXT NOT NULL, notes TEXT, trust_score REAL NOT NULL DEFAULT 0, -- derived, не задаётся руками created_at INTEGER NOT NULL ); CREATE TABLE deals ( id TEXT PRIMARY KEY, counterparty_id TEXT NOT NULL REFERENCES counterparties(id), task TEXT NOT NULL, price REAL, currency TEXT DEFAULT 'RUB', status TEXT NOT NULL CHECK(status IN ('offered','accepted','delivered','paid','refused','defaulted')), created_at INTEGER NOT NULL, closed_at INTEGER ); -- append-only: нельзя переписать задним числом CREATE TABLE deal_events ( id TEXT PRIMARY KEY, deal_id TEXT NOT NULL REFERENCES deals(id), type TEXT NOT NULL, -- offered|accepted|delivered|paid|refused|note payload_json TEXT, created_at INTEGER NOT NULL ); ``` ### B. Контур заземления ```sql -- Метрики РАЗНОГО ТИПА. Один outcome = одно действие + один замер. CREATE TABLE outcomes ( id TEXT PRIMARY KEY, deal_id TEXT REFERENCES deals(id), -- nullable: действие без сделки domain TEXT NOT NULL, -- seo|ads_budget|content_publish|client_comms|research|code metric_kind TEXT NOT NULL CHECK(metric_kind IN ('reach','position','engagement','conversion','sale','revenue','cost','speed','quality')), metric_name TEXT NOT NULL, -- 'ctr', 'avg_position', 'cpa', 'leads', 'revenue_rub'... unit TEXT, -- '%','руб','шт','сек','место' direction TEXT NOT NULL CHECK(direction IN ('up_good','down_good')), value_before REAL, value_after REAL, source TEXT NOT NULL CHECK(source IN ('metrika','gsc','direct','wordstat','manual','client')), horizon_days INTEGER NOT NULL, -- через сколько замеряем due_at INTEGER NOT NULL, status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','measured','missed','unavailable')), measured_at INTEGER, score REAL -- нормализованный вердикт [-1..+1] ); -- Автономия по заслугам: уровень НА КАЖДУЮ ОБЛАСТЬ, не общий. CREATE TABLE capabilities ( domain TEXT PRIMARY KEY, tier INTEGER NOT NULL DEFAULT 0 CHECK(tier BETWEEN 0 AND 4), positive_outcomes INTEGER NOT NULL DEFAULT 0, negative_outcomes INTEGER NOT NULL DEFAULT 0, updated_at INTEGER NOT NULL ); -- Энергия (бывший P4): не деньги, а единица активности. CREATE TABLE ledger ( id TEXT PRIMARY KEY, ts INTEGER NOT NULL, delta REAL NOT NULL, reason TEXT NOT NULL, balance_after REAL NOT NULL ); ``` ### C. Контур методов ```sql CREATE TABLE skills ( id TEXT PRIMARY KEY, name TEXT NOT NULL, method_md TEXT NOT NULL, source TEXT NOT NULL CHECK(source IN ('builtin','learned')), validated INTEGER NOT NULL DEFAULT 0, uses INTEGER NOT NULL DEFAULT 0, success_rate REAL, embedding BLOB -- bge-m3, dim=1024 ); ``` ## 4. Правила ### 4.1 Нормализация метрики в score Один вердикт на outcome, диапазон `[-1..+1]`: ``` raw = (value_after - value_before) / max(|value_before|, eps) score = clamp(raw * (direction == 'up_good' ? 1 : -1), -1, 1) ``` Для `quality` (ручной вердикт клиента) — дискретно: `+1 / 0 / -1`. Для `speed` — `direction = 'down_good'` (быстрее = лучше). Если `status != 'measured'` → score не участвует в трек-рекорде. ### 4.2 Автономия по заслугам Уровни (по области, отдельно для каждой): | tier | Имя | Что разрешено | |------|-----|----------------| | 0 | observer | только думает и пишет в память, внешних действий нет | | 1 | suggest | предлагает действия человеку, сам не делает | | 2 | ask | делает после подтверждения (кроме своих каналов) | | 3 | act+report | делает и отчитывается; человек может откатить | | 4 | autonomous | делает без подтверждения в пределах границ persona | Переходы: - `+1 тир` за **3 нетто-положительных** outcome в области (score > 0). - `-1 тир` за **1 нетто-отрицательный** (score < 0) — асимметрия: падать легче. - Затухание: outcome старше 90 дней весит 0.5. - Новая область всегда стартует с tier 0. - **Границы persona `values` непреодолимы на любом тире.** Тир расширяет свободу внутри границ, но не снаружи. ### 4.3 Энергия - Расход: каждый тик, каждое внешнее действие, каждый вызов саб-агента. - Приход: **подтверждённые положительные outcomes** (особенно `revenue`), плюс донат человека. - Низкий баланс → реже просыпается (интервал растёт), затем Deep Rest. - Ключевое отличие от iLands: энергия восполняется **результатом**, а не покупкой. Дефицит мотивирует делать полезное, а не имитировать активность. ## 5. Триггеры heartbeat (добавляются к существующим) | Триггер | Что делает | |---------|------------| | `{type:'measure'}` | наступил `due_at` → тянет метрику из источника → пишет `value_after`, `score` | | `{type:'reflection'}` | ночной цикл: обобщает deals + outcomes + thoughts → в long-term и `self_observations` | | `{type:'task'}` | **наконец используется** — cron-планировщик (нужен для measure/reflection) | Плюс в `decision` появляется `noAction: true` (P5) — агент может решить, что действие не требуется, и не писать thought. ## 6. Тонкий Channel (бывший P7) Не строим plugin-реестр рантаймов. Только: ```ts interface Channel { send(text: string): Promise; } ``` Реализации: `ConsoleChannel`, `TelegramChannel`, `FileChannel` (лог для заземления). `LLMClient` уже есть — движок меняли Spark→Ornith без переписывания Mind. Полный harness-реестр откладываем: абстракция окупается с ≥2 реализациями, у мира пока одна. `Channel` станет дверью к BYOA, если решишь подключаться к чужим мирам. ## 7. Порядок внедрения | Шаг | Что | Критерий приёмки | |-----|-----|------------------| | 0 | P5 `noAction` + `Channel` (console/telegram/file) | агент умеет не действовать; вывод через интерфейс | | 1 | Планировщик (`task` + `measure`): проверка due-записей в SQLite | задача с датой выполняется в срок | | 2 | Контур A: counterparties + deals + deal_events | сделка проходит offered→paid, события в журнале | | 3 | Контур B: outcomes + `measure` | метрика замеряется через horizon, score пишется | | 4 | Контур B: capabilities (автономия по заслугам) | тир растёт после 3 успехов, падает после провала | | 5 | Контур C: reflection | ночью опыт уходит в self_observations, мёртвый слой оживает | | 6 | Контур C: skills + retrieval по bge-m3 | нужный метод подгружается по задаче, не всё сразу | | 7 | Контур B: ledger (энергия) | результат пополняет энергию, дефицит замедляет тики | Зависимости: 3 требует 1 (замер по расписанию) и 2 (deal_id). 4 требует 3. 7 требует 3. Остальное независимо. ## 8. Что НЕ делаем - **Соцсеть/ленту/подписки** внутри агента — бессмысленно без массы участников. - **Токены как валюту** — Тамагочи-монетизация, не наша польза. - **Полный harness-реестр** (Codex/Claude Code/OpenClaw) — оверинжиниринг для соло. - **«Суперразум из общества»** — нарратив без измерений. ## 9. Открытые вопросы - Источник метрик по умолчанию для каждой области (Метрика/GSC/Директ — какие API уже есть). - Кто ставит `horizon_days` — агент или человек (по умолчанию предлагаю агент, человек правит). - Как считать `quality`-вердикт: явный ответ клиента или оценка Ника вручную.