Архитектура эволюционирующего интеллекта
Phase 21.5–40.12 — Самосовершенствующаяся система скиллов для Arc OS. Статус: Production-ready. Sage Worker (автономное улучшение) + бенчмарки (A/B тестирование) + Marketplace Discovery + семантический поиск NotebookLM.
Обзор
Arc OS работает на федеративной архитектуре ботов, где дочерние боты проксируют сообщения пользователей в Claude CLI. Phase 21.1 ввела отслеживание качества (логи выполнения, кнопки обратной связи). Phase 21.5 замыкает петлю: система теперь валидирует собственный вывод, запоминает исправления, фокусирует контекст и автономно предлагает улучшения.
Семь столпов образуют слой интеллекта:
Сообщение пользователя
│
├─► Context Router ──► SKILLS_HINT (топ-5 релевантных скиллов)
│
├─► Learnings ──► блок LEARNINGS (прошлые исправления)
│
▼
buildGsdPrompt() ──► Claude CLI ──► Ответ
│
├─► Binary Evals ──► Warning-сноски
│
└─► Quality Tracker ──► Метрики
│
Nightly Improve ──► Одобрение CEO
Столп 1: Binary Eval Engine
Модуль: shared/evals.ts
Файлы спеков: skills/<name>/<name>.evals.json
Что делает
Каждый скилл может объявлять правила валидации в JSON-файле. После того как Claude генерирует ответ, eval engine проверяет его по всем применимым правилам. Провалы дают неблокирующие warning-сноски, добавляемые к сообщению в Telegram.
Типы правил
| Тип | Проверяет | Пример использования |
|---|---|---|
string_contains |
Ответ содержит буквальную строку | Убедиться, что JSON-вывод имеет поле "verdict" |
string_not_contains |
Ответ НЕ содержит строку | Заблокировать --force в инструкциях git |
regex_match |
Ответ соответствует regex-паттерну | Убедиться, что аудит системы упоминает disk/RAM/CPU |
regex_not_match |
Ответ НЕ соответствует regex | Предотвратить паттерны утечки учётных данных |
max_length |
Длина ответа <= N символов | Поддерживать краткость вывода |
min_length |
Длина ответа >= N символов | Обеспечить содержательные ответы |
Уровни серьёзности
- warning: Показывается как
⚠️в сноске. Указывает на проблему качества. - info: Показывается как
ℹ️в сноске. Информационный, некритический.
Как eval'ы влияют на метрики
Результаты eval'ов логируются вместе с событиями качества. Когда nightly improvement loop обнаруживает скилл с низким процентом успеха, паттерны провала eval'ов помогают определить корневую причину без AI-анализа.
Пример eval-файла
{
"version": 1,
"skill": "code-review",
"rules": [
{ "id": "cr-001", "name": "Must return JSON verdict", "type": "string_contains", "value": "\"verdict\"", "severity": "warning" },
{ "id": "cr-002", "name": "No console.log debug", "type": "regex_not_match", "pattern": "console\\.log\\(", "severity": "warning" }
]
}
Принцип проектирования
Вдохновлён фреймворком eval'ов Anthropic's Skill Creator: декларативные утверждения о выводах, без AI в петле валидации. Бинарный pass/fail устраняет неоднозначность.
Столп 2: Context Router
Модуль: shared/context-router.ts
Источник данных: skills/_registry.json (поля triggers + keywords)
Что делает
Перед построением GSD prompt роутер оценивает каждый зарегистрированный скилл относительно сообщения пользователя. Топ-5 совпадений вставляются как блок SKILLS_HINT, настраивая Claude фокусироваться на релевантных возможностях.
Алгоритм скоринга
Для каждого скилла:
score = 0
для каждого trigger: если сообщение содержит trigger → score += 2
для каждого keyword: если сообщение содержит keyword → score += 1
Сортировать по score DESC → взять топ 5
Trigger-совпадения дают больше очков, потому что trigger'ы — явные сигналы вызова (напр., "review", "deploy"). Keyword'ы обеспечивают более широкое семантическое соответствие (напр., "OWASP", "Docker").
Почему advisory, а не фильтрация
Роутер только advisory. Claude CLI всё равно загружает все скиллы через CLAUDE.md. Причины:
- Безопасность: жёсткая фильтрация через
--allowedToolsили мутации симлинков рискует сломать работающую сессию при неверной классификации сообщения роутером. - Стабильность: никаких мутаций файловой системы на работающем процессе.
- Деградация без критического отказа: если роутер падает, у Claude всё ещё есть полный доступ к скиллам.
Экономия контекстного окна
Без роутера все 23 скилла конкурируют за внимание в prompt'е. Блок SKILLS_HINT говорит Claude "фокусируйся на этих 3-5" — снижая нерелевантную активацию скиллов и удерживая ответы по теме. Это контекстное прайминирование, а не сокращение контекста.
Столп 3: Reflect Loop (Persistent Learnings)
Модуль: shared/learnings.ts
Хранение: {PROJECT_CWD}/learnings.md
Что делает
Когда CEO нажимает "Fix It" или "👎", система фиксирует правило обучения и сохраняет его в markdown-файл. При каждом последующем сообщении накопленные learnings вставляются в GSD prompt как блок LEARNINGS.
Pipeline: событие → обучение
CEO нажимает 🛠️ Fix It
│
├─► addLearning(source: "fixit", rule: "Fix requested for: <context>")
│
└─► projectLearnings перезагружаются с диска
CEO нажимает 👎
│
├─► addLearning(source: "negative", rule: "Negative feedback on: <context>")
│
└─► qualityTracker.logFeedback(positive: false)
Формат файла learnings
# Learnings
> Auto-generated. Injected into GSD prompt at session start.
## Rules
- [2026-04-03T14:22:00Z] [fixit] Always use t-call for translations in Odoo QWeb
- [2026-04-03T15:10:00Z] [negative] Avoid sudo in deployment scripts
Вставка в prompt
Функция formatForPrompt() берёт самые последние learnings (до 2000 символов), переворачивает их (сначала самые новые) и форматирует как:
LEARNINGS (past corrections — follow these rules):
- Avoid sudo in deployment scripts
- Always use t-call for translations in Odoo QWeb
Принцип проектирования
Вдохновлён Claude Reflect System: исправления не просто фиксируют текущий ответ — они становятся постоянными правилами, предотвращающими регрессию. Система накапливает "иммунную память" со временем.
Столп 4: Karpathy Loop (Nightly Self-Improvement)
Модуль: scripts/nightly-improve.ts
Расписание: ежедневно в 03:00 UTC через cron
Состояние: mcp-server/state/improvement-proposals.json
Что делает
- Читает
config/bot_registry.jsonдля перечисления всех дочерних ботов - Для каждого дочернего: читает
quality-metrics.jsonиз его директории состояния - Вызывает
findUnderperformingSkills()— фильтрует скиллы, где:applied_count >= 3(минимальный размер выборки)- И либо
success_rate < 80%, ИЛИfeedback_negative > feedback_positive
- Читает
learnings.mdдля связанных паттернов исправлений - Генерирует предложения на основе шаблонов (детерминировано, без AI)
- Отправляет CEO сводный отчёт в Telegram
- Отправляет карточки отдельных предложений с inline-кнопками Approve/Reject
Флоу одобрения CEO
Nightly script ──► Telegram: Proposal Card
│
┌────────────┼────────────┐
▼ ▼
✅ Одобрить ❌ Отклонить
│ │
Бэкап skill.md Пометить как отклонённое
как skill.v1.md в proposals.json
(макс. 3 версии)
│
Пометить как одобренное
в proposals.json
Версионирование скиллов
При одобрении master-бот создаёт версионные бэкапы:
skill.md→skill.v1.md(текущий → бэкап)skill.v1.md→skill.v2.md(ротация)- Максимум 3 версии бэкапа на скилл
Принцип проектирования
Вдохновлён Karpathy's AutoResearch Loop: изменить → проверить → сохранить/отбросить → повторить. Критическое отличие: предложения основаны на шаблонах и требуют одобрения человека. Никакой автономной перезаписи скиллов — CEO остаётся финальным авторитетом.
Phase 36+ — Семантический слой NotebookLM
Phase 36.3 добавила пятый канал обратной связи: Google NotebookLM как долгосрочная семантическая память.
CRM Events (закрытие задачи, обновление вики)
│
└─► fire-and-forget POST к bridge /sync
│
▼
NotebookLM Bridge (:19213)
├── SyncWorker (asyncio.Queue, 3 попытки)
└── notebooklm-py → Google NotebookLM
│
▼
Ноутбук обновлён новым источником
│
┌─────────────────────┤
▼ ▼
инструмент ask_notebooklm Neural Skill Generator
(Cloud PM chat, 15с) (POST /skills/generate, 30с)
│ │
▼ ▼
Семантический ответ в Markdown-скилл для
контексте проекта ревью + сохранения (Phase 36.6)
Phase 36.6 добавила Neural Skill Generator: CEO задаёт цель извлечения, bridge запрашивает NotebookLM через структурированный AI Architect prompt, возвращает строгий Markdown Rulebook, который можно сохранить как скилл.
Phase 36.7 вынесла ноутбуки в боковую панель UI (зелёная/красная точка статуса, количество источников, внешняя ссылка).
Столп 6: Sage Worker (Phase 40.11c)
Модуль: shared/sage.ts
Триггер: POST /api/crm/sage/analyze или scripts/nightly-improve.ts
Что делает
Sage — автономный движок улучшения скиллов. Анализирует скиллы с помощью метрик качества + обратной связи пользователей (learnings), затем генерирует конкретный улучшенный контент через Anthropic API (модель Haiku для экономии). Результаты хранятся как skill_update_requests (PR) в базе данных для ревью CEO.
Флоу
Запрос Sage Analyze
│
├─► Загрузить активные скиллы из БД (skillQueries)
├─► Сопоставить с метриками качества (readMetrics)
├─► Приоритизировать неэффективные (findUnderperformingSkills)
│
▼ Для каждого целевого скилла (макс. 5):
├─► Загрузить контент скилла + форк (если скоупирован по проекту)
├─► Загрузить метрики качества (success rate, счётчики обратной связи)
├─► Загрузить связанные learnings (исправления пользователей)
├─► Пропустить если уже существует pending PR
├─► Построить prompt (контент + метрики + learnings)
├─► Вызвать Anthropic API (Haiku, таймаут 30с)
├─► Разобрать ответ (NO_CHANGE = пропустить)
├─► Вставить skill_update_request (proposed_by: 'sage')
└─► Автозапуск бенчмарка (Столп 7) для нового PR
Почему CRM-эндпоинт, а не воркер
Sage нужен прямой доступ к БД (skillQueries, benchmarkQueries) — воркеры запускаются как subprocess'ы без подключения к БД. Sage не получает сообщения пользователей; это фоновый анализатор, чей вывод = строки в БД, а не чат-текст.
Столп 7: Data-Driven Approvals — Benchmarks (Phase 40.11d)
Модуль: shared/sage.ts (runBenchmark())
БД: shared/migrations/005_skill_benchmarks.ts
API: POST /api/crm/sage/benchmark, GET /api/crm/skill-updates/:id/benchmarks
Что делает
До того как CEO одобряет PR от Sage, система доказывает, что изменение работает. Генерирует 3 тестовых сценария, прогоняет оба — старый и новый контент скилла — через них (слепой A/B тест) и использует LLM judge для определения лучшего. Комбинированный скоринг: eval_rules детерминированный (60%) + LLM judge (40%).
Флоу бенчмарка
Запустить бенчмарк (requestId)
│
├─► Загрузить skill_update_request (current_content + proposed_content)
├─► Загрузить eval_rules из БД
│
▼ Сгенерировать 3 тестовых сценария (Haiku)
│
▼ Для каждого сценария:
├─► Запустить старый контент скилла → old_output
├─► Запустить новый контент скилла → new_output
├─► Рандомизировать порядок A/B (предотвращение position-bias)
├─► LLM Judge оценивает оба (1-10) + причина
├─► Детерминированный eval_rules скоринг (если доступен)
├─► Комбинированный счёт: eval 60% + LLM 40%
└─► Сохранить в таблицу skill_benchmarks
│
▼ Обновить метаданные PR
├─► verdict: PASSED / FAILED / TIE
├─► improvement_pct: ((new_avg - old_avg) / old_avg * 100)
└─► BenchmarkBadge виден в заголовке PR на фронтенде
Фронтенд: Battle Mode
SkillEvolution.jsx → компонент BenchmarkReport:
- Lazy-loaded по PR (загружается при разворачивании)
- Сводка: wins/losses/ties/verdict/improvement_pct
- По сценарию: Old vs New бок о бок, звёздочка победителя, счёт/10, причина решения
- Кнопка "Run Benchmark" на вкладке Content (голубой цвет)
- Якорная кнопка per PR для повторного запуска бенчмарков
Карта файлов
shared/
├── evals.ts ← Столп 1: Binary Eval Engine
├── context-router.ts ← Столп 2: Context Router (routeContextFromDb)
├── learnings.ts ← Столп 3: Reflect Loop
├── quality.ts ← Расширен: findUnderperformingSkills()
├── sage.ts ← Столпы 6+7: Sage Worker + Benchmarks (runSageAnalysis, runBenchmark)
├── db.ts ← SQLite SSOT: skillQueries, benchmarkQueries, chatQueries
├── migrations/
│ ├── 004_skill_system.ts ← skills_global, forks, evolution_logs, update_requests
│ └── 005_skill_benchmarks.ts ← skill_benchmarks (результаты A/B тестов)
├── crm-routes.ts ← CRM API: 55+ эндпоинтов (Sage + бенчмарки + эволюция скиллов)
└── ui_templates.ts ← Расширен: improvementProposal()
scripts/
├── nightly-improve.ts ← Столп 4: Karpathy Loop (теперь использует Sage + DB)
└── migrate-skills-to-db.ts ← Nuclear migration: файлы → DB
clients/
├── arc-cli.ts ← ARC CLI (Phase 31.5): login, start, projects
└── knowledge-mcp.ts ← Deprecated (Phase 38 → CLI subcommands)
services/
└── notebooklm-bridge/ ← Столп 5: семантический поиск NotebookLM (Phase 36.3)
├── main.py ← FastAPI (:19213), /query, /sync, /notebooks/init, /health
└── seed_knowledge.py ← Массовый импорт существующих знаний
frontend/src/crm/pages/
└── SkillEvolution.jsx ← Двухпанельный UI: explorer + detail (Content/Evals/Evolution/PRs)
BenchmarkBadge, BenchmarkReport, Battle Mode, кнопка Sage analyze
child-bot/bot.ts ← Интеграция: startup + GSD prompt + eval footnotes + /learnings
child-bot/ingest-watcher.ts ← Авто-инgest: fs.watch на raw/ → CRM inbox (Phase 28)
master-bot/bot.ts ← Интеграция: триггер nightly cron Sage