{
  "updated_at": "2026-10-14T10:02:43+00:00",
  "groups": [
    "Файлы",
    "Терминал",
    "Код-анализ",
    "Планирование",
    "Web",
    "Память",
    "Система",
    "Агенты (hub)",
    "MCP-серверы",
    "Скиллы"
  ],
  "tools": [
    {
      "id": "bash",
      "group": "Терминал",
      "name": "Команды оболочки",
      "kind": "tool",
      "purpose": "Одна команда или короткий конвейер в рабочем каталоге сессии",
      "params": [
        "command — команда целиком; оболочка не подставляется",
        "env — дополнительные переменные окружения",
        "timeout — секунды: 0 снимает дедлайн, иначе значение зажимается в 1–3600",
        "cwd — рабочий каталог",
        "pty — запуск в терминале",
        "async — увести команду в фон"
      ],
      "when": "Реальные бинари и короткие конвейеры: счёт, выборка, diff. Поиск и чтение файлов идут встроенными инструментами, а серверы, наблюдатели и REPL — через hub (op=start).",
      "test": {
        "cmd": "seq 1 1000 | wc -l",
        "result": "1000; ответ вернулся за 0.14 с, дедлайн 300 с применён по умолчанию",
        "ms": 145
      },
      "limits": "Дедлайн 300 с по умолчанию, допустимо 1–3600 с, 0 — без ограничения. Инлайн-вывод до 50 КиБ; что больше — уходит в артефакт с сырым потоком, а в ответе остаётся хвост с пометкой.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/bash.ts:316-331, 1002; tools/tool-timeouts.ts:11"
    },
    {
      "id": "glob",
      "group": "Файлы",
      "name": "Поиск файлов по маске",
      "kind": "tool",
      "purpose": "Ищет пути по маске; содержимое ищет `grep`",
      "params": [
        "path — маска, файл или каталог; несколько целей через точку с запятой",
        "hidden — включать скрытые файлы (по умолчанию да)",
        "gitignore — уважать .gitignore (по умолчанию да)",
        "limit — сколько результатов вернуть: по умолчанию и максимум 200"
      ],
      "when": "Когда путь заранее неизвестен и нужно найти файлы по имени или расширению. Содержимое ищет grep, а один каталог целиком отдаёт read.",
      "test": {
        "cmd": "glob scripts/streaming/**/*.py, затем glob .env* дважды (с gitignore и без)",
        "result": "1 файл (site_catalog.py); .env* по умолчанию — 5 файлов, с gitignore=false — 7: появляется сам .env и вложенный в чужой проект",
        "ms": 18
      },
      "limits": "До 200 результатов (это и дефолт, и потолок), таймаут 5 с. Скрытые файлы включены по умолчанию, .gitignore уважается по умолчанию — .env не покажется, пока явно не попросить (проверено). Выдача отсортирована по времени изменения, свежие сверху; limit ≤ 0 отклоняется с ошибкой.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/glob.ts:44-56, 297-303, 567"
    },
    {
      "id": "grep",
      "group": "Файлы",
      "name": "Поиск по содержимому",
      "kind": "tool",
      "purpose": "Ищет регуляркой по содержимому файлов, каталогов и внутренних URL",
      "params": [
        "pattern — регулярное выражение (Rust regex, фолбэк PCRE2)",
        "path — файл, каталог, маска, внутренний URL, селектор «файл:строки» или список целей через точку с запятой",
        "case — учитывать регистр",
        "gitignore — уважать .gitignore",
        "skip — пропустить N файлов: пагинация, когда прошлый вызов упёрся в лимит"
      ],
      "when": "Поиск по содержимому, когда путь заранее неизвестен: литералы, регулярки, шаблоны через границу строк. Заменяет внешний grep и работает по внутренним URL.",
      "test": {
        "cmd": "grep \"^def c_mem_\" ui/test_harness.py",
        "result": "11 совпадений — ровно столько же даёт независимый подсчёт регуляркой по тому же файлу (5150 строк)",
        "ms": 178
      },
      "limits": "Одна выдача — до 20 файлов и до 20 совпадений на файл, дальше пагинация через skip. Файлы больше 4 МиБ просматриваются частично, о чём есть пометка. Строка совпадения обрезается по 512 символам.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/grep.ts:82-101, 115; session/streaming-output.ts:12"
    },
    {
      "id": "ast_grep",
      "group": "Код-анализ",
      "name": "Структурный поиск (AST)",
      "kind": "tool",
      "purpose": "Структурный поиск по AST (ast-grep), а не по тексту",
      "params": [
        "pat — AST-паттерн: $A — один узел, $$$ARGS — ноль и более, $_ — несвязанный",
        "paths — файлы, каталоги, маски; язык определяется по каждому файлу"
      ],
      "when": "Структурный поиск, когда важна форма кода, а не текст: конструкции и вызовы независимо от форматирования и комментариев.",
      "test": null,
      "limits": "Выключен ключом astGrep.enabled (по умолчанию false, оверлей харнесса его не включает): вызов вернул «Unknown tool from js runtime: ast_grep» за 2.5 мс. Поэтому теста нет — есть честное признание. Включается тумблером в панели закладок, тогда инструмент появляется и у агента.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/ast-grep.ts; ui/tool_docs.json (tool:ast_grep)"
    },
    {
      "id": "ast_edit",
      "group": "Код-анализ",
      "name": "Структурная правка (AST)",
      "kind": "tool",
      "purpose": "Структурный рерайт через ast-grep: паттерн → замена по AST",
      "params": [
        "ops — пары pat → out; метапеременные паттерна подставляются в замену по правилу 1:1",
        "paths — файлы, каталоги, маски, где искать совпадения"
      ],
      "when": "Кодмод по форме: одна и та же перестройка в десятках мест. Для одноразовой текстовой правки проще edit.",
      "test": {
        "cmd": "предложение json.dumps($$$ARGS) → json.dumps($$$ARGS) в site_catalog.py, затем отказ",
        "result": "3 замены в 1 файле: «Staged as a proposal — files NOT modified yet»; отказ их отбросил, sha256 файла до и после совпал",
        "ms": 16
      },
      "limits": "Правило 1:1 — узел нельзя разбить или склеить, паттерн обязан быть целым узлом AST. Найденное не применяется само: без записи причины в xd://resolve правки не будет.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/ast-edit.ts; xd://ast_edit (док устройства)"
    },
    {
      "id": "lsp",
      "group": "Код-анализ",
      "name": "Языковые серверы (LSP)",
      "kind": "tool",
      "purpose": "Языковые серверы: диагностика, определения, ссылки, переименование, code actions",
      "params": [
        "action — diagnostics | definition | references | hover | symbols | rename | rename_file | code_actions | request",
        "для действий с позицией: file + line + symbol (строка нумеруется с 1)",
        "timeout — секунды: по умолчанию 20, допустимо 5–300"
      ],
      "when": "Навигация и правки там, где есть языковой сервер: определения, ссылки, диагностика, переименование с учётом shadowing и реэкспортов.",
      "test": {
        "cmd": "lsp diagnostics и symbols для .py и .ts файлов",
        "result": "ответ честный: «No language server found» за 1–13 мс — текстового фолбэка нет и он не подставляется",
        "ms": 13
      },
      "limits": "Без установленного языкового сервера инструмент не изобретает результат, а сообщает об отсутствии сервера. Таймаут 20 с по умолчанию, диапазон 5–300.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/lsp.ts; tools/tool-timeouts.ts:17"
    },
    {
      "id": "todo",
      "group": "Планирование",
      "name": "Список задач",
      "kind": "tool",
      "purpose": "Мутация списка задач сессии одним действием + снимок фаз и задач",
      "params": [
        "op — init | start | done | drop | block | unblock | append | rm | view",
        "task | phase | items | reason — что именно менять"
      ],
      "when": "План самой сессии: фазы, задачи, блокировки. Держит порядок шагов, когда работа длинная и её нужно видеть по частям.",
      "test": {
        "cmd": "todo view — снимок списка задач",
        "result": "вернул текущие фазы и статусы: 4 из 4 задач фазы закрыты, 0 открытых",
        "ms": 2
      },
      "limits": "Один вызов — одна операция (кроме view). Задачи авто-продвигаются по фазам, поэтому порядок фаз и есть порядок работы. Вызов todo не должен быть единственным действием хода — он идёт в паре с реальной работой.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/todo.ts; ui/tool_docs.json (tool:todo)"
    },
    {
      "id": "debug",
      "group": "Код-анализ",
      "name": "Отладчик",
      "kind": "tool",
      "purpose": "Отладчик по DAP: точки останова, шаги, стек, переменные, память",
      "params": [
        "action — launch | attach | точки останова | step in/over/out | evaluate | stack_trace | variables | read_memory | terminate",
        "adapter — debugpy, dlv, lldb-dap, gdb, rdbg или запись из dap.json"
      ],
      "when": "Когда нужен не вывод, а состояние: брейкпоинты, шаги, стек, значения переменных, память процесса.",
      "test": {
        "cmd": "debug launch мини-скрипта с явным adapter=debugpy, затем modules и terminate",
        "result": "адаптер найден (debugpy в списке установленных), но сессия не поднялась: «DAP connection closed: debugpy transport ended» за 5.7 с; дальше действия отвечают «No active debug session», terminate — тихий no-op",
        "ms": 5722
      },
      "limits": "Дефолтный адаптер (bash-debug-adapter) не установлен — нужен явный adapter. В этой среде отладочная сессия не поднимается, и инструмент говорит об этом прямо, а не молчит. Таймаут 30 с (5–300).",
      "source": "oh-my-pi/packages/coding-agent/src/tools/debug.ts; tools/tool-timeouts.ts:18"
    },
    {
      "id": "git",
      "group": "Код-анализ",
      "name": "Git в интерфейсе",
      "kind": "key",
      "purpose": "Настройка OMP: ветка/статус/PR в TUI и слежение за метаданными репозитория",
      "params": [],
      "when": "Вызывать нечего: это тумблер отображения ветки, статуса и PR в интерфейсе, а не инструмент.",
      "test": null,
      "limits": "Отдельного инструмента нет, поэтому теста нет: git-операции агент делает через bash (git status, git diff, git log), а разрушительные команды — только по прямой просьбе.",
      "source": "ui/tool_docs.json (tool:git); ui/tool_folders.py:53"
    },
    {
      "id": "plan",
      "group": "Планирование",
      "name": "Режим планирования",
      "kind": "key",
      "purpose": "Режим планирования: read-only исследование перед правками",
      "params": [],
      "when": "Режим планирования: агент исследует и предлагает план, а правки делает только после подтверждения плана.",
      "test": null,
      "limits": "Это тумблер (plan.enabled), а не инструмент: отдельного вызова нет, поэтому теста нет. Польза ровно в одном — запрет на правки до согласованного плана.",
      "source": "ui/tool_docs.json (tool:plan); ui/tool_folders.py:54"
    },
    {
      "id": "goal",
      "group": "Планирование",
      "name": "Режим цели",
      "kind": "hidden",
      "purpose": "Режим цели сессии и скрытый инструмент goal",
      "params": [],
      "when": "Цель сессии: пока она задана, агент держит её в поле зрения и меряет шаги ею.",
      "test": null,
      "limits": "Тумблер goal.enabled плюс скрытый инструмент goal: в списке инструментов модели он не показывается, поэтому теста у карточки нет.",
      "source": "ui/tool_docs.json (tool:goal); ui/tool_folders.py:55"
    },
    {
      "id": "ask",
      "group": "Система",
      "name": "Вопрос пользователю",
      "kind": "tool",
      "purpose": "Интерактивный вопрос пользователю: выбор из вариантов или свободный текст",
      "params": [
        "вопрос и варианты выбора или свободный текст ответа"
      ],
      "when": "Интерактивный вопрос пользователю: когда нужен выбор человека, а не догадка агента.",
      "test": null,
      "limits": "Теста нет: в headless-прогоне отвечать некому — вопрос останется без ответа. Для уточнений в автономной работе пишут в чат.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/ask.ts; ui/tool_docs.json (tool:ask)"
    },
    {
      "id": "web_search",
      "group": "Web",
      "name": "Веб-поиск",
      "kind": "tool",
      "purpose": "Один веб-запрос через первый доступный провайдер поиска",
      "params": [
        "query — строка поиска с операторами Google-стиля (site:, after:, inurl:, кавычки)",
        "num_search_results / max_tokens — размер выдачи"
      ],
      "when": "Свежие данные и внешние источники: когда нужен поиск, а не чтение известного адреса (известный адрес читает read).",
      "test": {
        "cmd": "web_search «hls.js lowLatencyMode documentation»",
        "result": "ОШИБКА после 83.2 с: startpage не отдал контента, duckduckgo заблокировал бот-проверкой; нужен провайдер с ключом (например Exa)",
        "ms": 83242
      },
      "limits": "Ключ exa.enabled включён, но ключа Exa в конфиге нет, а providers.webSearchOrder пуст — поэтому запрос ушёл в бесключевые провайдеры (startpage, duckduckgo) и оба отказали. Отказ приходит только после таймаутов: 83 с ожидания. Лечится ключом провайдера или порядком поиска в настройках.",
      "source": "oh-my-pi/packages/coding-agent/src/prompts/tools/web-search.md; ui/tool_docs.json (tool:web_search)"
    },
    {
      "id": "browser",
      "group": "Web",
      "name": "Браузер",
      "kind": "tool",
      "purpose": "Скриптовый Chromium/CDP: вкладки, реюз, привязка к своему Chrome",
      "params": [
        "action — open | run | close; name — имя вкладки (вкладки живут между вызовами)",
        "code — JavaScript против реальной вкладки; url, wait_until, timeout — навигация"
      ],
      "when": "Проверка и отладка живых страниц: вкладки, авторизация, интерактив, снятие скриншотов. Статичный текст дешевле читать через read.",
      "test": {
        "cmd": "прогон локальной страницы: open → waitForSelector → evaluate 12 полей → screenshot",
        "result": "ошибок страницы нет; прочитаны карточки, чипсы групп, задачи и id плеера; переполнений 0, скриншот снят",
        "ms": 1500
      },
      "limits": "Навигация и перерисовки обнуляют ссылки на элементы — перед действием нужен новый снимок. Запуск и снимки укладываются в секунды; таймаут вызова 30 с по умолчанию (1–300).",
      "source": "oh-my-pi/packages/coding-agent/src/tools/browser.ts; tools/tool-timeouts.ts:13"
    },
    {
      "id": "fetch",
      "group": "Web",
      "name": "Чтение URL",
      "kind": "key",
      "purpose": "Разрешение для `read` тянуть и обрабатывать URL (не отдельный инструмент)",
      "params": [],
      "when": "Не отдельный инструмент, а разрешение для read тянуть http(s): страница скачивается и конвертируется в текст.",
      "test": null,
      "limits": "Отдельной тулзы нет — теста нет: карточка объясняет, что ключ fetch.enabled открывает чтение URL внутри read.",
      "source": "ui/tool_docs.json (tool:fetch); ui/omp-windows-overlay.yml:15-16"
    },
    {
      "id": "exa",
      "group": "Web",
      "name": "Exa — веб-поиск",
      "kind": "key",
      "purpose": "Провайдер веб-поиска Exa для web_search",
      "params": [],
      "when": "Провайдер веб-поиска: с ключом Exa выдача web_search приходит от него.",
      "test": null,
      "limits": "Инструмента нет — теста нет. Модель видит только web_search; exa.enabled решает, откуда тот берёт результаты.",
      "source": "ui/tool_docs.json (tool:exa); ui/tool_folders.py:60"
    },
    {
      "id": "github",
      "group": "Система",
      "name": "GitHub — операции CLI",
      "kind": "tool",
      "purpose": "Операции GitHub CLI: репозитории, файлы, PR, поиск, watch Actions",
      "params": [],
      "when": "Операции GitHub CLI: репозиторий и файлы, pull request, поиск, слежение за запусками Actions.",
      "test": null,
      "limits": "Выключен ключом github.enabled, а сам провайдер github перечислен в disabledProviders: вызов вернул «Unknown tool from js runtime: github» за 1.2 мс — теста нет. Чтобы включить, нужны и ключ, и авторизованный gh.",
      "source": "ui/tool_docs.json (tool:github); ui/tool_folders.py:61"
    },
    {
      "id": "security",
      "group": "Система",
      "name": "Сканер безопасности",
      "kind": "device",
      "purpose": "Планирование и прогон security-сканов, валидация находок, security://",
      "params": [
        "action — preflight | start | status | cancel | validate | cloud_scans | cloud_start | cloud_status | cloud_pull",
        "target_kind / include_paths / exclude_paths / base_revision / head_revision — что сканировать",
        "credential_id, scan_id, finding_id — привязка к аккаунту и к находкам"
      ],
      "when": "План и прогон сканов безопасности репозитория, валидация находок и чтение результатов через security://.",
      "test": {
        "cmd": "устройство xd://security_scan, action=status",
        "result": "устройство ответило: «operation_id is required for this action» — вызов доходит и проверяет аргументы",
        "ms": 3
      },
      "limits": "Скан не запускался: это фоновая задача на снимке репозитория, и запускать её здесь было незачем. По умолчанию ключ security.enabled выключен — тогда недоступны и инструмент, и security://. Устройства xd:// монтируются только в сессию, которой выдан инструмент записи: в read-only наборе монтирования нет вообще, и любой вызов устройства отклоняется сообщением «xd:// is not mounted in this session» ещё до проверки имени (проверено на read-only субагенте).",
      "source": "xd://security_scan (док устройства); ui/tool_docs.json (tool:security); oh-my-pi/packages/coding-agent/src/internal-urls/xd-protocol.ts:35,43; sdk.ts:3130-3211; task/read-only-policy.ts"
    },
    {
      "id": "vault",
      "group": "Система",
      "name": "Хранилище Obsidian",
      "kind": "url",
      "purpose": "Доступ к Obsidian-хранилищу через vault:// (чтение и правка)",
      "params": [],
      "when": "Доступ к Obsidian-хранилищу через vault:// — чтение и правка заметок.",
      "test": {
        "cmd": "read vault://",
        "result": "инструмент ответил прямо: «vault:// is disabled. Enable it by setting vault.enabled = true»",
        "ms": 2
      },
      "limits": "Пока ключ vault.enabled выключен (это состояние по умолчанию), пространство не резолвится и запись убирается из системного промпта — проверено на живом вызове: инструмент ответил прямо, без текстового фолбэка.",
      "source": "ui/tool_docs.json (tool:vault)"
    },
    {
      "id": "checkpoint",
      "group": "Система",
      "name": "Чекпойнт контекста",
      "kind": "tool",
      "purpose": "Отметка состояния диалога, чтобы потом свернуть разведку в отчёт (rewind)",
      "params": [],
      "when": "Отметка состояния диалога: потом парный rewind сворачивает разведку в короткий отчёт.",
      "test": null,
      "limits": "Выключен ключом checkpoint.enabled (по умолчанию false): вызов вернул «Unknown tool from js runtime: checkpoint» за 1.2 мс, поэтому теста нет. Включается тумблером осознанно: парный rewind выбрасывает часть контекста диалога.",
      "source": "ui/tool_docs.json (tool:checkpoint)"
    },
    {
      "id": "launch",
      "group": "Система",
      "name": "Процессы под надзором",
      "kind": "op",
      "purpose": "Супервизия долгоживущих процессов — теперь op-семейство `hub`",
      "params": [],
      "when": "Супервизия долгоживущих процессов — теперь это операции hub: start, ps, logs, stop, restart, describe.",
      "test": null,
      "limits": "Отдельного инструмента `launch` больше нет — теста нет. Ключ launch.enabled остался и открывает op-семейство hub.",
      "source": "ui/tool_docs.json (tool:launch); oh-my-pi/packages/coding-agent/src/prompts/tools/hub.md"
    },
    {
      "id": "speechgen",
      "group": "Система",
      "name": "Синтез речи",
      "kind": "tool",
      "purpose": "Синтез речи в файл: локально (Kokoro) или через xAI Grok Voice",
      "params": [
        "text — что озвучить; output_path — куда положить аудио",
        "голос и провайдер — локальный каталог или облачный xAI"
      ],
      "when": "Синтез речи в файл: озвучка, черновые дорожки, проверка звука в проекте.",
      "test": null,
      "limits": "Теста нет: вызов тянет голосовую модель и не является дешёвой проверкой, в этом прогоне не запускался. Рантайм-имя инструмента — tts.",
      "source": "ui/tool_docs.json (tool:speechgen)"
    },
    {
      "id": "generate_image",
      "group": "Система",
      "name": "Генерация изображений",
      "kind": "device",
      "purpose": "Генерация и правка изображений; результат пишется во временный путь",
      "params": [],
      "when": "Генерация и правка изображений: результат пишется во временный путь.",
      "test": null,
      "limits": "Теста нет: вызову нужен провайдер генерации, и это не дешёвая проверка. При включённом tools.xdev отдаётся как устройство xd://generate_image. Устройства xd:// монтируются только в сессию, которой выдан инструмент записи: в read-only наборе монтирования нет вообще, и любой вызов устройства отклоняется сообщением «xd:// is not mounted in this session» ещё до проверки имени (проверено на read-only субагенте).",
      "source": "ui/tool_docs.json (tool:generate_image); oh-my-pi/packages/coding-agent/src/internal-urls/xd-protocol.ts:35,43; sdk.ts:3130-3211; task/read-only-policy.ts"
    },
    {
      "id": "inspect_image",
      "group": "Система",
      "name": "Разбор изображений",
      "kind": "tool",
      "purpose": "Разбор локальной картинки vision-моделью: текстовый анализ",
      "params": [
        "path — файл картинки, .svg с пометкой :img, вложение текущего хода или attachment://N",
        "question — что именно спросить про изображение"
      ],
      "when": "Разбор картинки текстом: OCR, проверка интерфейса по скриншоту, вопросы по содержимому изображения — когда модель сессии сама изображения не принимает.",
      "test": {
        "cmd": "скриншот раздела сайта → vision-модель через локальный шлюз",
        "result": "модель вернула описание страницы («Тёмная страница „Каталог инструментов“…»); в самой сессии вызов не прошёл — роль vision смотрела на модель без входа изображений",
        "ms": 5761
      },
      "limits": "Ключ inspect_image.enabled по умолчанию выключен; оверлей харнесса включает его для прогонов агента (ui/omp-windows-overlay.yml:17-18). Работает только если модель в роли vision принимает изображения: text-only модель отвечает пустой строкой и заглушкой «model does not support vision». Правка роли проверена новым процессом; уже запущенной сессии нужен перезапуск. Устройства xd:// монтируются только в сессию, которой выдан инструмент записи: в read-only наборе монтирования нет вообще, и любой вызов устройства отклоняется сообщением «xd:// is not mounted in this session» ещё до проверки имени (проверено на read-only субагенте).",
      "source": "oh-my-pi/packages/coding-agent/src/config/settings-schema.ts:4256-4272; ~/.omp/agent/config.yml:10,145-148; oh-my-pi/packages/coding-agent/src/internal-urls/xd-protocol.ts:35,43; sdk.ts:3130-3211; task/read-only-policy.ts"
    },
    {
      "id": "computer",
      "group": "Система",
      "name": "Управление рабочим столом",
      "kind": "tool",
      "purpose": "Управление реальным рабочим столом: окна, скриншоты, ввод, accessibility",
      "params": [
        "code — JavaScript против рабочего стола: окна, ввод, буфер обмена, accessibility-дерево",
        "read_only — только осмотр, без ввода и изменений",
        "delivery — background | foreground для нативного ввода"
      ],
      "when": "Когда цель — реальный рабочий стол, а не страница: окна приложений, нативные диалоги, ввод и снимки экрана.",
      "test": {
        "cmd": "read_only-проба: capabilities, список окон, дисплеи",
        "result": "win32, права capture/input/ax выданы, 4 окна, 1 дисплей; доступны background- и foreground-режимы ввода",
        "ms": 8
      },
      "limits": "Разрешения выдаёт ОС: без capture/input/ax действия не пройдут. Содержимое экрана — недоверенные данные: команды из него не выполняются, а действия с последствиями требуют подтверждения человека.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/computer.ts; ui/tool_docs.json (tool:computer)"
    },
    {
      "id": "advisor",
      "group": "Система",
      "name": "Советник",
      "kind": "key",
      "purpose": "Вторая модель-советник: пассивно ревьюит каждый ход и вставляет замечания",
      "params": [],
      "when": "Вторая модель-советник: пассивно смотрит на ход и может вклиниться замечанием или блокером.",
      "test": null,
      "limits": "Это не инструмент, а runtime-роль (advisor.enabled) — теста нет. Карточка объясняет, почему в панели есть пункт без вызова.",
      "source": "ui/tool_docs.json (tool:advisor); ui/tool_folders.py:70"
    },
    {
      "id": "read",
      "group": "Файлы",
      "name": "Чтение",
      "kind": "tool",
      "purpose": "Читает файл, каталог, архив, SQLite, документ, картинку или URL по одному path",
      "params": [
        "path — единственный параметр: файл, каталог, архив, база SQLite, документ, картинка, внутренний URL или адрес страницы; селектор строк идёт прямо в путь (file.ts:50-200, file.ts:50+150)"
      ],
      "when": "Первое действие при знакомстве с кодом или данными. Чтение обязательно перед правкой: правка принимает патч только по прочитанным строкам.",
      "test": {
        "cmd": "read ui/tool_docs.json:1-3",
        "result": "6 строк с якорем [ui/tool_docs.json#C9F5] и хвостом «[Showing lines 1-6 of 441]» — видно и окно, и полный размер файла",
        "ms": 10
      },
      "limits": "По умолчанию 3000 строк и 50 КиБ за вызов, длинная строка обрезается по 512 символам. Каталог отдаётся деревом на 2 уровня, до 12 детей на каталог. Картинка — до 20 МиБ.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/read.ts:529-535, 526-527, 2313-2314; session/streaming-output.ts:10-12"
    },
    {
      "id": "read_group",
      "group": "Файлы",
      "name": "Чтение (группы)",
      "kind": "group",
      "purpose": "Панельная группировка OMP: несколько прочитанных файлов одним блоком",
      "params": [],
      "when": "Вызывать нечего: несколько прочитанных файлов одним блоком — это группировка отображения, а читает всё `read`.",
      "test": null,
      "limits": "Отдельного инструмента нет, поэтому и теста нет: пункт существует только для вида панели, его выключение не меняет прогон.",
      "source": "ui/tool_docs.json (tool:read_group); ui/tool_folders.py:75-98"
    },
    {
      "id": "write",
      "group": "Файлы",
      "name": "Запись",
      "kind": "tool",
      "purpose": "Создаёт/перезаписывает файл, элемент архива, строку SQLite или устройство xd://",
      "params": [
        "path — файл, элемент архива (архив.zip:путь/внутри), строка базы (base.sqlite:таблица[:ключ]) или устройство xd://имя",
        "content — содержимое целиком: файл перезаписывается, а не дописывается"
      ],
      "when": "Новый файл или полная перезапись существующего. Точечную правку делает `edit` — только он сверяет контекст по прочитанным строкам.",
      "test": {
        "cmd": "write фикстуры из двух строк в data/tmp, затем перезапись строкой «v2»",
        "result": "файл создан, содержимое совпало с ожиданием байт в байт; перезапись дала 3 байта; опечатка в схеме (foo://bar) отклонена с подсказкой",
        "ms": 50
      },
      "limits": "В ответе длина считается в символах, а на диске лежат байты: 27 символов кириллицы дали 50 байт в UTF-8. Элемент архива переписывается через временный файл — падение посреди записи не рушит архив. Путь, похожий на URL, отклоняется, пока не начнёшь его с ./ Через write же исполняются устройства xd://: сам инструмент вызывается как write xd://<имя>, поэтому сессия без права записи устройств не видит.",
      "source": "oh-my-pi/packages/coding-agent/src/tools/write.ts:300-303, 505, 114-132, 652-654"
    },
    {
      "id": "edit",
      "group": "Файлы",
      "name": "Правка файла",
      "kind": "tool",
      "purpose": "Правки файла: hashline-патч (по умолчанию), unified-diff или patch-режим",
      "params": [
        "input — патч целиком: секции «[путь#ЯКОРЬ]» и операции PUT / CUT / MV / REM (режим hashline, по умолчанию)",
        "в режимах apply_patch, patch, replace и sloppy вход свой; режим выбирается настройкой"
      ],
      "when": "Правка существующего файла после чтения: замена, вставка, удаление, перенос блока, переименование. Новый файл целиком пишет запись, а перестилизацию делает форматтер проекта.",
      "test": {
        "cmd": "фикстура из 6 строк: PUT 3.=3 + CUT 5.=5 @mv + PUT >6 @mv",
        "result": "3-я строка заменена, MOVE-ME переехала с 5-й на 6-ю, остальные четыре не тронуты; в ответе дифф, результат сверен с файлом на диске",
        "ms": 13
      },
      "limits": "Меняются только показанные строки; якорь обязателен, правка вне окна чтения отклоняется. Устаревший якорь не отказ: правка применяется со снимка этой сессии и идёт с предупреждением (проверено).",
      "source": "oh-my-pi/packages/coding-agent/src/edit/index.ts:593-790; hashline/src/prompt.md"
    },
    {
      "id": "apply_patch",
      "group": "Файлы",
      "name": "Правка патчем",
      "kind": "group",
      "purpose": "Режим `edit`: правка файла unified-diff-патчем (wire-имя apply_patch)",
      "params": [],
      "when": "Отдельного вызова нет: это режим `edit`, в котором инструмент отдаётся модели под wire-именем apply_patch — так его ждут провайдеры, обученные на этом имени.",
      "test": null,
      "limits": "Тест невозможен по определению: инструмент один — `edit`, карточка лишь показывает, как режим выглядит в панели. Вход в этом режиме — unified-diff, а не hashline-патч.",
      "source": "oh-my-pi/packages/coding-agent/src/edit/index.ts:664-718, 490-498"
    },
    {
      "id": "edit_delete",
      "group": "Файлы",
      "name": "Удаление",
      "kind": "group",
      "purpose": "Операция удаления внутри `edit` (CUT в hashline) — отдельного инструмента нет",
      "params": [],
      "when": "Удаление строк и блоков — это операция CUT внутри `edit`; CUT без вставки ещё и забирает блок в регистр, чтобы вставить его в другом месте.",
      "test": null,
      "limits": "Отдельного инструмента нет, поэтому теста нет: карточка описывает операцию одной тулзы, а не самостоятельный вызов.",
      "source": "oh-my-pi/packages/coding-agent/src/edit/index.ts:719-740; hashline/src/prompt.md"
    },
    {
      "id": "edit_move",
      "group": "Файлы",
      "name": "Перемещение",
      "kind": "group",
      "purpose": "Операция перемещения внутри `edit` (MV в hashline) — отдельного инструмента нет",
      "params": [],
      "when": "Перенос блока — это CUT в регистр плюс PUT тем же регистром, переименование файла — MV. И то, и другое делает `edit`.",
      "test": null,
      "limits": "Отдельного инструмента нет, поэтому теста нет: карточка нужна, чтобы в панели было видно — это операция `edit`, а не третий инструмент рядом с ним.",
      "source": "oh-my-pi/packages/coding-agent/src/edit/index.ts:719-740; hashline/src/prompt.md"
    },
    {
      "id": "eval",
      "group": "Терминал",
      "name": "Код в ячейке",
      "kind": "tool",
      "purpose": "Ячейка Python/JS/Ruby/Julia в постоянном рантайме: состояние живёт между вызовами",
      "params": [
        "language — py | js (и другие ядра, если собраны)",
        "code — текст ячейки; один вызов = одна ячейка"
      ],
      "when": "Когда состояние должно пережить вызов: постоянное ядро, инкрементальная работа, вычисления между шагами. Одноразовую команду проще отдать в bash.",
      "test": {
        "cmd": "три ячейки подряд: метка → чтение метки → sleep(1.5); замер по транскрипту сессии (startedAt → результат)",
        "result": "метка пережила вызов (persistent=True): 4 мс на тривиальную ячейку, 3 мс на чтение, 1502 мс на sleep(1.5) — внутри ячейки тот же сон занял 1500 мс",
        "ms": 4
      },
      "limits": "Латентность = время ячейки плюс 1–3 мс накладных. Дедлайн 30 с по умолчанию, допустимо 1–3600. Ячейка внутри ячейки убивает ядро — проверено (kernel exit 130). Зафиксирован один невоспроизводимый выступ 4048 мс: залипание среды, а не стоимость инструмента (два повтора дали 1502 и 1504 мс).",
      "source": "oh-my-pi/packages/coding-agent/src/tools/eval.ts; tools/tool-timeouts.ts:12; замер по транскрипту сессии"
    },
    {
      "id": "task",
      "group": "Планирование",
      "name": "Субагенты",
      "kind": "tool",
      "purpose": "Спавн субагентов: один за вызов или пачкой tasks[]",
      "params": [
        "context — общий фон пачки: цель, ограничения, контракт",
        "tasks[] — элементы пачки: name, agent, task, outputSchema, schemaMode, isolated",
        "isolated — изолированное рабочее дерево для правок"
      ],
      "when": "Работа, которую можно разрезать: разведка по незнакомому коду, независимые правки, ревью. Агент выбирается под задачу: scout только читает, есть reviewer, librarian, designer, sonic.",
      "test": {
        "cmd": "задача «верни ровно TOOL-TEST-3», агент sonic",
        "result": "спавн вернул управление за 9 мс, ответ получен через 4.8 с отдельной задачей",
        "ms": 4800
      },
      "limits": "Одновременно до 32 субагентов, дальше очередь; по умолчанию вызов не блокирует, результат приходит сам. Ответ агента ограничен 500 000 байт и 5000 строк — длинное уходит в артефакт.",
      "source": "oh-my-pi/packages/coding-agent/src/task/types.ts:117-135, 52-56; config/settings-schema.ts:4946-4964"
    },
    {
      "id": "think",
      "group": "Планирование",
      "name": "Размышление",
      "kind": "hidden",
      "purpose": "Скрытый инструмент размышления (вне схемы инструментов модели)",
      "params": [],
      "when": "Место для размышления, которое не попадает в схему инструментов модели: думать агент может и обычным текстом.",
      "test": null,
      "limits": "Инструмент существует, но спрятан (HIDDEN_TOOL_NAMES): вызова в схеме нет — поэтому и теста нет. Карточка объясняет, куда девается это имя в панели.",
      "source": "oh-my-pi/packages/coding-agent/src/prompts/tools/think.md; ui/tool_docs.json (tool:think)"
    },
    {
      "id": "reflect",
      "group": "Планирование",
      "name": "Синтез по памяти",
      "kind": "off",
      "purpose": "Синтез ответа поверх долговременной памяти (Mnemopi/Hindsight)",
      "params": [],
      "when": "Синтез ответа поверх долговременной памяти — когда нужен вывод, а не отдельные записи.",
      "test": null,
      "limits": "Backend памяти выключен оверлеем (memory.backend: off — mnemopi/fastembed не ставится на Windows), поэтому в прогоне инструмент не смонтирован: теста нет. Память проекта даёт MCP-сервер memory-turbovec.",
      "source": "ui/omp-windows-overlay.yml:6-7; ui/tool_docs.json (tool:reflect)"
    },
    {
      "id": "context_gauge",
      "group": "Планирование",
      "name": "Индикатор контекста",
      "kind": "group",
      "purpose": "Индикатор заполнения контекста в статус-строке OMP",
      "params": [],
      "when": "Вызывать нечего: это индикатор заполнения контекста в статус-строке интерфейса.",
      "test": null,
      "limits": "Инструмента нет — теста нет: карточка объясняет, что «context_gauge» в панели является компонентом интерфейса, а не тулзой.",
      "source": "ui/tool_docs.json (tool:context_gauge)"
    },
    {
      "id": "recall",
      "group": "Память",
      "name": "Поиск в памяти",
      "kind": "off",
      "purpose": "Поиск по долговременной памяти (Mnemopi/Hindsight)",
      "params": [],
      "when": "Поиск по долговременной памяти — когда backend памяти включён.",
      "test": null,
      "limits": "Backend выключен оверлеем (memory.backend: off), поэтому в прогоне инструмент не смонтирован: теста нет. Память проекта даёт MCP-сервер memory-turbovec, а релевантные записи подмешиваются в системный промпт автоматически.",
      "source": "ui/omp-windows-overlay.yml:6-7; ui/memory_recall.py; ui/tool_docs.json (tool:recall)"
    },
    {
      "id": "retain",
      "group": "Память",
      "name": "Запись в память",
      "kind": "off",
      "purpose": "Запись durable-факта в долговременную память",
      "params": [],
      "when": "Запись durable-факта, который должен пережить сессию, — когда backend памяти включён.",
      "test": null,
      "limits": "В этом харнессе backend выключен (memory.backend: off), в прогоне инструмент не смонтирован: теста нет. Записи делает MCP-инструмент memory_add.",
      "source": "ui/omp-windows-overlay.yml:6-7; ui/tool_docs.json (tool:retain)"
    },
    {
      "id": "custom",
      "group": "Система",
      "name": "Свои инструменты",
      "kind": "group",
      "purpose": "Инструменты, зарегистрированные расширениями и плагинами",
      "params": [],
      "when": "Инструменты, зарегистрированные расширениями и плагинами: агент видит их под их собственными именами.",
      "test": null,
      "limits": "Отдельного инструмента `custom` нет — теста нет: это пространство имён в панели, а не вызов.",
      "source": "ui/tool_docs.json (tool:custom)"
    },
    {
      "id": "report_tool_issue",
      "group": "Система",
      "name": "Репорт об инструменте",
      "kind": "device",
      "purpose": "Автоматический QA-репорт о неверном поведении инструмента",
      "params": [],
      "when": "Автоматический QA-репорт о неверном поведении инструмента: ложные срабатывания допустимы — лучше репорт, чем молчание.",
      "test": null,
      "limits": "Тест сознательно не запускался: репорт уходит наружу, это побочный эффект. Первый вызов спрашивает согласие; отказ отключает отправку до явного включения. Устройства xd:// монтируются только в сессию, которой выдан инструмент записи: в read-only наборе монтирования нет вообще, и любой вызов устройства отклоняется сообщением «xd:// is not mounted in this session» ещё до проверки имени (проверено на read-only субагенте).",
      "source": "oh-my-pi/packages/coding-agent/src/tools/report-tool-issue.ts; ui/tool_docs.json (tool:report_tool_issue); oh-my-pi/packages/coding-agent/src/internal-urls/xd-protocol.ts:35,43; sdk.ts:3130-3211; task/read-only-policy.ts"
    },
    {
      "id": "hub_inbox",
      "group": "Агенты (hub)",
      "name": "Входящие",
      "kind": "op",
      "purpose": "op=inbox единой тулзы hub: забрать входящие сообщения других агентов",
      "params": [
        "peek — посмотреть, не вынимая сообщения из шины"
      ],
      "when": "Забрать сообщения, пришедшие от других агентов, когда руки дошли до координации.",
      "test": {
        "cmd": "hub inbox peek=true",
        "result": "«Inbox empty» — очередь смотрится без изъятия сообщений",
        "ms": 3
      },
      "limits": "peek оставляет сообщения в шине, обычный вызов их забирает. Пустая очередь — это ответ, а не ошибка.",
      "source": "xd://hub (док op=inbox)"
    },
    {
      "id": "hub_jobs",
      "group": "Агенты (hub)",
      "name": "Фоновые задачи",
      "kind": "op",
      "purpose": "op=jobs: снимок фоновых задач прогона (завершённые и идущие)",
      "params": [
        "без аргументов — снимок всех фоновых задач прогона"
      ],
      "when": "Одним взглядом увидеть, какие фоновые задачи идут и какие завершились — без ожидания и опроса.",
      "test": {
        "cmd": "hub jobs",
        "result": "снимок состояния: завершённые задачи с пометкой о доставке результата (1 завершённая на момент вызова)",
        "ms": 28
      },
      "limits": "Идентификаторы задач живут в памяти процесса около пяти минут после завершения, дальше остаётся id агента. Снимок заменяет собой отложенную доставку результата.",
      "source": "xd://hub (док op=jobs)"
    },
    {
      "id": "hub_list",
      "group": "Агенты (hub)",
      "name": "Список агентов",
      "kind": "op",
      "purpose": "op=list: состав живых агентов и их статусы",
      "params": [
        "status — running | idle | parked; limit — сколько строк показать (до 100)"
      ],
      "when": "Понять, кто сейчас работает рядом: живые, простаивающие и припаркованные агенты — и как их адресовать.",
      "test": {
        "cmd": "hub list",
        "result": "статусы пиров: 0 живых, 0 простаивающих, 3 припаркованных — припаркованные остаются доступными по адресу",
        "ms": 299
      },
      "limits": "Список ограничен по числу строк, чтобы не вываливать всех припаркованных. Адресовать можно только точным id из списка — выдуманное имя не сработает.",
      "source": "xd://hub (док op=list)"
    },
    {
      "id": "hub_logs",
      "group": "Агенты (hub)",
      "name": "Логи процесса",
      "kind": "op",
      "purpose": "op=logs: хвост вывода процесса (курсор, grep, follow, head)",
      "params": [
        "name — чей вывод; lines — сколько строк (по умолчанию 100, максимум 1000)",
        "cursor — читать только новое; follow — ждать появления строк; grep — фильтр регуляркой"
      ],
      "when": "Читать вывод живого процесса: логи сервера, ответ REPL, прогресс долгой команды.",
      "test": {
        "cmd": "hub logs после отправки строки",
        "result": "окно вывода с курсором: «ready / ping-1 / got: ping-1», cursor=134",
        "ms": 28
      },
      "limits": "Курсор делает чтение инкрементальным: следующий вызов с тем же cursor отдаёт только новое. follow ждёт новые строки, не крутя цикл опроса.",
      "source": "xd://hub (док op=logs)"
    },
    {
      "id": "hub_send",
      "group": "Агенты (hub)",
      "name": "Сообщение / ввод",
      "kind": "op",
      "purpose": "op=send: сообщение агенту или stdin/клавиши/сигнал процессу",
      "params": [
        "name — процессу: text, keys, signal; to — пиру: текст сообщения",
        "await — ждать ответа пира; enter — добавлять перевод строки"
      ],
      "when": "Дать процессу ввод (строчка в REPL, клавиши, сигнал) или написать агенту — не блокируя свой ход.",
      "test": {
        "cmd": "hub send text=ping-1 процессу-эху",
        "result": "строка ушла в stdin и вернулась в выводе: «got: ping-1»",
        "ms": 15
      },
      "limits": "Отправка не блокирует: доставка подтверждается отдельно, а ответ пира ждут через wait. Сигнал завершает дерево процессов, а не отдельный pid.",
      "source": "xd://hub (док op=send)"
    },
    {
      "id": "hub_start",
      "group": "Агенты (hub)",
      "name": "Запуск процесса",
      "kind": "op",
      "purpose": "op=start: запуск долгоживущего процесса под надзором брокера",
      "params": [
        "name — имя процесса в каталоге проекта; application + args — что запускать",
        "ready — условия готовности: строка в логе, порт, таймаут",
        "restart / persist / detached — политика рестарта и переживание выходов"
      ],
      "when": "Серверы, наблюдатели, отладчики и REPL: всё, что живёт долго и требует надзора, а не одного запуска.",
      "test": {
        "cmd": "hub start процесса-эха с готовностью по строке в логе",
        "result": "готовность подтверждена: ready за 7.3 с, pid выдан, restarts=0",
        "ms": 7276
      },
      "limits": "Готовность подтверждается логом или портом — создание процесса само по себе готовностью не считается. Имя уникально в каталоге проекта: живое имя нужно остановить или перезапустить.",
      "source": "xd://hub (док op=start); ui/server.py (broker)"
    },
    {
      "id": "hub_wait",
      "group": "Агенты (hub)",
      "name": "Ожидание",
      "kind": "op",
      "purpose": "op=wait: блокирующее ожидание первого из — сообщение, финиш задачи, таймаут",
      "params": [
        "ids — ждать конкретные задачи; from — ждать конкретного пира; timeoutMs — окно ожидания (0 — бесконечно)"
      ],
      "when": "Когда ход действительно упирается в ожидание: первое из трёх событий — сообщение, завершение задачи, таймаут.",
      "test": {
        "cmd": "hub wait без аргументов, когда задач нет",
        "result": "вернул управление сразу: «No running background jobs to wait for»",
        "ms": 6
      },
      "limits": "Ждёт первое событие, а не все задачи: после возврата ожидание нужно продлить, если ответа ещё нет. Без аргументов ждёт всё сразу; ids и from сужают окно.",
      "source": "xd://hub (док op=wait)"
    },
    {
      "id": "skill:harness",
      "group": "Скиллы",
      "name": "harness",
      "kind": "skill",
      "purpose": "Обёртка Harness V18 вместо прямых вызовов нижележащих инструментов",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:code-review",
      "group": "Скиллы",
      "name": "code-review",
      "kind": "skill",
      "purpose": "Ревью изменений с фиксированной точки по двум осям: стандарты и спецификация",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:diagnosing-bugs",
      "group": "Скиллы",
      "name": "diagnosing-bugs",
      "kind": "skill",
      "purpose": "Цикл диагностики сложных багов и просадок производительности",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:tdd",
      "group": "Скиллы",
      "name": "tdd",
      "kind": "skill",
      "purpose": "Разработка через тесты: сначала падающий тест, потом код",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:codebase-design",
      "group": "Скиллы",
      "name": "codebase-design",
      "kind": "skill",
      "purpose": "Словарь для проектирования глубоких модулей и их интерфейсов",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:domain-modeling",
      "group": "Скиллы",
      "name": "domain-modeling",
      "kind": "skill",
      "purpose": "Построение и уточнение доменной модели проекта",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:ponytail",
      "group": "Скиллы",
      "name": "ponytail",
      "kind": "skill",
      "purpose": "Самое ленивое решение, которое реально работает: короче и минимальнее",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:ponytail-review",
      "group": "Скиллы",
      "name": "ponytail-review",
      "kind": "skill",
      "purpose": "Ревью только на переусложнение: что можно удалить",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:ponytail-audit",
      "group": "Скиллы",
      "name": "ponytail-audit",
      "kind": "skill",
      "purpose": "Аудит всего репозитория на переусложнение: что удалить",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:git-guardrails-claude-code",
      "group": "Скиллы",
      "name": "git-guardrails-claude-code",
      "kind": "skill",
      "purpose": "Хуки Claude Code, блокирующие опасные git-команды до выполнения",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:setup-matt-pocock-skills",
      "group": "Скиллы",
      "name": "setup-matt-pocock-skills",
      "kind": "skill",
      "purpose": "Настроить репозиторий под набор инженерных скиллов",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:prototype",
      "group": "Скиллы",
      "name": "prototype",
      "kind": "skill",
      "purpose": "Одноразовый прототип для проверки вопроса дизайна",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:research",
      "group": "Скиллы",
      "name": "research",
      "kind": "skill",
      "purpose": "Исследование по первичным источникам с отчётом в репозитории",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:resolving-merge-conflicts",
      "group": "Скиллы",
      "name": "resolving-merge-conflicts",
      "kind": "skill",
      "purpose": "Разрешение уже идущего конфликта merge или rebase",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:writing-for-agents",
      "group": "Скиллы",
      "name": "writing-for-agents",
      "kind": "skill",
      "purpose": "Как писать документы для агентов: скиллы, AGENTS.md, CLAUDE.md",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:writing-guidelines",
      "group": "Скиллы",
      "name": "writing-guidelines",
      "kind": "skill",
      "purpose": "Проверка прозы и документации по гайдлайну стиля",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:web-design-guidelines",
      "group": "Скиллы",
      "name": "web-design-guidelines",
      "kind": "skill",
      "purpose": "Проверка интерфейса по Web Interface Guidelines",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:vercel-react-best-practices",
      "group": "Скиллы",
      "name": "vercel-react-best-practices",
      "kind": "skill",
      "purpose": "Практики производительности React и Next.js от Vercel",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:vercel-composition-patterns",
      "group": "Скиллы",
      "name": "vercel-composition-patterns",
      "kind": "skill",
      "purpose": "Паттерны композиции React для масштабируемых компонентов",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:graphify",
      "group": "Скиллы",
      "name": "graphify",
      "kind": "skill",
      "purpose": "Граф знаний по коду и докам: запросы, пути, объяснения",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:handoff",
      "group": "Скиллы",
      "name": "handoff",
      "kind": "skill",
      "purpose": "Сжать текущий диалог в handoff-документ для следующего агента",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:transcribe-ru",
      "group": "Скиллы",
      "name": "transcribe-ru",
      "kind": "skill",
      "purpose": "Распознать русскую речь из аудио или видео в текст",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:skills-index",
      "group": "Скиллы",
      "name": "skills-index",
      "kind": "skill",
      "purpose": "Полный каталог установленных скиллов: имя, назначение, путь",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:sn-deep-research",
      "group": "Скиллы",
      "name": "sn-deep-research",
      "kind": "skill",
      "purpose": "Глубокое исследование: много источников, сверка, отчёт",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:sn-da-excel-workflow",
      "group": "Скиллы",
      "name": "sn-da-excel-workflow",
      "kind": "skill",
      "purpose": "Анализ Excel: чтение, чистка, статистика, экспорт отчёта",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:sn-ppt-entry",
      "group": "Скиллы",
      "name": "sn-ppt-entry",
      "kind": "skill",
      "purpose": "Вход в генерацию презентаций: режим, брифинг, запуск пайплайна",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:sn-research-report",
      "group": "Скиллы",
      "name": "sn-research-report",
      "kind": "skill",
      "purpose": "Структура исследовательского отчёта под задачу читателя",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:sn-md-to-html-report",
      "group": "Скиллы",
      "name": "sn-md-to-html-report",
      "kind": "skill",
      "purpose": "Markdown-отчёт в самодостаточную HTML-страницу с редакторской подачей",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:sn-search-academic",
      "group": "Скиллы",
      "name": "sn-search-academic",
      "kind": "skill",
      "purpose": "Академический поиск: статьи, разбор, цепочки цитирований",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:sn-prepare-citations",
      "group": "Скиллы",
      "name": "sn-prepare-citations",
      "kind": "skill",
      "purpose": "Постобработка сносок: дедупликация, нумерация, список литературы",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "skill:design-taste-frontend",
      "group": "Скиллы",
      "name": "Дизайн",
      "kind": "skill",
      "purpose": "Дизайн: лендинги, портфолио и редизайны без шаблонного вида",
      "params": [],
      "when": "Скилл не вызывают — его загружают: read skill://<имя> по делу. В промпте агента объявлен только always-on набор, остальные доступны через skills-index.",
      "test": null,
      "limits": "Проверка общая для всех тридцати: файл SKILL.md на месте и фронтматтер (name/description) разбирается — 30/30 за 14 мс. Отдельного прогона у карточки нет, потому что скилл — инструкция, а не исполняемый инструмент.",
      "source": "ui/tool_docs.json (skill:*); ui/tool_folders.py: skill_docs"
    },
    {
      "id": "mcp:demo-adapter",
      "group": "MCP-серверы",
      "name": "demo-adapter",
      "kind": "mcp",
      "purpose": "Эталонный адаптер: показывает, что внешний источник контекста подключается без правок кода харнесса",
      "params": [],
      "when": "Эталонный адаптер: показывает, что внешний источник контекста подключается без правок кода харнесса.",
      "test": {
        "cmd": "echo_context с текстом «проверка»",
        "result": "вернул «ADAPTER_CONTEXT: проверка» — внешний MCP-сервер отвечает в общем контуре",
        "ms": 10
      },
      "limits": "Смысл сервера демонстрационный, а не рабочий: его задача — доказать расширяемость. Инструменты видны агенту как mcp__demo-adapter_*.",
      "source": "ui/reference_mcp_adapter.py; ui/data/adapters.json"
    },
    {
      "id": "mcp:memory-turbovec",
      "group": "MCP-серверы",
      "name": "memory-turbovec",
      "kind": "mcp",
      "purpose": "Проектная семантическая память (search/add, без clear)",
      "params": [
        "memory_search: query и k — семантический поиск по памяти проекта",
        "memory_add: текст записи — durable-строка с именами и идентификаторами",
        "memory_count: без аргументов — сколько записей в хранилище"
      ],
      "when": "Память проекта: перед ответом о прошлых решениях — поиск, после важного вывода — запись строки.",
      "test": {
        "cmd": "memory_count, затем memory_search запроса про каталог сайта (k=3)",
        "result": "247 записей в хранилище; поиск вернул релевантные записи с текстами",
        "ms": 261
      },
      "limits": "Семантический поиск стоит около 3 с на запрос — это векторный поиск, а не индекс по словам. Записи живут в общем журнале и переживают сессии; отдельного удаления у сервера нет.",
      "source": "ui/memory_mcp_server.py; xd://mcp__memory_turbovec_*"
    },
    {
      "id": "mcp:bifrost",
      "group": "MCP-серверы",
      "name": "bifrost",
      "kind": "mcp",
      "purpose": "SSH-мост к удалённым серверам (connect/exec/read/status/upload/download/disconnect). Реализация: ui/bifrost_mcp_server.py (stdlib, системный OpenSSH). v2: резидентный ssh-канал (~100 мс на команду вместо хендшейка), ServerAlive+авто-переподключение, инлайн до 45 КБ и спилл в ui/data/bifrost-out, срезы удалённых файлов (read), файлы <=256 КБ по каналу с sha256. Самопроверка: python ui/bifrost_mcp_server.py --selftest (проверено 2026-09-14).",
      "params": [
        "connect | status | exec | read | upload | download | disconnect",
        "server — какое из настроенных подключений взять; команды идут через один постоянный канал"
      ],
      "when": "Работа с удалённой машиной: команды, логи, деплой, файлы — по одному постоянному каналу вместо ручного ssh на каждый шаг.",
      "test": {
        "cmd": "bifrost_status",
        "result": "канал подключён, счётчик команд рос по ходу работы, round-trip около 0.4 с, рестартов канала — 6 за сессию",
        "ms": 7
      },
      "limits": "Инлайн-вывод до 45 КБ, дальше спилл в файл; файлы до 256 КБ идут по каналу с проверкой sha256, крупнее — через scp. Один канал на сервер с авто-переподключением: обрыв не роняет работу.",
      "source": "ui/bifrost_mcp_server.py; ui/data/bifrost.json"
    },
    {
      "id": "mcp:graphify-harness",
      "group": "MCP-серверы",
      "name": "graphify-harness",
      "kind": "mcp",
      "purpose": "Кодовый граф ЛОКАЛЬНОГО харнесса (свой, с этой машины: ui/, tooling/, extensions/, omp/) — не путать со снимками продукта с сервера",
      "params": [
        "get_node — узел и соседи по имени или части пути",
        "query_graph — обход графа; god_nodes — самые связанные узлы",
        "shortest_path — путь между узлами; explain — объяснение узла"
      ],
      "when": "Вопросы об устройстве кодовой базы: связи файлов, узлы-хабы, путь между сущностями — вместо чтения файл за файлом.",
      "test": {
        "cmd": "get_node name=site_catalog",
        "result": "мгновенный ответ «found: false»: узел не проиндексирован, и инструмент говорит это прямо, а не выдумывает связи",
        "ms": 21
      },
      "limits": "Граф — снимок: узел попадает в него после переиндексации, поэтому свежие файлы могут отсутствовать. Локальный граф харнесса обновляется отдельно от снимков продукта.",
      "source": "tooling/v18/bin/graphify-mcp-server.py; data/graphify/harness/graph.json"
    }
  ],
  "tasks_current": [
    {
      "title": "Карточки инструментов: проверка на реальных прогонах",
      "detail": "Проверено 29 позиций из 84: у каждой — параметры, границы и измеренный результат прогона. Остальное честно названо тумблерами, op-семействами, устройствами и панельными группировками"
    },
    {
      "title": "Семь историй о делах на странице",
      "detail": "Общее для всех чувство, своё дело и что с этой болью делается — плюс «Путь и снаряжение» и блок отклика"
    },
    {
      "title": "Страница живёт из репозитория",
      "detail": "Эфир, каталог, задачи и история собираются генератором из каталога харнесса, а не правятся руками в разметке"
    }
  ],
  "tasks_future": [
    {
      "title": "Публичный README и установка в одну команду",
      "detail": "Документация и запуск продукта одной командой для будущих пользователей"
    },
    {
      "title": "Чистка и документация кода",
      "detail": "Приведение кодовой базы к виду, пригодному для открытия"
    },
    {
      "title": "Наборы расширений и шаблонов для типовых задач",
      "detail": "Готовые практики и шаблоны поверх харнесса"
    }
  ],
  "cases": {
    "niches": [
      "Производство",
      "Услуги",
      "Строительство",
      "Архитектура",
      "Медицина",
      "Торговля",
      "Образование",
      "Логистика и грузоперевозки",
      "Наука",
      "Образ жизни",
      "Финансы",
      "Рестораны и общепит",
      "Сельское хозяйство",
      "IT-разработка",
      "Маркетинг и реклама",
      "Недвижимость",
      "Транспорт и доставка",
      "Ремонт и обслуживание",
      "Спорт и фитнес",
      "Развлечения и контент",
      "Продажи и лидогенерация",
      "Управление компанией"
    ],
    "cases": [
      {
        "id": "erp-bez-vendorov",
        "niche": "IT-разработка",
        "title": "ERP без сторонних продуктов",
        "pain": "Бизнесу обещают «внедрение ERP за год и миллион»: лицензии, интеграторы, графики. На деле вы покупаете чужую логику, которую всё равно переделываете под себя, и зависите от вендора.",
        "chain": [
          "plan",
          "todo",
          "task",
          "write",
          "edit",
          "bash",
          "eval",
          "lsp",
          "recall",
          "hub_start"
        ],
        "steps": [
          "Завести проект харнесса: один раздел на весь контур — учёт, заказы, отчёты.",
          "Вместе с агентом описать предметную область: сущности, связи, правила — текстом, а не «требованиями для подрядчика».",
          "Собрать каркас БД и API генератором кода, проверить связи графом.",
          "Прогонять каждую задачу отдельной подзадачей: статус, прогресс, результат в панели.",
          "Сводки в чат вместо графиков: утром три варианта с цифрами, а не сорок сообщений.",
          "Отдать повторяющееся агентам-исполнителям через hub, себе оставить решения."
        ],
        "numbers": {
          "time": "контур учёта и заказов — недели, не год",
          "cost": "без лицензий и интеграторов",
          "scale": "1 владелец + агенты = контур, который раньше держала команда",
          "risk": "низкий: всё локально, журнал с проверкой цепи, откат к любой точке"
        },
        "measured": false,
        "result": "Харнесс — это и есть ERP-контур: единое окно, проект-раздел, сводки в чат. Внедрять нечего — он уже собран и проверяется на реальных прогонах."
      },
      {
        "id": "gruzoperevozki",
        "niche": "Логистика и грузоперевозки",
        "title": "Перевозчик, у которого телефон молчит",
        "pain": "Заказы — в звонках и чатах: диспетчер переспрашивает, водитель занят, клиент ждёт. Каждый сегмент дороги живёт в голове у одного человека — выпал он, встала вся цепочка.",
        "chain": [
          "plan",
          "todo",
          "task",
          "hub_start",
          "hub_send",
          "browser",
          "write",
          "recall",
          "web_search"
        ],
        "steps": [
          "Завести профиль компании: услуги, зоны, тарифы, свободные/занятые машины.",
          "Научить агента отвечать на заявки: сроки, цена, что нужно от клиента.",
          "Назначить оператора-агента: входящие звонки и сообщения разбираются, бронь ставится в календарь.",
          "Подключить соцсети: заявки оттуда попадают в тот же контур.",
          "Сводка в конце дня: что взято, что в работе, где узкое место."
        ],
        "numbers": {
          "time": "приём заявки — минуты вместо часов переписки",
          "cost": "диспетчер не нужен на каждый рейс",
          "scale": "до десятков заказов в день на одного владельца",
          "risk": "средний: агент отвечает клиентам — нужен допуск на внешние действия"
        },
        "measured": false,
        "result": "Клиенты получают ответ и бронь без ожидания, водители — маршрут, владелец — сводку вместо хаоса в мессенджерах."
      },
      {
        "id": "kontent-zavod",
        "niche": "Развлечения и контент",
        "title": "Контент-завод: сценарий → ролик → пост",
        "pain": "Контент ест дни: сценарий, съёмка или рендер, монтаж, тексты, постинг. Один ролик — неделя ручной работы, а площадок пять.",
        "chain": [
          "write",
          "edit",
          "generate_image",
          "inspect_image",
          "bash",
          "task",
          "hub_start",
          "web_search"
        ],
        "steps": [
          "Агенту пишется сценарий: тема, структура, реплики, тайминги.",
          "Видео собирается видеопровайдером по сценарию — ролик, а не слайды.",
          "Кадры проверяются глазами (inspect_image), текст — на стиль и факты.",
          "Готовый ролик + тексты постов для каждой площадки.",
          "Постинг по расписанию: площадки получают своё, без ручного дублирования."
        ],
        "numbers": {
          "time": "ролик — часы, не неделя",
          "cost": "без студии и монтажёра",
          "scale": "поток из десятков роликов в месяц силами одного человека",
          "risk": "средний: API видеопровайдеров меняются — нужна проверка фактического API"
        },
        "measured": false,
        "result": "Один человек держит контент-конвейер: от сценария до публикаций на всех площадках. Провайдеры подключаются как адаптеры — как MCP-серверы в харнессе."
      },
      {
        "id": "medicina-nauka",
        "niche": "Медицина",
        "title": "Медицина и наука: документы вместо рутины",
        "pain": "Исследование, обзор, отчёт — это недели на чтение, выписки и оформление. Врач и учёный тратят время на формат, а не на суть.",
        "chain": [
          "fetch",
          "read",
          "write",
          "edit",
          "task",
          "recall",
          "retain",
          "web_search"
        ],
        "steps": [
          "Статьи и данные собираются: чтение, извлечение фактов, ссылки.",
          "Обзор структурируется: вопрос → метод → результаты → выводы.",
          "Отчёт пишется по шаблону сферы, правки — по месту, в том же проекте.",
          "Непроверенное помечается как непроверенное — в доверенную память не идёт.",
          "Повторные обзоры опираются на память проекта: не начинаются с нуля."
        ],
        "numbers": {
          "time": "обзор литературы — дни, не месяцы",
          "cost": "только время модели и электроэнергия",
          "scale": "десятки источников обрабатываются параллельно",
          "risk": "низкий для черновика; публикация — всегда за человеком"
        },
        "measured": false,
        "result": "Документация перестаёт быть узким местом: учёный отвечает за смысл, харнесс — за сбор, оформление и память проекта."
      },
      {
        "id": "proizvodstvo",
        "niche": "Производство",
        "title": "Цех: наряд-заказы и остатки без «бумаг»",
        "pain": "Заказ пришёл — а где материал, что уже сделано, кто свободен? Учёт в тетради или таблице, которая живёт у одного мастера.",
        "chain": [
          "todo",
          "task",
          "write",
          "edit",
          "bash",
          "eval",
          "recall",
          "hub_start"
        ],
        "steps": [
          "Завести карточки: станки, материалы, сроки, нормы.",
          "Наряд-заказ создаётся текстом — агент раскладывает его на операции.",
          "Движение материалов фиксируется в проекте, остатки считаются сами.",
          "Свободные руки и станки видны в статусах задач.",
          "Вечерняя сводка: что в работе, что готово, где затык."
        ],
        "numbers": {
          "time": "учёт — по ходу, не в конце недели",
          "cost": "без 1С-проекта и внедренца",
          "scale": "десятки наряд-заказов в месяц на одно окно",
          "risk": "низкий: данные локальные, журнал действий проверяем"
        },
        "measured": false,
        "result": "Мастер видит цех целиком из одного окна: остатки, загрузка, сроки — и может предъявить след каждого действия."
      },
      {
        "id": "uslugi",
        "niche": "Услуги",
        "title": "Клиентский сервис без «сейчас перезвоню»",
        "pain": "Заявки из звонков, почты и мессенджеров; ответы повторяются; никто не помнит, что обещал. Клиент ждёт — сервис теряет.",
        "chain": [
          "hub_start",
          "hub_send",
          "browser",
          "write",
          "task",
          "recall",
          "web_search"
        ],
        "steps": [
          "Заявки стекаются в один контур из всех каналов.",
          "База знаний услуг и ответов собирается агентом из ваших материалов.",
          "Ответы готовятся по базе, сложное — поднимается человеку.",
          "Статусы и договорённости — в проекте, ничего не теряется.",
          "Сводка: сколько заявок, какие закрылись сами, где нужен человек."
        ],
        "numbers": {
          "time": "ответ — минуты, не «до конца дня»",
          "cost": "без call-центра и CRM-подписки",
          "scale": "сотни обращений в месяц на одного владельца",
          "risk": "низкий: агент готовит, человек подтверждает"
        },
        "measured": false,
        "result": "Клиент получает ответ и видит статус, владелец — сводку вместо беготни по чатам."
      },
      {
        "id": "stroitelstvo",
        "niche": "Строительство",
        "title": "Прораб: смета, сроки, подрядчики в одном окне",
        "pain": "Смета в Excel, сроки в голове, подрядчики в телефонной книге. Один срыв — и пересчёт руками, а виноват всегда прораб.",
        "chain": [
          "plan",
          "todo",
          "task",
          "write",
          "edit",
          "eval",
          "hub_start",
          "recall"
        ],
        "steps": [
          "Объект — проект: этапы, материалы, суммы, ответственные.",
          "Смета собирается из актуальных цен, правки — текстом.",
          "Подрядчикам уходят заявки и статусы через агентов-исполнителей.",
          "Движение денег и материалов — в журнале с проверкой цепи.",
          "Отчёт для заказчика собирается из фактов проекта, не из памяти."
        ],
        "numbers": {
          "time": "смета и план — часы, не дни",
          "cost": "без проектного отдела",
          "scale": "несколько объектов параллельно, у каждого своя история",
          "risk": "средний: внешние подрядчики — допуск на отправку заявок нужен"
        },
        "measured": false,
        "result": "Прораб ведёт объекты из одного окна: сметы, сроки, деньги — и каждый шаг можно предъявить."
      },
      {
        "id": "arhitektura",
        "niche": "Архитектура",
        "title": "Архитектор: варианты и документация без ночей",
        "pain": "Клиенту нужны варианты, а каждый эскиз — часы работы. Документация съедает время, которое должно уходить на замысел.",
        "chain": [
          "generate_image",
          "inspect_image",
          "write",
          "edit",
          "task",
          "fetch",
          "recall",
          "web_search"
        ],
        "steps": [
          "Задание клиента превращается в краткое описание-бриф.",
          "Варианты генерируются и проверяются глазами, правки — по месту.",
          "Пояснительная записка и спецификации собираются из карточек проекта.",
          "История вариантов хранится: клиент видит, как росла идея.",
          "Финальный набор — пакет документов, готовый к отправке."
        ],
        "numbers": {
          "time": "первые варианты — часы, не недели",
          "cost": "без студии-подрядчика на этапе эскизов",
          "scale": "несколько проектов параллельно, память никого не теряет",
          "risk": "низкий: финальные чертежи и решения — за человеком"
        },
        "measured": false,
        "result": "Архитектор отдаёт генерацию вариантов и рутину документации харнессу, а сам занимается замыслом."
      },
      {
        "id": "torgovlya",
        "niche": "Торговля",
        "title": "Магазин: цены, остатки и витрина без ручного труда",
        "pain": "Товаров сотни, цены меняются, остатки разъезжаются. Обновлять витрину вручную — вечер уходит на таблицы.",
        "chain": [
          "write",
          "edit",
          "bash",
          "eval",
          "fetch",
          "task",
          "recall"
        ],
        "steps": [
          "Каталог товаров заводится из вашего файла — без ручного ввода.",
          "Цены и остатки обновляются по расписанию из источника.",
          "Витрина (сайт/канал) пересобирается генератором при изменении.",
          "Сводка продаж и остатков — утром, цифрами.",
          "Списание и переоценка — задача агенту, след в журнале."
        ],
        "numbers": {
          "time": "обновление витрины — минуты, не вечер",
          "cost": "без дорогой товароучётной системы",
          "scale": "сотни позиций на одного владельца",
          "risk": "низкий: публикация — после подтверждения"
        },
        "measured": false,
        "result": "Витрина живёт из данных, а не из рук: цены и остатки не врут, владелец видит цифры."
      },
      {
        "id": "obrazovanie",
        "niche": "Образование",
        "title": "Преподаватель: курс, задания, проверка",
        "pain": "Курс нужно собрать, задания проверить, обратную связь дать каждому. На группу — вечера ручной работы.",
        "chain": [
          "write",
          "edit",
          "task",
          "read",
          "fetch",
          "recall",
          "retain",
          "hub_start"
        ],
        "steps": [
          "Материалы курса собираются в проект: структура, конспекты, источники.",
          "Задания формируются по теме и уровню группы.",
          "Работы учеников проверяются по критериям, замечания — конкретные.",
          "Обратная связь каждому — из той же проверки, без переписывания.",
          "Память по ученику: что прошли, что западает — в следующем занятии."
        ],
        "numbers": {
          "time": "проверка группы — часы, не дни",
          "cost": "без ассистента",
          "scale": "несколько курсов и групп параллельно",
          "risk": "низкий: итоговая оценка — за преподавателем"
        },
        "measured": false,
        "result": "Преподаватель собирает курс и проверяет работы в разы быстрее, а память подсказывает, кому что повторить."
      },
      {
        "id": "nauka",
        "niche": "Наука",
        "title": "Исследователь: обзор и гипотезы из источников",
        "pain": "Статей тысячи, времени нет, а выводы нужны сегодня. Читать всё руками — нереально, верить одному обзору — опасно.",
        "chain": [
          "web_search",
          "fetch",
          "read",
          "write",
          "task",
          "recall",
          "retain"
        ],
        "steps": [
          "Запрос превращается в список источников с проверкой достоверности.",
          "Ключевые статьи читаются, факты и цифры выписываются со ссылками.",
          "Синтез: что сходится, что противоречит, где пробелы.",
          "Черновик вывода — с пометками об источнике каждой цифры.",
          "Память проекта хранит прочитанное: следующий обзор не начинается с нуля."
        ],
        "numbers": {
          "time": "первичный обзор — дни",
          "cost": "только доступ к источникам",
          "scale": "десятки источников параллельно",
          "risk": "средний: нужна проверка фактов человеком — модель не источник истины"
        },
        "measured": false,
        "result": "Учёный получает карту источников и черновик вывода за дни, с честными пометками, где проверки нет."
      },
      {
        "id": "obraz-zhizni",
        "niche": "Образ жизни",
        "title": "Личный проект: от идеи до привычки",
        "pain": "Цели есть, дисциплины нет: начал — бросил, начал — бросил. Причина не лень, а отсутствие системы, которая помнит и напоминает.",
        "chain": [
          "todo",
          "plan",
          "task",
          "retain",
          "recall",
          "write"
        ],
        "steps": [
          "Цель формулируется как проект: что значит «сделано».",
          "Путь разбивается на шаги с критериями — не «заниматься», а «30 минут, разминка + тяга».",
          "Каждый день — задача с проверкой: сделано / не сделано, без самообмана.",
          "Память хранит: что мотивировало, что срывало — и подсказывает.",
          "Недельная сводка: тренд, а не настроение."
        ],
        "numbers": {
          "time": "проверка дня — минута",
          "cost": "бесплатно, если харнесс уже стоит",
          "scale": "несколько целей параллельно, каждая видна",
          "risk": "низкий: система не наказывает, а показывает"
        },
        "measured": false,
        "result": "Цель становится проектом со статусами и памятью — привычка держится не на силе воли, а на системе."
      },
      {
        "id": "finansy",
        "niche": "Финансы",
        "title": "Личные и малые финансы: учёт, план, отчёт",
        "pain": "Деньги уходят, а куда — непонятно. Сводить банки и кассы руками — вечер раз в месяц, который вечно откладывается.",
        "chain": [
          "write",
          "edit",
          "eval",
          "bash",
          "task",
          "recall",
          "retain"
        ],
        "steps": [
          "Выписки и кассы складываются в один проект — без ручного ввода.",
          "Категории и правила разбора задаются один раз.",
          "Месячный отчёт собирается сам: доход, расход, остатки, тренды.",
          "План и факт — рядом: где разошлись, видно сразу.",
          "Решение (закупка, найм) — задача с цифрами, а не «как-нибудь»."
        ],
        "numbers": {
          "time": "месячный отчёт — минуты",
          "cost": "без подписки на финансовый сервис",
          "scale": "личные и малые бизнес-финансы в одном окне",
          "risk": "низкий: данные локальные, журнал проверяем"
        },
        "measured": false,
        "result": "Финансы видны цифрами, а не тревогой: план и факт сходятся, решения опираются на данные."
      },
      {
        "id": "restorany",
        "niche": "Рестораны и общепит",
        "title": "Точка общепита: меню, закупки, смена",
        "pain": "Меню устарело, закупки на глаз, смена — в головах. Продукт портится, гость ждёт, владелец ночами сводит цифры.",
        "chain": [
          "plan",
          "todo",
          "task",
          "write",
          "edit",
          "eval",
          "recall",
          "hub_start"
        ],
        "steps": [
          "Меню и рецептуры — карточки: состав, себестоимость, выход.",
          "Закупки считаются от плана продаж и остатков, не от памяти.",
          "Смена: задачи поварам и официантам со статусами.",
          "Себестоимость блюд пересчитывается при изменении цен поставщиков.",
          "Сводка дня: продажи, списания, узкие места."
        ],
        "numbers": {
          "time": "пересчёт себестоимости — мгновенно",
          "cost": "без дорогой R-Keeper-подписки",
          "scale": "одна точка или сеть — структура та же",
          "risk": "низкий: публикация меню — после подтверждения"
        },
        "measured": false,
        "result": "Рецептуры, закупки и смены в одном окне: меньше списаний, понятная себестоимость, гости не ждут."
      },
      {
        "id": "selskoe-hozyaystvo",
        "niche": "Сельское хозяйство",
        "title": "Хозяйство: посевы, закупки, сезонный план",
        "pain": "Сезон один раз в год, ошибка в закупке — потерянный год. Журналы на бумаге, память одного агронома.",
        "chain": [
          "plan",
          "todo",
          "task",
          "write",
          "edit",
          "bash",
          "recall",
          "web_search"
        ],
        "steps": [
          "Участки и культуры — карточки с историей сезонов.",
          "План работ на сезон: что, когда, чем, кем.",
          "Закупки семян/удобрений считаются от плана и остатков.",
          "Погодные и ценовые сводки собираются по расписанию.",
          "После сезона — разбор: что сработало, что повторить, что убрать."
        ],
        "numbers": {
          "time": "план сезона — дни, не месяцы бумаг",
          "cost": "без агро-софта с ежегодной лицензией",
          "scale": "одно хозяйство или несколько полей — структура та же",
          "risk": "низкий: рекомендации — человеку, решения за ним"
        },
        "measured": false,
        "result": "Сезон ведётся по плану с памятью прошлых лет — ошибки закупок и забытые работы перестают быть сюрпризом."
      },
      {
        "id": "marketing",
        "niche": "Маркетинг и реклама",
        "title": "Маркетолог: кампании, площадки, отчёт по фактам",
        "pain": "Кампании в пяти кабинетах, отчёты собираются вручную, «эффективность» — из ощущений, а не из цифр.",
        "chain": [
          "web_search",
          "fetch",
          "write",
          "eval",
          "bash",
          "task",
          "recall",
          "hub_start"
        ],
        "steps": [
          "Все кабинеты и площадки — в одном контуре, данные стягиваются.",
          "Кампания — проект: бюджет, гипотеза, сроки, ответственный.",
          "Показатели собираются по расписанию, без ручной выгрузки.",
          "Отчёт — фактами: охват, цена контакта, конверсия, что менять.",
          "Память держит связки: что сработало на этой аудитории — не тестируется заново."
        ],
        "numbers": {
          "time": "отчёт — минуты, не вечер таблиц",
          "cost": "без рекламной платформы-агрегатора",
          "scale": "десятки кампаний и площадок в одном окне",
          "risk": "средний: расход бюджета — действия с допуском человека"
        },
        "measured": false,
        "result": "Маркетинг виден цифрами и связками: что закупать, где резать — решается данными, а не ощущением."
      },
      {
        "id": "nedvizhimost",
        "niche": "Недвижимость",
        "title": "Агент: объекты, показы, сделка без потерь",
        "pain": "Объекты в головах и чатах, показы накладываются, документы теряются. Один забытый звонок — сорванная сделка.",
        "chain": [
          "todo",
          "task",
          "write",
          "browser",
          "hub_start",
          "recall",
          "web_search"
        ],
        "steps": [
          "Объект — карточка: параметры, цена, документы, история.",
          "Показы и звонки — задачи со статусами и напоминаниями.",
          "Актуальность цен и объявлений проверяется по площадкам.",
          "Чек-лист сделки: ни один документ не забыт.",
          "Сводка дня: что показано, что в работе, что требует решения."
        ],
        "numbers": {
          "time": "ведение объекта — минуты в день",
          "cost": "без CRM-подписки",
          "scale": "десятки объектов параллельно, память не теряет",
          "risk": "низкий: отправка внешних сообщений — с допуском"
        },
        "measured": false,
        "result": "Агент держит все объекты и сделки из одного окна: ничего не забыто, каждое действие можно предъявить."
      },
      {
        "id": "transport",
        "niche": "Транспорт и доставка",
        "title": "Доставка: маршруты, статусы, клиент в курсе",
        "pain": "Курьеры разъезжаются, клиенты звонят «где заказ?», маршруты строятся на глаз. Пик — хаос на телефоне.",
        "chain": [
          "hub_start",
          "hub_send",
          "browser",
          "write",
          "task",
          "recall"
        ],
        "steps": [
          "Заказы доставки — задачи: адрес, окно, вес, курьер.",
          "Маршруты предлагаются исходя из заказов дня.",
          "Клиент получает статус сам: принят, едет, доставлен.",
          "Курьеры видят свои задачи; сводка — у диспетчера.",
          "Опоздания видны заранее — переброска до того, как клиент позвонил."
        ],
        "numbers": {
          "time": "статус клиенту — сам, без звонков",
          "cost": "без платной TMS",
          "scale": "десятки выездов в день на диспетчера",
          "risk": "низкий: внешние сообщения — с допуском владельца"
        },
        "measured": false,
        "result": "Доставка едет по статусам: клиент в курсе, диспетчер видит картину, опоздания ловятся заранее."
      },
      {
        "id": "remont",
        "niche": "Ремонт и обслуживание",
        "title": "Ремонтная служба: заявки, запчасти, выезды",
        "pain": "Заявки по телефону, запчасти кончаются в самый нужный момент, мастера ездят неоптимально.",
        "chain": [
          "todo",
          "task",
          "write",
          "edit",
          "hub_start",
          "recall"
        ],
        "steps": [
          "Заявка — карточка: что, где, когда, кто едет.",
          "Склад запчастей — остатки, минимум, заказ при пороге.",
          "Выезды группируются по адресам и срочности.",
          "История объекта: что чинили, чем, когда — перед выездом видна.",
          "Сводка: загруженность мастеров, повторные вызовы, узкие места."
        ],
        "numbers": {
          "time": "заявка и выезд — минуты на оформление",
          "cost": "без сервисного софта",
          "scale": "несколько мастеров, сотни заявок в месяц",
          "risk": "низкий: рекомендации человеку, решения за ним"
        },
        "measured": false,
        "result": "Служба видит заявки, склад и мастеров из одного окна — меньше холостых выездов и повторных вызовов."
      },
      {
        "id": "sport",
        "niche": "Спорт и фитнес",
        "title": "Клуб: расписание, клиенты, загрузка зала",
        "pain": "Расписание в таблице, абонементы в голове, зал то пустует, то переполнен. Тренер — администратор, а не тренер.",
        "chain": [
          "todo",
          "task",
          "write",
          "edit",
          "eval",
          "hub_start",
          "recall"
        ],
        "steps": [
          "Расписание — проект: группы, тренеры, залы, время.",
          "Клиенты и абонементы — карточки с историей посещений.",
          "Загрузка залов видна по статусам записи.",
          "Напоминания о занятии уходят сами.",
          "Сводка месяца: заполняемость, отмены, доход по группам."
        ],
        "numbers": {
          "time": "расписание и записи — минуты",
          "cost": "без фитнес-CRM",
          "scale": "несколько групп и залов параллельно",
          "risk": "низкий: уведомления клиентам — с допуском"
        },
        "measured": false,
        "result": "Клуб видит загрузку и клиентов цифрами — тренер снова тренирует, а не ведёт таблицы."
      },
      {
        "id": "ii-otdel-prodazh",
        "niche": "Продажи и лидогенерация",
        "title": "ИИ-отдел продаж: заявки из Telegram-чатов",
        "pain": "Клиенты пишут «нужен специалист» в профильных чатах, и найти это можно только листая ленту руками. Час-два в день на десять чатов, а запрос живёт недолго: написанный в 11:20 к 14:00 уже закрыт — человек договорился с тем, кто ответил первым.",
        "chain": [
          "browser",
          "fetch",
          "task",
          "hub_start",
          "eval",
          "retain",
          "recall",
          "plan"
        ],
        "steps": [
          "Дешёвая модель читает сотни сообщений в профильных чатах и выбрасывает спам, рекламу, болтовню и тех, кто сам продаёт услуги; остальному ставит оценку 1–3 — насколько это похоже на запрос клиента.",
          "Сильная модель перечитывает отобранное в оригинале и решает: лид или нет, — работая по десятку сообщений, а не по сотням.",
          "Черновик первого сообщения пишется в стиле владельца по его эталонным примерам и ложится готовым текстом в личные чаты.",
          "Отправляет человек своей рукой: клиенту отвечает живой человек, бот только готовит текст.",
          "Сканы идут по расписанию несколько раз в день — запрос не успевает остыть.",
          "Диалог заводится в CRM, вечером сверка личных чатов с воронкой: начатый и забытый разговор не теряется."
        ],
        "numbers": {
          "time": "разбор ленты идёт по расписанию, а не часами вручную",
          "cost": "отсев сотен сообщений — на дешёвой модели, сильная работает только по отобранному",
          "scale": "один владелец и четыре агента вместо отдела продаж",
          "risk": "низкий: отправляет человек, бот не пишет клиенту сам"
        },
        "measured": false,
        "result": "Схема разобрана и перенесена из открытого разбора автора канала NEXTGEN AI (ainextgen.ru, октябрь 2026): у него выходит 9–10 заявок в день при чеке 35–180 тыс. ₽, и это заявки, а не подписанные договоры — часть отваливается по бюджету. Цифры чужого контура, поэтому помечены как оценка. В харнессе связка собирается из инструментов каталога: чтение чатов браузером, дешёвая модель на отсев подзадачей, сильная — на черновик, память — вместо забытой CRM."
      },
      {
        "id": "kompaniya-v-odnom-okne",
        "niche": "Управление компанией",
        "title": "Компания в одном окне: двенадцать процессов без ручной сборки",
        "pain": "Компания растёт направлениями — розница, опт, сервис, поставки, — а управление держится на людях и таблицах. Деньги: дебиторка живёт без связки «сумма / срок / просрочка / ответственный». Тендеры: документация и номенклатура пересчитываются руками, рентабельность позиции не считается, контура «подал → выиграл → исполнил → закрыл» нет. Люди: показатели считаются, но без апелляции и без внешних причин. Данные: цены пяти-семи магазинов сводятся вручную, обращения из тендеров, соцсетей и офлайна лежат раздельно, а 1С и CRM, скорее всего, расходятся. Ничего из этого не видно в одном месте — поэтому каждое решение начинается со сбора данных, а не с решения.",
        "chain": [
          "read",
          "write",
          "edit",
          "eval",
          "task",
          "plan",
          "todo",
          "recall",
          "retain",
          "hub_start"
        ],
        "steps": [
          "Собрать входные данные: стек и версия 1С, способ интеграции, оргструктура, формулы KPI, справочники, согласие на обработку данных сотрудников. Это единственная внешняя зависимость: без неё календарь не стартует.",
          "Подключить источники только на чтение: ключ вводит владелец, наружу отдаётся признак «задан / не задан».",
          "Собрать единую модель: подразделение, сотрудник, клиент, сделка, тендер, закупка, дебиторка, план. Одна сущность — один источник истины; расхождение 1С и CRM показывается как конфликт, а не затирается.",
          "Посчитать метрики по формулам компании: оборот, маржа, план и факт, доля просроченной, win-rate, цикл тендера. Формулы — данные, а не код: свои формулы подключаются без переделки.",
          "Построить карту слабых зон: вес зоны = отклонение от цели × значимость показателя; у зоны видно следствие и то, какого числа не хватает.",
          "Добавлять направления модулями — розница, склад, логистика, сервис, — не ломая уже работающий пилот.",
          "Отдать повторяющееся агентам: сбор, сверку, напоминания. За человеком остаются решения и разговоры."
        ],
        "numbers": {
          "time": "пилот — 4–6 недель после выгрузки; полное покрытие направлений — около 5–6 месяцев (оценка)",
          "cost": "эффект в рублях считается по формулам компании, а не по обещаниям",
          "scale": "двенадцать процессов и все направления в одном окне; направления добавляются модулями",
          "risk": "низкий: доступ только на чтение, ключи у владельца, расхождения видны, а не затираются"
        },
        "measured": false,
        "result": "Пилот не нужно писать с нуля: каркас уже работает на демо-данных, включается реальный источник. Дальше — расширения модели, затем направления, которым нужны новые сущности; внешние направления идут параллельно. Числа в примерах — демо-набор: это механика расчёта, а не обещание суммы. Эффект в рублях считается по формулам компании и только после выгрузки; до неё ни один показатель компании не показывается без пометки «демо».",
        "sections": [
          {
            "title": "Решение: четыре контура в одном окне",
            "meta": "рассказ · блок 3",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-contours.webp",
                  "alt": "Четыре лотка с разным крепежом на верстаке: у каждого контура своё место"
                }
              },
              {
                "t": "p",
                "v": "Раздел «Компания» — один экран вместо папки с таблицами. Четыре контура: подключения, единая модель, метрики и карта зон, люди. У каждого своё правило — и правила здесь и есть разница между отчётом и системой."
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-company-contours.svg",
                  "alt": "Четыре контура раздела «Компания» и правило каждого"
                }
              },
              {
                "t": "p",
                "v": "Справочники, метрики и правила компания добавляет сама через интерфейс: чтобы завести новый показатель или точку, не нужно переписывать ядро."
              }
            ]
          },
          {
            "title": "На чём это стоит: paps harness",
            "meta": "рассказ · блок 4",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-harness.webp",
                  "alt": "Домашняя мастерская: сверлильный станок и точило на верстаке, инструменты на стене"
                }
              },
              {
                "t": "p",
                "v": "Харнесс — это система вокруг модели, а не чат. Панель, домены, ядро с правилами и агент, который работает в своём рабочем дереве. Процессы добавляются модулями: новый не ломает уже работающий."
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-harness.svg",
                  "alt": "Схема paps harness: панель, домены, ядро, агент и шлюз моделей"
                }
              },
              {
                "t": "ol",
                "v": [
                  "лидогенерация и ведение каналов: обращения из тендеров, соцсетей и офлайна идут одной воронкой",
                  "задачи: поручение разбирается на подзадачи и проходит ревью, а не теряется в переписке",
                  "память проекта и граф кода: агент видит связи, а не один файл",
                  "ключи и модели: проба ключа, переключение провайдера без остановки работы",
                  "журнал с проверкой цепи: ход работы можно предъявить, а не пересказать"
                ]
              }
            ]
          },
          {
            "title": "Боль владельца: пять кластеров",
            "meta": "рассказ · блок 2",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-pains.webp",
                  "alt": "Стол с неразобранными папками, чеками и стопкой планшетов — ручная работа"
                }
              },
              {
                "t": "p",
                "v": "Деньги, тендеры, люди, каналы и данные, то, что видно снаружи. Это формулировки владельца и наблюдения из открытых источников — не наши выводы о вашей работе."
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-pains.svg",
                  "alt": "Пять кластеров боли владельца"
                }
              },
              {
                "t": "p",
                "v": "Первые двенадцать болей — гипотезы из заметок и ТЗ. Они проверяются на выгрузке; что не подтвердится — не попадает в карту зон."
              }
            ]
          },
          {
            "title": "Сценарии по направлениям",
            "meta": "рассказ · блок 5",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-processes.webp",
                  "alt": "Деревянная сортировка с ячейками: чертежи в тубусах, коробки с деталями"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-processes.svg",
                  "alt": "Двенадцать процессов по направлениям и их статус"
                }
              },
              {
                "t": "kv",
                "v": [
                  [
                    "каркас",
                    "работает на демо-данных; включается реальным источником"
                  ],
                  [
                    "частично",
                    "модель есть, не хватает сущностей — поставщик, карточка клиента"
                  ],
                  [
                    "нет модуля",
                    "розница, склад, логистика, сервис — нужны новые сущности"
                  ]
                ]
              },
              {
                "t": "p",
                "v": "Вне этого домена уже работает лидогенерация и ведение каналов: в «Компанию» она входит агрегатом, а не второй копией данных."
              }
            ]
          },
          {
            "title": "Что уже работает, а что ждёт данных",
            "meta": "рассказ · блок 6",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-stages.webp",
                  "alt": "Собранный наполовину механизм: детали разложены в порядке сборки"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-stages.svg",
                  "alt": "Десять этапов: готово, после данных, от компании"
                }
              },
              {
                "t": "p",
                "v": "Этапы 1–7 проверены живьём: это не презентация, систему можно открыть на экране. Этап 0 — единственная внешняя зависимость. Пока нет выгрузки, называть календарные даты было бы выдумкой."
              }
            ]
          },
          {
            "title": "Календарь: от данных до полного покрытия",
            "meta": "сроки · оценка трудоёмкости",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-timeline.webp",
                  "alt": "Пустая сетка плана на стене, карандаш и линейка на полке"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-timeline.svg",
                  "alt": "Волны и сроки: от входных данных до внешних направлений"
                }
              },
              {
                "t": "p",
                "v": "Порядок — по зависимостям модели данных, а не по тому, что проще продать: сначала то, что уже работает каркасом, затем расширения модели, затем направления, которым нужны новые сущности. Внешние направления идут параллельно волнам."
              },
              {
                "t": "p",
                "v": "Сроки — оценка трудоёмкости в рабочих неделях. Календарь привязан к старту этапа 0: W1 — неделя после того, как пришли данные."
              }
            ]
          },
          {
            "title": "Показатели: что система считает и куда двигает",
            "meta": "демо-данные",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-metrics.webp",
                  "alt": "Штангенциркуль измеряет точеную деталь на плите, рядом микрометр"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-metrics.svg",
                  "alt": "Показатели: текущее значение и цель, полосы на одной шкале"
                }
              },
              {
                "t": "p",
                "v": "Эффект считается по формулам компании, а не по нашим допущениям: формула и значимость показателя — данные, которые можно поменять без правки кода. Где цель не задана компанией, зона не ранжируется и несёт пометку — вместо выдуманного числа."
              }
            ]
          },
          {
            "title": "Что это даёт в деньгах",
            "meta": "рассказ · блок 7",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-effect.webp",
                  "alt": "Латунные весы с пустыми чашами и стопка пустых квитанций на столе"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-effect.svg",
                  "alt": "Формула веса зоны и три демо-примера в рублях"
                }
              },
              {
                "t": "p",
                "v": "Отклонение считается в деньгах, а не в процентах: проценты не решают — решают рубли и сроки. Следствие зоны отвечает на вопрос «что теряется, если не трогать»."
              },
              {
                "t": "p",
                "v": "Суммы выше — демонстрация расчёта на демо-данных, а не обещание. На реальных данных они считаются по формулам компании и только после подключения источника."
              }
            ]
          },
          {
            "title": "Границы: что входит и что не входит",
            "meta": "границы объявлены заранее",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-scope.webp",
                  "alt": "Рабочая зона на полу, отмеченная клейкой лентой, рядом рулетка"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-scope.svg",
                  "alt": "Что входит в работу и что честно не входит"
                }
              },
              {
                "t": "p",
                "v": "Доступ к 1С и CRM — только чтение: ни один маршрут не пишет наружу. Ключ вводит владелец, наружу отдаётся признак «задан / не задан»."
              }
            ]
          },
          {
            "title": "Риски и как они закрываются",
            "meta": "риски названы заранее",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-risks.webp",
                  "alt": "Средства защиты на верстаке: очки, перчатки, наушники, аптечка"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-risks.svg",
                  "alt": "Пять рисков внедрения и способ закрытия каждого"
                }
              }
            ]
          },
          {
            "title": "Следующий шаг: шесть пунктов от компании",
            "meta": "рассказ · блок 8",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-next-step.webp",
                  "alt": "Планшет с пустым чек-листом из квадратов и карандаш на столе"
                }
              },
              {
                "t": "shot",
                "v": {
                  "file": "case-next-step.svg",
                  "alt": "Шесть пунктов этапа 0 и цепочка от демо к реальным числам"
                }
              },
              {
                "t": "p",
                "v": "После этого этапа фиксируется календарь: демо-набор меняется на реальные данные, а на следующей встрече видно карту слабых зон по вашим числам."
              }
            ]
          },
          {
            "title": "Границы честности: что пока не доказано",
            "meta": "проверяемость",
            "blocks": [
              {
                "t": "shot",
                "v": {
                  "file": "case-honesty.webp",
                  "alt": "Увеличительное стекло в латунной оправе на чистом листе бумаги"
                }
              },
              {
                "t": "ol",
                "v": [
                  "показатели компании — демо-числа: пока не пришла выгрузка, это демонстрация механики, а не замер",
                  "боли из заметок — гипотезы; они подтверждаются или снимаются на данных",
                  "ориентир склада «дольше семи дней» — из заметок владельца, нормативом не подтверждён",
                  "стек и версия 1С не подтверждены; принимается и API, и файловая выгрузка"
                ]
              },
              {
                "t": "p",
                "v": "Что проверяемо уже сейчас: домен отвечает на живые запросы, доступ — только чтение, и на каждом экране видно источник и период числа."
              }
            ]
          }
        ]
      }
    ]
  },
  "models": [
    {
      "id": "mentalnye-modeli",
      "title": "Ментальные модели (мета)",
      "essence": "Картинки в голове, через которые видно мир: чем их больше, тем больше решений видно без долгих размышлений. Мета-модель — про то, что сами модели можно учить и пополнять.",
      "example": "Мастер на глаз отличает годный металл от брака — у него картинка. Человек, который видел десять моделей, замечает, что две из них тянут в разные стороны, и решает, какая здесь главная.",
      "harness": "Харнесс держит модели там, где они нужны: в разделах, кейсах и объяснениях. Агент объясняет решение через модель — через выгоду и издержки, — а не через обещание.",
      "chain": [
        "think",
        "reflect",
        "write",
        "recall"
      ]
    },
    {
      "id": "stimuly",
      "title": "Стимулы",
      "essence": "Люди и системы делают то, что им выгодно, даже когда говорят другое. Решение работает, когда у действующего есть причина делать правильно — а не когда его просят.",
      "example": "Подрядчик «всё сделает» — но приходит вовремя, только если просрочка ему дорого стоит. Торговец ведёт честно, когда обман виден сразу.",
      "harness": "Харнесс построен на стимулах: проверка цепи делает след честным, квитанции памяти отделяют проверенное от непроверенного. Агенту выгодно быть точным — неточное не проходит дальше.",
      "chain": [
        "reflect",
        "ask",
        "retain",
        "recall"
      ]
    },
    {
      "id": "alternativnye-izderzhki",
      "title": "Альтернативные издержки",
      "essence": "Цена выбора — то, от чего ты отказался. Деньги, время и внимание, потраченные на одно, не придут из другого. Считается не «сколько стоит», а «что я не сделал».",
      "example": "Час ручного ввода в таблицу — час, не потраченный на заказчика. Дёшево «по деньгам» может быть дорого по жизни.",
      "harness": "Шаги и подзадачи показывают издержки выбора: каждое действие — задача с временем и результатом. Память хранит, на что ушло время, — и видно, где оно сгорает.",
      "chain": [
        "todo",
        "plan",
        "task",
        "reflect"
      ]
    },
    {
      "id": "problema-indeyki",
      "title": "Проблема индейки",
      "essence": "То, что было всегда, не гарантирует то, что будет: индейка тысячу дней сыта, а на тысяча первый — к обеду. Прошлое — не договор о будущем.",
      "example": "«Мы так всегда делали» — пока рынок не пошевелился. График, который всегда был ровным, не доказывает, что он останется ровным.",
      "harness": "Границы и пределы инструментов пишутся честно, измерения помечаются как измеренные, а не как вечные. То, что проверено вчера, в карточке не выдаётся за истину навсегда.",
      "chain": [
        "reflect",
        "ask",
        "eval",
        "bash"
      ]
    },
    {
      "id": "britva-okkama",
      "title": "Бритва Оккама",
      "essence": "Из двух объяснений выбирай то, что требует меньше допущений. Не потому что простое «правильнее», а потому что у него меньше мест, где можно ошибиться.",
      "example": "«Сломалось всё сразу» — проще проверить: не включается свет. Один предохранитель объясняет больше, чем заговор электриков.",
      "harness": "Каталог инструментов — это разреженный набор: одна тулза на семейство операций, без десятка похожих клонов. Инструмент делает одно и это видно.",
      "chain": [
        "think",
        "grep",
        "read",
        "write"
      ]
    },
    {
      "id": "izbegay-razoreniya",
      "title": "Избегай разорения",
      "essence": "Сначала не потеряй всё, потом думай о выигрыше. Один удар, который стирает тебя, сильнее любой череды успехов. Выживание — первая задача.",
      "example": "Ставка, при которой можно потерять дом, — не «риск», а самоуничтожение. Казино живёт на том, что игроки думают наоборот.",
      "harness": "Необратимое не делается без человека: публикация, внешние действия, опасные команды — за допуском. Правила запрещают по умолчанию, разрешают — списком.",
      "chain": [
        "ask",
        "security",
        "checkpoint",
        "vault"
      ]
    },
    {
      "id": "igra-s-nenulevoy-summoy",
      "title": "Игра с ненулевой суммой",
      "essence": "Выигрыш одного не обязан быть проигрышем другого. Есть сделки, где оба становятся богаче: обмен знаниями, доверие, совместная работа.",
      "example": "Мастер учит ученика — ученик берёт рутину, мастер берёт время. Оба в плюсе, в отличие от драки за кусок.",
      "harness": "Роль агента — не заменить человека, а снять с него ношу: человек выбирает, агент исполняет. Вместе дают больше, чем сумма — это прямая модель страницы.",
      "chain": [
        "task",
        "hub_start",
        "ask",
        "recall"
      ]
    },
    {
      "id": "falsifitsiruemost",
      "title": "Фальсифицируемость",
      "essence": "Утверждение научно, если можно придумать проверку, которая его опровергнет. «Всё будет хорошо» — не проверяется; «контур собирается за неделю» — проверяется.",
      "example": "«Лечит» не проверяется, пока нет способа увидеть, что не лечит. Тест, который не может провалиться, ничего не говорит.",
      "harness": "Каждая карточка каталога — с границей: как проверялось, что не умеет, что осталось за пределами. «Проверено» — это тест, который мог упасть и не упал.",
      "chain": [
        "eval",
        "bash",
        "todo",
        "reflect"
      ]
    },
    {
      "id": "principial-agent",
      "title": "Теория принципала–агента",
      "essence": "Принципал (владелец) передаёт работу агенту (исполнителю), но интересы у них не совпадают автоматически. Система должна делать так, чтобы агенту было выгодно служить принципалу.",
      "example": "Наёмный менеджер может тянуть в свою сторону, если его контроль — за результат, а не за процесс. Владелец видит цифры — и управляет по ним.",
      "harness": "Журнал, связанный хешами, и квитанции памяти — контроль принципала: каждое действие подписано и проверяемо. Секреты — в карантине, данные — у владельца.",
      "chain": [
        "ask",
        "todo",
        "security",
        "checkpoint"
      ]
    },
    {
      "id": "begi-v-goru",
      "title": "Беги в гору",
      "essence": "Делай то, что тяжело сейчас и легко потом: учиться, чинить долг, автоматизировать. В гору тяжело идти — но с горы потом легко катиться.",
      "example": "Разобрать склад сейчас — скучно; искать нужное каждый день потом — дороже. Порядок окупается не сегодня, а каждый день после.",
      "harness": "Харнесс встроен в эту модель: потратить время на настройку и память — чтобы потом рутина шла сама. Проект помнит себя — не приходится начинать с нуля.",
      "chain": [
        "goal",
        "plan",
        "todo",
        "retain"
      ]
    },
    {
      "id": "estestvenny-otbor",
      "title": "Естественный отбор",
      "essence": "Выживает не самый сильный, а тот, кто лучше приспособлен к условиям и успевает размножаться. В деле — выживают практики, которые реально работают.",
      "example": "Два мастера, одинаково талантливые: один учится у заказчиков, другой — нет. Через год у первого очередь, у второго — свободные дни.",
      "harness": "Инструменты проходят отбор реальными прогонами: что работает — остаётся с пометкой «проверено», что нет — честно называется тумблером или семейством. Отбор публичный.",
      "chain": [
        "task",
        "eval",
        "reflect",
        "todo"
      ]
    },
    {
      "id": "prisposablivaemost",
      "title": "Приспособляемость",
      "essence": "Ценность не в том, чтобы быть правым при неизменных условиях, а в том, чтобы оставаться полезным, когда условия меняются. Жёсткий план умирает первым.",
      "example": "Лавка, которая торговала только одним товаром, исчезла при первом кризисе; та, что перестраивалась, — выжила.",
      "harness": "Роутинг моделей и открытые адаптеры: провайдера можно менять, не перестраивая работу. Границы описаны — значит, известно, где система может прогнуться.",
      "chain": [
        "bash",
        "edit",
        "ask",
        "recall"
      ]
    },
    {
      "id": "slozhny-procent",
      "title": "Сложный процент",
      "essence": "Рост, который ложится на предыдущий рост: проценты на проценты. Маленькое и регулярное становится огромным — но только если успевает накопиться.",
      "example": "Копить по чуть-чуть каждый месяц незаметно, а через десять лет — дом. Пропущенный месяц съедает не одну копейку, а весь её будущий рост.",
      "harness": "Память и главы — сложный процент знаний: факты уходят в память, возвращаются в нужный момент и складываются. Каждая сессия начинается не с нуля, а с накопленного.",
      "chain": [
        "retain",
        "recall",
        "checkpoint",
        "task"
      ]
    },
    {
      "id": "kriticheskaya-massa",
      "title": "Критическая масса",
      "essence": "Есть порог, после которого процесс идёт сам: снежный ком, эпидемия, сеть. До порога — усилия, после — инерция. Всё решает не размер, а переход порога.",
      "example": "Пять подписчиков — рутина; пять тысяч — канал живёт сам: приводят, делятся, возвращаются. Разница не в старании, а в переходе порога.",
      "harness": "Кейсы — по одному на нишу, чтобы у каждой был свой мини-цикл «боль → связка → цифры». Когда накоплено достаточно — ниши ссылаются друг на друга и раздел начинает расти сам.",
      "chain": [
        "plan",
        "task",
        "write",
        "reflect"
      ]
    },
    {
      "id": "inertsiya",
      "title": "Инерция",
      "essence": "Тело, движущееся по прямой, продолжает двигаться, пока его не остановят: привычки, процессы, технологии живут дольше своей пользы. Менять их — тратить энергию.",
      "example": "«Так заведено» — и таблица в Excel живёт десять лет, хотя всем мешает. Остановить её — усилие, продолжить — ноль усилий.",
      "harness": "Списки задач и статусы делают инерцию видимой: что бросали, что тянется, где затык. Память напоминает о брошенном — иначе оно тащится вечно.",
      "chain": [
        "todo",
        "plan",
        "reflect",
        "recall"
      ]
    },
    {
      "id": "effekt-kolei",
      "title": "Эффект колеи",
      "essence": "Чем глубже колея, тем легче катиться по ней и тем труднее выйти. Хорошая практика — колея; плохая — тоже колея. Главный вопрос: куда ты накатал.",
      "example": "Код, который «работает, не трогай», — колея: каждый раз проще добавить костыль, чем выйти и переложить. Через год править уже страшно.",
      "harness": "Карты кода и граф связей показывают колею: правка идёт по структуре, а не по памяти. Ревью и границы ловят костыли до того, как они стали нормой.",
      "chain": [
        "lsp",
        "grep",
        "read",
        "ast_grep"
      ]
    },
    {
      "id": "nepredvidennye-posledstviya",
      "title": "Непредвиденные последствия",
      "essence": "У действия есть эффекты, которых не ждали: побочные, отложенные, на других. Даже простая правка дёргает соседнее — просто мы не всегда это видим.",
      "example": "Скидка ради продаж — и все привыкли ждать скидку. Новая дорога — и пробки переехали. Причина и следствие не всегда рядом.",
      "harness": "Правки идут после сверки связей по графу: изменил одно — видно, что заденет. Журнал фиксирует эффекты, чтобы они не были «непредвиденными» дважды.",
      "chain": [
        "lsp",
        "ast_grep",
        "grep",
        "read"
      ]
    },
    {
      "id": "nelineynost",
      "title": "Нелинейность",
      "essence": "Не всё растёт поровну: удвоение усилий может дать ноль или вчетверо. Зависимости, пороги, насыщение — мир редко бывает прямой линией.",
      "example": "Пятый час рекламы почти не добавляет продаж, а первый — добавляет всё. Усилие и результат расходятся, и это нормально.",
      "harness": "Ограничения по времени и выводу признают нелинейность: длинный процесс не обязан быть линейным, у каждого шага — свой вес. Измерения показывают, где кривая уходит вверх.",
      "chain": [
        "think",
        "task",
        "eval",
        "reflect"
      ]
    },
    {
      "id": "krug-kompetentsiy",
      "title": "Круг компетенций",
      "essence": "Знай, что ты знаешь, и знай, где твоя граница. Оптимально — внутри круга; у границы — осторожно; за кругом — не берись или берись с проверкой.",
      "example": "Сантехник починит кран, но не возьмётся за котёл — или возьмётся, зная цену ошибки. Дорого обходится не незнание, а незнание границы.",
      "harness": "«Проверено» и «оценка» — честный круг компетенций: где есть измерение, где его нет, написано на карточке. Границы инструментов — часть описания, а не приписка.",
      "chain": [
        "ask",
        "reflect",
        "read",
        "write"
      ]
    },
    {
      "id": "vtorichnye-posledstviya",
      "title": "Вторичные последствия",
      "essence": "Смотри на два шага вперёд: у решения есть следствия от следствий. То, что кажется выигрышем на первом ходе, часто проигрыш на втором.",
      "example": "Автоматизация ради скорости — и сотрудники перестали понимать процесс. Экономия на материале — и клиенты ушли. Первый ход выигран, партия — нет.",
      "harness": "Перед действием агент проверяет, что заденет правка (граф, связи, границы), а журнал пишет эффекты — чтобы вторичное не пришло вторично.",
      "chain": [
        "lsp",
        "grep",
        "think",
        "reflect"
      ]
    },
    {
      "id": "strategiya-shtangi",
      "title": "Стратегия штанги",
      "essence": "Держи два конца: очень безопасное и очень рискованное, — а середину избегай. Потери ограничены, выигрыш не ограничен; середняк часто хуже обоих.",
      "example": "Свободный мастер работает на себя (риск) и держит подушку (безопасность): если проект падает — подушка держит; если взлетает — весь выигрыш его.",
      "harness": "Локальные данные и карантин секретов — безопасный конец; открытые эксперименты и новые модели — рискованный. Средняя «облачная подписка на всё» — не выбор харнесса.",
      "chain": [
        "vault",
        "checkpoint",
        "bash",
        "think"
      ]
    },
    {
      "id": "svoya-shkura",
      "title": "Своя шкура на кону",
      "essence": "Тот, кто рискует своим, решает иначе, чем тот, кто рискует чужим. Ответственность за результат меняет качество решений сильнее любых регламентов.",
      "example": "Советник советует «купи», а сам не покупает — он не в игре. Мастер, который знает, что переделывать ему, делает один раз.",
      "harness": "Человек остаётся заказчиком: агент приносит варианты, выбор и ответственность — за человеком. Действия, меняющие состояние, требуют подтверждения — своя шкура в контуре.",
      "chain": [
        "ask",
        "todo",
        "reflect",
        "security"
      ]
    },
    {
      "id": "mashtabiruemost",
      "title": "Масштабируемость",
      "essence": "Сработает ли то же самое в десять раз больше? Ручное не масштабируется, процесс — да. Проверяется не размер, а способность расти без перестройки.",
      "example": "Пять клиентов ведёт один человек, пятьсот — уже нет: он тонет в рутине. Тот, кто построил процесс, ведёт и пятьсот — руками системы.",
      "harness": "Сессии и подсессии, главы памяти, hubs: один контур растёт на десятки задач без потери контекста. Кейсы построены так, чтобы ниши добавлялись без перестройки раздела.",
      "chain": [
        "task",
        "hub_start",
        "plan",
        "retain"
      ]
    },
    {
      "id": "hrupkost",
      "title": "Хрупкость",
      "essence": "Хрупкое ломается от удара, антихрупкое — крепнет от него. Важно не «как выглядит», а «что будет при ударе». Хрупкость часто прячется за гладким фасадом.",
      "example": "Завод с одним поставщиком компонента — фасад ровный, удар — и всё встало. Два поставщика — уже не так страшно.",
      "harness": "Откаты и контрольные точки, журнал с проверкой цепи: удар не стирает работу. Роутинг моделей: упал один провайдер — работает другой, без перестройки.",
      "chain": [
        "checkpoint",
        "bash",
        "git",
        "vault"
      ]
    },
    {
      "id": "optsionalnost",
      "title": "Опциональность",
      "essence": "Ценность — в праве выбора, а не в одном выбранном варианте. Дешёвая опция, которой можно не воспользоваться, часто дороже всего конкретного.",
      "example": "Держать место в двух проектах — «лишняя» опция, пока не сорвался первый. Тогда она — всё. То, что можно не использовать, даёт свободу.",
      "harness": "Модели ротируются по задаче, провайдеры меняются, правила настраиваются: у владельца остаются опции, а не один путь. Конфигурация — часть продукта, не привилегия.",
      "chain": [
        "custom",
        "edit",
        "bash",
        "think"
      ]
    }
  ],
  "manual": [
    {
      "id": "prodayushchaya-konsultaciya",
      "module": "Продающие консультации",
      "title": "Продающая консультация по структуре",
      "essence": "Созвон перестаёт быть разговором «посмотрим», когда у него есть структура: контакт, запрос, путь, препятствия, подтверждение, история, цена, закрытие. Харнесс держит эту структуру и следит, чтобы ни один шаг не потерялся.",
      "steps": [
        "Готовишься: карточка клиента, его запрос, продукт, цена, рассрочка — всё в проекте, а не в голове.",
        "На созвоне ведёшь по шагам структуры; заметки идят в журнал созвонов.",
        "Запись звонка расшифровывается и разбирается: где держал структуру, где сошёл с неё.",
        "Клиент уходит в один из сегментов после созвона — карточка получает сценарий работы.",
        "Скрипты возражений и шаблоны сообщений достаются из базы, а не вспоминаются на ходу."
      ],
      "chain": [
        "write",
        "edit",
        "read",
        "recall",
        "retain",
        "skill:transcribe-ru",
        "task",
        "todo"
      ],
      "result": "Структура на виду, ни один шаг не потерян, разбор после звонка — по фактам, а не по памяти."
    },
    {
      "id": "job-s-zayavkami",
      "module": "Продающие консультации",
      "title": "Работа с заявками после созвона: четыре сценария",
      "essence": "Главное в продаже — не созвон, а то, что после него. Каждый клиент попадает в один из четырёх сегментов (готов платить / подумать / не тянет / не интересно), и у каждого — своя коммуникация. Держать четыре очереди в голове нельзя — их держит система.",
      "steps": [
        "После каждого созвона клиент раскладывается по сегменту — карточка со статусом и сценарием.",
        "«Готов платить» — ссылка на оплату сразу, без лишних слов.",
        "«Подумает» — напоминание в задачи и долгосрочные касания по расписанию.",
        "Бронь — якорь обязательства: дата окончания ставится в календарь, напоминания уходят сами.",
        "Сводка в конце дня: кто где, кому писать, кому не надо."
      ],
      "chain": [
        "todo",
        "task",
        "write",
        "recall",
        "hub_start",
        "hub_send",
        "read"
      ],
      "result": "Четыре очереди ведёт система: никто не забыт, брони не протухают, клиенту пишут точно в срок."
    },
    {
      "id": "trenirovka-prodazh",
      "module": "Продающие консультации",
      "title": "Тренировка продаж на нейросети: клиент-бот",
      "essence": "Продажи — навык, который натаскивается повторением: клиент-бот отыгрывает возражения, ты ведёшь структуру, после — разбор слабых мест. Копейки на токены вместо потерянных лидов на живых созвонах.",
      "steps": [
        "Задаёшь нейросети промт: аудитория, продукт, чек, желание клиента, возражения.",
        "Голосовой режим: нейросеть играет клиента, ты ведёшь продажу.",
        "Сценарий с реальным клиентом: вопросы, оффер, возражения, цена, закрытие.",
        "После тренировки — честный разбор: где закрывал, где смазал, что улучшить.",
        "Повторяешь конкретное возражение, пока не перестанешь спотыкаться."
      ],
      "chain": [
        "write",
        "edit",
        "eval",
        "skill:transcribe-ru",
        "task",
        "recall",
        "retain"
      ],
      "result": "Десятки тренировок до первых реальных звонков: на живом клиенте ведёшь спокойно, а не выживаешь."
    },
    {
      "id": "lid-magnit",
      "module": "Лид-магнитная воронка",
      "title": "Лид-магнит: видео → страница → бот → заявка",
      "essence": "Лид-магнит — бесплатная ценность, которая забирает контакт: видео с обложкой, своя страница, бот с серией сообщений, заявка на консультацию. Каждый элемент собирается по шагам, а харнесс держит все шаги и материалы вместе.",
      "steps": [
        "Видео заливается на хостинг, обложка собирается нейросетью или в редакторе.",
        "Страница лид-магнита: заголовок, видео, форма, кнопка — на своём домене.",
        "Бот собирается под платформу (Telegram, VK, MAX) — серия сообщений с ценностью.",
        "Заявка из бота попадает в общий поток: задача, карточка, статус.",
        "Реклама ведёт на лид-магнит, аналитика замыкается метрикой."
      ],
      "chain": [
        "write",
        "edit",
        "bash",
        "generate_image",
        "inspect_image",
        "browser",
        "task",
        "web_search"
      ],
      "result": "Воронка собирается по шагам без потери материалов: видео, страница, бот и заявки — в одном контуре."
    },
    {
      "id": "priem-oplat",
      "module": "Приём оплат и рассрочки",
      "title": "Оплата и рассрочка: банк принимает решение, не ты",
      "essence": "Продавать на высокий чек — значит дать клиенту способ платить. Банковская рассрочка через платёжную страницу: банк сразу переводит тебе всю сумму, клиент возвращает без процентов, ты не бегаешь за платежами.",
      "steps": [
        "Платёжная страница подключается: анкета, реквизиты, способы оплаты, рассрочки.",
        "Ссылка на оплату/рассрочку/бронь — в карточке каждого клиента, не в переписке.",
        "Банк одобряет рассрочку — деньги приходят сразу, возврат — ответственность банка.",
        "Отказ банка страхуется альтернативными сервисами — клиент не уходит в тупик.",
        "Статусы оплат в проекте: кто заплатил, кто на брони, кому напомнить."
      ],
      "chain": [
        "todo",
        "task",
        "write",
        "recall",
        "browser",
        "web_search",
        "retain"
      ],
      "result": "Высокий чек перестаёт пугать: 90 000 одним платежом — это страшно, а 3 750 в месяц — легко. Ты не кассир, ты эксперт."
    },
    {
      "id": "voprosy-agentu",
      "module": "Введение",
      "title": "Вопросы из взрослой позиции: как просить, чтобы получать",
      "essence": "Ответ полезен ровно настолько, насколько хорош вопрос. Взрослая позиция — обозначить проблему, дать варианты, показать свою логику и только потом спросить. Это правило работает и с людьми, и с агентами.",
      "steps": [
        "Проблема формулируется конкретно: что произошло, что пошло не так.",
        "Даёшь варианты, которые уже передумал: что пробовал, что из этого вышло.",
        "Показываешь логику: почему склоняешься к этому варианту.",
        "Задаёшь вопрос с цифрами: конверсия, суммы, сроки — без «низкая», а «3 из 10».",
        "Агенту задача ставится так же: контекст, цель, границы, критерий готовности."
      ],
      "chain": [
        "think",
        "write",
        "task",
        "todo",
        "reflect",
        "ask",
        "grep"
      ],
      "result": "И человек, и агент отвечают по делу с первого раза: вопрос с цифрами и логикой — это половина решения."
    },
    {
      "id": "blog-zayavki",
      "module": "Генерация заявок с блога",
      "title": "Блог, который приносит заявки, а не лайки",
      "essence": "Блог — топливо для заявок: календарь активностей, регулярные посты, призывы, эфиры и тесты. Харнесс ведёт календарь, готовит контент по структуре и следит, чтобы ничего не выпало из ритма.",
      "steps": [
        "Календарь активностей на месяц: посты, сторис, эфиры, призывы — всё на виду.",
        "Контент пишется по структуре, черновики проверяются на стиль и факты.",
        "Посты с призывами на консультацию и разборы подписчиков — по расписанию.",
        "Ответы в личных сообщениях не теряются: входящие стекаются в один контур.",
        "Сводка за период: что дало заявки, что нет, что усилить."
      ],
      "chain": [
        "plan",
        "todo",
        "task",
        "write",
        "edit",
        "hub_start",
        "web_search",
        "recall"
      ],
      "result": "Блог живёт по плану: контент в ритме, призывы на месте, заявки считаются, а не ждут."
    },
    {
      "id": "zapusk",
      "module": "Продажи через запуски",
      "title": "Запуск: три касания до решения",
      "essence": "Запуск — это серия касаний по расписанию: 3 видео или эфира, прогрев, напоминания, открытие продаж. Харнесс собирает план запуска в задачи и ведёт каждую активность по сценарию.",
      "steps": [
        "План запуска: даты, форматы (видео/эфиры), цели по продажам.",
        "Контент каждого касания готовится заранее — сценарии, промты, черновики.",
        "Напоминания и прогрев по расписанию: ни один день запуска не пустует.",
        "Заявки и оплаты по дням — в проекте, видно динамику.",
        "После запуска — разбор: что дало продажи, что повторить."
      ],
      "chain": [
        "plan",
        "todo",
        "task",
        "write",
        "edit",
        "hub_start",
        "recall",
        "eval"
      ],
      "result": "Запуск идёт по плану и не рассыпается: каждое касание на месте, продажи видны цифрами."
    }
  ],
  "tavern": {
    "niches": [
      {
        "case_id": "proizvodstvo",
        "demand": "Наряд-заказы, учёт материалов и загрузка без бумаг: заказ пришёл — видно, где материал, что сделано и кто свободен.",
        "id": "proizvodstvo",
        "title": "Производство",
        "estimate": {
          "value": "38 млн ₽ эффекта; 477 процессов роботизировано (ММК)",
          "year": "2025",
          "source": "ММК, цит. по TAdviser",
          "url": "https://www.tadviser.ru/index.php/Статья:Российский_рынок_RPA-систем"
        }
      },
      {
        "case_id": "uslugi",
        "demand": "Единый входящий поток из звонков, почты и мессенджеров: заявки не теряются, повторяющиеся ответы уходят в шаблоны.",
        "id": "uslugi",
        "title": "Услуги"
      },
      {
        "case_id": "stroitelstvo",
        "demand": "Смета, сроки и подрядчики в одном окне: смета не в Excel, сроки не в голове, срыв виден заранее.",
        "id": "stroitelstvo",
        "title": "Строительство"
      },
      {
        "case_id": "arhitektura",
        "demand": "Быстрые варианты для клиента и документация из них: эскиз перестаёт стоить ночь работы.",
        "id": "arhitektura",
        "title": "Архитектура"
      },
      {
        "case_id": "medicina-nauka",
        "demand": "Обзоры, выписки и черновики документов вместо недель чтения и оформления вручную.",
        "id": "medicina",
        "title": "Медицина"
      },
      {
        "case_id": "torgovlya",
        "demand": "Витрина, цены и остатки без ручного труда: сотни товаров обновляются сами, расхождения видны сразу.",
        "id": "torgovlya",
        "title": "Торговля"
      },
      {
        "case_id": "obrazovanie",
        "demand": "Сборка курса, проверка заданий и обратная связь каждому — без ручной рутины преподавателя.",
        "id": "obrazovanie",
        "title": "Образование"
      },
      {
        "case_id": "gruzoperevozki",
        "demand": "Заявки, статусы и оповещения без звонков: диспетчер не переспрашивает, клиент видит свой груз.",
        "id": "logistika",
        "title": "Логистика и грузоперевозки",
        "estimate": {
          "value": "1–1,5 млн ₽ за RPA на один процесс",
          "year": "2026",
          "source": "Д. Распопова, цит. по TAdviser",
          "url": "https://www.tadviser.ru/index.php/Статья:Российский_рынок_RPA-систем"
        }
      },
      {
        "case_id": "nauka",
        "demand": "Обзоры и гипотезы из источников: тысячи статей сворачиваются в выводы за сегодня, а не за месяц.",
        "id": "nauka",
        "title": "Наука"
      },
      {
        "case_id": "obraz-zhizni",
        "demand": "Ведение целей и привычек: напоминания по делу вместо цикла «начал — бросил».",
        "id": "obraz-zhizni",
        "title": "Образ жизни"
      },
      {
        "case_id": "finansy",
        "demand": "Учёт, план и отчёт: банки и кассы сводятся сами, видно, куда уходят деньги.",
        "id": "finansy",
        "title": "Финансы",
        "estimate": {
          "value": "окупаемость RPA от полугода до года",
          "year": "2022",
          "source": "ИБА, цит. по TAdviser",
          "url": "https://www.tadviser.ru/index.php/Статья:Российский_рынок_RPA-систем"
        }
      },
      {
        "case_id": "restorany",
        "demand": "Меню, закупки и смена под контролем: закупки не на глаз, продукт не портится.",
        "id": "restorany",
        "title": "Рестораны и общепит"
      },
      {
        "case_id": "selskoe-hozyaystvo",
        "demand": "Сезонный план и учёт: ошибка в закупке видна до сезона, а не после потерянного года.",
        "id": "selskoe-hozyaystvo",
        "title": "Сельское хозяйство"
      },
      {
        "case_id": "erp-bez-vendorov",
        "demand": "Учёт и процессы без вендорной кабалы: без лицензий, интегратора и внедрения за год.",
        "id": "it",
        "title": "IT-разработка",
        "estimate": {
          "value": "21–24 млрд ₽ — рынок RPA РФ",
          "year": "2024",
          "source": "TAdviser",
          "url": "https://www.tadviser.ru/index.php/Статья:Российский_рынок_RPA-систем"
        }
      },
      {
        "case_id": "marketing",
        "demand": "Сводка кампаний и отчёт по фактам: пять кабинетов собираются в один отчёт без ручной сборки.",
        "id": "marketing",
        "title": "Маркетинг и реклама",
        "estimate": {
          "value": "$3,6 млрд — мировой рынок RPA-ПО (+14,5%)",
          "year": "2024",
          "source": "Gartner",
          "url": "https://www.gartner.com/en/documents/6842834"
        }
      },
      {
        "case_id": "nedvizhimost",
        "demand": "Объекты, показы и сделка без потерь: показы не накладываются, документы не теряются.",
        "id": "nedvizhimost",
        "title": "Недвижимость"
      },
      {
        "case_id": "transport",
        "demand": "Маршруты, статусы и клиент в курсе: «где заказ?» закрывается статусом, а не звонком.",
        "id": "transport",
        "title": "Транспорт и доставка"
      },
      {
        "case_id": "remont",
        "demand": "Заявки, запчасти и выезды: запчасть не кончается в нужный момент, мастера расписаны.",
        "id": "remont",
        "title": "Ремонт и обслуживание"
      },
      {
        "case_id": "sport",
        "demand": "Расписание, клиенты и загрузка зала: зал не пустует и не переполнен, абонементы не в голове.",
        "id": "sport",
        "title": "Спорт и фитнес"
      },
      {
        "case_id": "kontent-zavod",
        "demand": "Конвейер сценарий → ролик → пост: контент перестаёт есть дни.",
        "id": "razvlecheniya",
        "title": "Развлечения и контент"
      }
    ],
    "note": "Ниши и спрос на автоматизацию. Оценки рынка — только из открытых аналитических источников, каждая со ссылкой; без оценки строка остаётся качественным описанием спроса.",
    "updated_at": "2026-09-22",
    "checked_at": "2026-09-22"
  },
  "stories": {
    "stories": [
      {
        "agent": {
          "model": "opencode-go/deepseek-v4.1-flash",
          "session_id": "s41",
          "status": "done",
          "subtask_id": "t1789711760"
        },
        "desc": "Каталог инструментов и разделы сайта: 83 позиции из панели харнесса, десять групп, раздел «История» с семью историями и кнопка Telegram в отклике. Проверка — генератором и браузером, публикация — со сверкой байтов по sha256.",
        "id": "site-catalog",
        "request": "Ты — агент-исследователь и веб-редактор сайта wbzona.com. […] Ничего не коммить в git.",
        "result": "В блоке «Отклик» появилась кнопка «Написать в Telegram» (https://t.me/earthenerg) рядом с «Смотреть эфир». […]",
        "shot": {
          "alt": "Живой сайт: папка инструментов каталога",
          "file": "story-site-tools.webp"
        },
        "t0": "2026-09-18T11:09:20",
        "t1": "2026-09-18T14:46:47",
        "title": "Каталог сайта за один день",
        "values": [
          "83 инструмента в каталоге",
          "10 прогонов",
          "статус done"
        ]
      },
      {
        "agent": {
          "model": "deepseek-v4.1-flash",
          "session_id": "s100",
          "status": "review",
          "subtask_id": "t1789883238"
        },
        "desc": "Отчёт «сэкономлено токенов за N дней»: панель показывает, сколько входных токенов экономят главы, цифра измеряемая — гейт mem.savings закрывает приёмку синтетикой и живыми строками.",
        "id": "b23-savings",
        "request": "ЗАДАЧА (ТЗ, этап B2 п.3 […], строки 218-230). ЦЕЛЬ: в панели харнесса и через API показать, сколько входных токенов экономят главы за окно N дней. […]",
        "result": "Гейт mem.savings — test_harness.py --only mem.savings → [PASS]: saved 3800 (21.1%) на базлайнах; без глав saved 0; битые строки пропущены. […, доработка 2026-09-21]",
        "shot": {
          "alt": "Кадр эфира 2026-09-22 04:38 UTC: пик активности нарезки, 50 смен кадра",
          "file": "story-b23-live.webp"
        },
        "t0": "2026-09-20T10:47:26",
        "t1": "2026-09-21T14:52:38",
        "title": "Счётчик экономии токенов",
        "values": [
          "гейт mem.savings PASS",
          "7 прогонов",
          "статус: на ревью"
        ]
      }
    ]
  },
  "folders": [
    {
      "id": "about",
      "title": "О проекте",
      "items": [
        {
          "id": "paps",
          "title": "PAPS Harness",
          "subtitle": "канал проекта · что внутри и что уже сделано"
        },
        {
          "id": "live",
          "title": "Эфир",
          "subtitle": "прямая трансляция рабочей машины, повтор — когда автор не в сети"
        },
        {
          "id": "what",
          "title": "Суть",
          "subtitle": "что такое харнесс — простыми словами"
        },
        {
          "id": "why",
          "title": "Сравнение",
          "subtitle": "чем это отличается от облачных платформ и чат-ассистентов"
        },
        {
          "id": "use",
          "title": "Ремёсла",
          "subtitle": "что с этим можно делать — шесть сценариев"
        },
        {
          "id": "how",
          "title": "Как устроено",
          "subtitle": "порядок, из-за которого можно доверять"
        },
        {
          "id": "history",
          "title": "История",
          "subtitle": "почему это строится и семь историй о делах"
        },
        {
          "id": "contact",
          "title": "Отклик",
          "subtitle": "три шага и как написать автору"
        }
      ],
      "count": 8
    },
    {
      "id": "tools",
      "title": "Инструменты",
      "items": [
        {
          "id": "bash",
          "title": "Команды оболочки",
          "subtitle": "Терминал · Одна команда или короткий конвейер в рабочем каталоге сессии",
          "verified": true
        },
        {
          "id": "glob",
          "title": "Поиск файлов по маске",
          "subtitle": "Файлы · Ищет пути по маске; содержимое ищет `grep`",
          "verified": true
        },
        {
          "id": "grep",
          "title": "Поиск по содержимому",
          "subtitle": "Файлы · Ищет регуляркой по содержимому файлов, каталогов и внутренних URL",
          "verified": true
        },
        {
          "id": "ast_grep",
          "title": "Структурный поиск (AST)",
          "subtitle": "Код-анализ · Структурный поиск по AST (ast-grep), а не по тексту",
          "verified": false
        },
        {
          "id": "ast_edit",
          "title": "Структурная правка (AST)",
          "subtitle": "Код-анализ · Структурный рерайт через ast-grep: паттерн → замена по AST",
          "verified": true
        },
        {
          "id": "lsp",
          "title": "Языковые серверы (LSP)",
          "subtitle": "Код-анализ · Языковые серверы: диагностика, определения, ссылки, переименование, code actions",
          "verified": true
        },
        {
          "id": "todo",
          "title": "Список задач",
          "subtitle": "Планирование · Мутация списка задач сессии одним действием + снимок фаз и задач",
          "verified": true
        },
        {
          "id": "debug",
          "title": "Отладчик",
          "subtitle": "Код-анализ · Отладчик по DAP: точки останова, шаги, стек, переменные, память",
          "verified": true
        },
        {
          "id": "git",
          "title": "Git в интерфейсе",
          "subtitle": "Код-анализ · Настройка OMP: ветка/статус/PR в TUI и слежение за метаданными репозитория",
          "verified": false
        },
        {
          "id": "plan",
          "title": "Режим планирования",
          "subtitle": "Планирование · Режим планирования: read-only исследование перед правками",
          "verified": false
        },
        {
          "id": "goal",
          "title": "Режим цели",
          "subtitle": "Планирование · Режим цели сессии и скрытый инструмент goal",
          "verified": false
        },
        {
          "id": "ask",
          "title": "Вопрос пользователю",
          "subtitle": "Система · Интерактивный вопрос пользователю: выбор из вариантов или свободный текст",
          "verified": false
        },
        {
          "id": "web_search",
          "title": "Веб-поиск",
          "subtitle": "Web · Один веб-запрос через первый доступный провайдер поиска",
          "verified": true
        },
        {
          "id": "browser",
          "title": "Браузер",
          "subtitle": "Web · Скриптовый Chromium/CDP: вкладки, реюз, привязка к своему Chrome",
          "verified": true
        },
        {
          "id": "fetch",
          "title": "Чтение URL",
          "subtitle": "Web · Разрешение для `read` тянуть и обрабатывать URL (не отдельный инструмент)",
          "verified": false
        },
        {
          "id": "exa",
          "title": "Exa — веб-поиск",
          "subtitle": "Web · Провайдер веб-поиска Exa для web_search",
          "verified": false
        },
        {
          "id": "github",
          "title": "GitHub — операции CLI",
          "subtitle": "Система · Операции GitHub CLI: репозитории, файлы, PR, поиск, watch Actions",
          "verified": false
        },
        {
          "id": "security",
          "title": "Сканер безопасности",
          "subtitle": "Система · Планирование и прогон security-сканов, валидация находок, security://",
          "verified": true
        },
        {
          "id": "vault",
          "title": "Хранилище Obsidian",
          "subtitle": "Система · Доступ к Obsidian-хранилищу через vault:// (чтение и правка)",
          "verified": true
        },
        {
          "id": "checkpoint",
          "title": "Чекпойнт контекста",
          "subtitle": "Система · Отметка состояния диалога, чтобы потом свернуть разведку в отчёт (rewind)",
          "verified": false
        },
        {
          "id": "launch",
          "title": "Процессы под надзором",
          "subtitle": "Система · Супервизия долгоживущих процессов — теперь op-семейство `hub`",
          "verified": false
        },
        {
          "id": "speechgen",
          "title": "Синтез речи",
          "subtitle": "Система · Синтез речи в файл: локально (Kokoro) или через xAI Grok Voice",
          "verified": false
        },
        {
          "id": "generate_image",
          "title": "Генерация изображений",
          "subtitle": "Система · Генерация и правка изображений; результат пишется во временный путь",
          "verified": false
        },
        {
          "id": "inspect_image",
          "title": "Разбор изображений",
          "subtitle": "Система · Разбор локальной картинки vision-моделью: текстовый анализ",
          "verified": true
        },
        {
          "id": "computer",
          "title": "Управление рабочим столом",
          "subtitle": "Система · Управление реальным рабочим столом: окна, скриншоты, ввод, accessibility",
          "verified": true
        },
        {
          "id": "advisor",
          "title": "Советник",
          "subtitle": "Система · Вторая модель-советник: пассивно ревьюит каждый ход и вставляет замечания",
          "verified": false
        },
        {
          "id": "read",
          "title": "Чтение",
          "subtitle": "Файлы · Читает файл, каталог, архив, SQLite, документ, картинку или URL по одному path",
          "verified": true
        },
        {
          "id": "read_group",
          "title": "Чтение (группы)",
          "subtitle": "Файлы · Панельная группировка OMP: несколько прочитанных файлов одним блоком",
          "verified": false
        },
        {
          "id": "write",
          "title": "Запись",
          "subtitle": "Файлы · Создаёт/перезаписывает файл, элемент архива, строку SQLite или устройство xd://",
          "verified": true
        },
        {
          "id": "edit",
          "title": "Правка файла",
          "subtitle": "Файлы · Правки файла: hashline-патч (по умолчанию), unified-diff или patch-режим",
          "verified": true
        },
        {
          "id": "apply_patch",
          "title": "Правка патчем",
          "subtitle": "Файлы · Режим `edit`: правка файла unified-diff-патчем (wire-имя apply_patch)",
          "verified": false
        },
        {
          "id": "edit_delete",
          "title": "Удаление",
          "subtitle": "Файлы · Операция удаления внутри `edit` (CUT в hashline) — отдельного инструмента нет",
          "verified": false
        },
        {
          "id": "edit_move",
          "title": "Перемещение",
          "subtitle": "Файлы · Операция перемещения внутри `edit` (MV в hashline) — отдельного инструмента нет",
          "verified": false
        },
        {
          "id": "eval",
          "title": "Код в ячейке",
          "subtitle": "Терминал · Ячейка Python/JS/Ruby/Julia в постоянном рантайме: состояние живёт между вызовами",
          "verified": true
        },
        {
          "id": "task",
          "title": "Субагенты",
          "subtitle": "Планирование · Спавн субагентов: один за вызов или пачкой tasks[]",
          "verified": true
        },
        {
          "id": "think",
          "title": "Размышление",
          "subtitle": "Планирование · Скрытый инструмент размышления (вне схемы инструментов модели)",
          "verified": false
        },
        {
          "id": "reflect",
          "title": "Синтез по памяти",
          "subtitle": "Планирование · Синтез ответа поверх долговременной памяти (Mnemopi/Hindsight)",
          "verified": false
        },
        {
          "id": "context_gauge",
          "title": "Индикатор контекста",
          "subtitle": "Планирование · Индикатор заполнения контекста в статус-строке OMP",
          "verified": false
        },
        {
          "id": "recall",
          "title": "Поиск в памяти",
          "subtitle": "Память · Поиск по долговременной памяти (Mnemopi/Hindsight)",
          "verified": false
        },
        {
          "id": "retain",
          "title": "Запись в память",
          "subtitle": "Память · Запись durable-факта в долговременную память",
          "verified": false
        },
        {
          "id": "custom",
          "title": "Свои инструменты",
          "subtitle": "Система · Инструменты, зарегистрированные расширениями и плагинами",
          "verified": false
        },
        {
          "id": "report_tool_issue",
          "title": "Репорт об инструменте",
          "subtitle": "Система · Автоматический QA-репорт о неверном поведении инструмента",
          "verified": false
        },
        {
          "id": "hub_inbox",
          "title": "Входящие",
          "subtitle": "Агенты (hub) · op=inbox единой тулзы hub: забрать входящие сообщения других агентов",
          "verified": true
        },
        {
          "id": "hub_jobs",
          "title": "Фоновые задачи",
          "subtitle": "Агенты (hub) · op=jobs: снимок фоновых задач прогона (завершённые и идущие)",
          "verified": true
        },
        {
          "id": "hub_list",
          "title": "Список агентов",
          "subtitle": "Агенты (hub) · op=list: состав живых агентов и их статусы",
          "verified": true
        },
        {
          "id": "hub_logs",
          "title": "Логи процесса",
          "subtitle": "Агенты (hub) · op=logs: хвост вывода процесса (курсор, grep, follow, head)",
          "verified": true
        },
        {
          "id": "hub_send",
          "title": "Сообщение / ввод",
          "subtitle": "Агенты (hub) · op=send: сообщение агенту или stdin/клавиши/сигнал процессу",
          "verified": true
        },
        {
          "id": "hub_start",
          "title": "Запуск процесса",
          "subtitle": "Агенты (hub) · op=start: запуск долгоживущего процесса под надзором брокера",
          "verified": true
        },
        {
          "id": "hub_wait",
          "title": "Ожидание",
          "subtitle": "Агенты (hub) · op=wait: блокирующее ожидание первого из — сообщение, финиш задачи, таймаут",
          "verified": true
        },
        {
          "id": "skill:harness",
          "title": "harness",
          "subtitle": "Скиллы · Обёртка Harness V18 вместо прямых вызовов нижележащих инструментов",
          "verified": false
        },
        {
          "id": "skill:code-review",
          "title": "code-review",
          "subtitle": "Скиллы · Ревью изменений с фиксированной точки по двум осям: стандарты и спецификация",
          "verified": false
        },
        {
          "id": "skill:diagnosing-bugs",
          "title": "diagnosing-bugs",
          "subtitle": "Скиллы · Цикл диагностики сложных багов и просадок производительности",
          "verified": false
        },
        {
          "id": "skill:tdd",
          "title": "tdd",
          "subtitle": "Скиллы · Разработка через тесты: сначала падающий тест, потом код",
          "verified": false
        },
        {
          "id": "skill:codebase-design",
          "title": "codebase-design",
          "subtitle": "Скиллы · Словарь для проектирования глубоких модулей и их интерфейсов",
          "verified": false
        },
        {
          "id": "skill:domain-modeling",
          "title": "domain-modeling",
          "subtitle": "Скиллы · Построение и уточнение доменной модели проекта",
          "verified": false
        },
        {
          "id": "skill:ponytail",
          "title": "ponytail",
          "subtitle": "Скиллы · Самое ленивое решение, которое реально работает: короче и минимальнее",
          "verified": false
        },
        {
          "id": "skill:ponytail-review",
          "title": "ponytail-review",
          "subtitle": "Скиллы · Ревью только на переусложнение: что можно удалить",
          "verified": false
        },
        {
          "id": "skill:ponytail-audit",
          "title": "ponytail-audit",
          "subtitle": "Скиллы · Аудит всего репозитория на переусложнение: что удалить",
          "verified": false
        },
        {
          "id": "skill:git-guardrails-claude-code",
          "title": "git-guardrails-claude-code",
          "subtitle": "Скиллы · Хуки Claude Code, блокирующие опасные git-команды до выполнения",
          "verified": false
        },
        {
          "id": "skill:setup-matt-pocock-skills",
          "title": "setup-matt-pocock-skills",
          "subtitle": "Скиллы · Настроить репозиторий под набор инженерных скиллов",
          "verified": false
        },
        {
          "id": "skill:prototype",
          "title": "prototype",
          "subtitle": "Скиллы · Одноразовый прототип для проверки вопроса дизайна",
          "verified": false
        },
        {
          "id": "skill:research",
          "title": "research",
          "subtitle": "Скиллы · Исследование по первичным источникам с отчётом в репозитории",
          "verified": false
        },
        {
          "id": "skill:resolving-merge-conflicts",
          "title": "resolving-merge-conflicts",
          "subtitle": "Скиллы · Разрешение уже идущего конфликта merge или rebase",
          "verified": false
        },
        {
          "id": "skill:writing-for-agents",
          "title": "writing-for-agents",
          "subtitle": "Скиллы · Как писать документы для агентов: скиллы, AGENTS.md, CLAUDE.md",
          "verified": false
        },
        {
          "id": "skill:writing-guidelines",
          "title": "writing-guidelines",
          "subtitle": "Скиллы · Проверка прозы и документации по гайдлайну стиля",
          "verified": false
        },
        {
          "id": "skill:web-design-guidelines",
          "title": "web-design-guidelines",
          "subtitle": "Скиллы · Проверка интерфейса по Web Interface Guidelines",
          "verified": false
        },
        {
          "id": "skill:vercel-react-best-practices",
          "title": "vercel-react-best-practices",
          "subtitle": "Скиллы · Практики производительности React и Next.js от Vercel",
          "verified": false
        },
        {
          "id": "skill:vercel-composition-patterns",
          "title": "vercel-composition-patterns",
          "subtitle": "Скиллы · Паттерны композиции React для масштабируемых компонентов",
          "verified": false
        },
        {
          "id": "skill:graphify",
          "title": "graphify",
          "subtitle": "Скиллы · Граф знаний по коду и докам: запросы, пути, объяснения",
          "verified": false
        },
        {
          "id": "skill:handoff",
          "title": "handoff",
          "subtitle": "Скиллы · Сжать текущий диалог в handoff-документ для следующего агента",
          "verified": false
        },
        {
          "id": "skill:transcribe-ru",
          "title": "transcribe-ru",
          "subtitle": "Скиллы · Распознать русскую речь из аудио или видео в текст",
          "verified": false
        },
        {
          "id": "skill:skills-index",
          "title": "skills-index",
          "subtitle": "Скиллы · Полный каталог установленных скиллов: имя, назначение, путь",
          "verified": false
        },
        {
          "id": "skill:sn-deep-research",
          "title": "sn-deep-research",
          "subtitle": "Скиллы · Глубокое исследование: много источников, сверка, отчёт",
          "verified": false
        },
        {
          "id": "skill:sn-da-excel-workflow",
          "title": "sn-da-excel-workflow",
          "subtitle": "Скиллы · Анализ Excel: чтение, чистка, статистика, экспорт отчёта",
          "verified": false
        },
        {
          "id": "skill:sn-ppt-entry",
          "title": "sn-ppt-entry",
          "subtitle": "Скиллы · Вход в генерацию презентаций: режим, брифинг, запуск пайплайна",
          "verified": false
        },
        {
          "id": "skill:sn-research-report",
          "title": "sn-research-report",
          "subtitle": "Скиллы · Структура исследовательского отчёта под задачу читателя",
          "verified": false
        },
        {
          "id": "skill:sn-md-to-html-report",
          "title": "sn-md-to-html-report",
          "subtitle": "Скиллы · Markdown-отчёт в самодостаточную HTML-страницу с редакторской подачей",
          "verified": false
        },
        {
          "id": "skill:sn-search-academic",
          "title": "sn-search-academic",
          "subtitle": "Скиллы · Академический поиск: статьи, разбор, цепочки цитирований",
          "verified": false
        },
        {
          "id": "skill:sn-prepare-citations",
          "title": "sn-prepare-citations",
          "subtitle": "Скиллы · Постобработка сносок: дедупликация, нумерация, список литературы",
          "verified": false
        },
        {
          "id": "skill:design-taste-frontend",
          "title": "Дизайн",
          "subtitle": "Скиллы · Дизайн: лендинги, портфолио и редизайны без шаблонного вида",
          "verified": false
        },
        {
          "id": "mcp:demo-adapter",
          "title": "demo-adapter",
          "subtitle": "MCP-серверы · Эталонный адаптер: показывает, что внешний источник контекста подключается без правок кода харнесса",
          "verified": true
        },
        {
          "id": "mcp:memory-turbovec",
          "title": "memory-turbovec",
          "subtitle": "MCP-серверы · Проектная семантическая память (search/add, без clear)",
          "verified": true
        },
        {
          "id": "mcp:bifrost",
          "title": "bifrost",
          "subtitle": "MCP-серверы · SSH-мост к удалённым серверам (connect/exec/read/status/upload/download/disconnect). Реализация: ui/bifrost_mcp_server.py (stdlib, системный OpenSSH). v2: резидентный ssh-канал (~100 мс на команду вместо хендшейка), ServerAlive+авто-переподключение, инлайн до 45 КБ и спилл в ui/data/bifrost-out, срезы удалённых файлов (read), файлы <=256 КБ по каналу с sha256. Самопроверка: python ui/bifrost_mcp_server.py --selftest (проверено 2026-09-14).",
          "verified": true
        },
        {
          "id": "mcp:graphify-harness",
          "title": "graphify-harness",
          "subtitle": "MCP-серверы · Кодовый граф ЛОКАЛЬНОГО харнесса (свой, с этой машины: ui/, tooling/, extensions/, omp/) — не путать со снимками продукта с сервера",
          "verified": true
        }
      ],
      "count": 84
    },
    {
      "id": "stories",
      "title": "Истории эфира",
      "items": [
        {
          "id": "site-catalog",
          "title": "Каталог сайта за один день",
          "subtitle": "Каталог инструментов и разделы сайта: 83 позиции из панели харнесса, десять групп, раздел «История» с семью историями и кнопка Telegram в отклике. Проверка — генератором и браузером, публикация — со сверкой байтов по sha256."
        },
        {
          "id": "b23-savings",
          "title": "Счётчик экономии токенов",
          "subtitle": "Отчёт «сэкономлено токенов за N дней»: панель показывает, сколько входных токенов экономят главы, цифра измеряемая — гейт mem.savings закрывает приёмку синтетикой и живыми строками."
        }
      ],
      "count": 2
    },
    {
      "id": "cases",
      "title": "Кейсы",
      "items": [
        {
          "id": "erp-bez-vendorov",
          "title": "ERP без сторонних продуктов",
          "subtitle": "IT-разработка · Бизнесу обещают «внедрение ERP за год и миллион»: лицензии, интеграторы, графики. На деле вы покупаете чужую логику, которую всё равно переделываете под себя, и зависите от вендора."
        },
        {
          "id": "gruzoperevozki",
          "title": "Перевозчик, у которого телефон молчит",
          "subtitle": "Логистика и грузоперевозки · Заказы — в звонках и чатах: диспетчер переспрашивает, водитель занят, клиент ждёт. Каждый сегмент дороги живёт в голове у одного человека — выпал он, встала вся цепочка."
        },
        {
          "id": "kontent-zavod",
          "title": "Контент-завод: сценарий → ролик → пост",
          "subtitle": "Развлечения и контент · Контент ест дни: сценарий, съёмка или рендер, монтаж, тексты, постинг. Один ролик — неделя ручной работы, а площадок пять."
        },
        {
          "id": "medicina-nauka",
          "title": "Медицина и наука: документы вместо рутины",
          "subtitle": "Медицина · Исследование, обзор, отчёт — это недели на чтение, выписки и оформление. Врач и учёный тратят время на формат, а не на суть."
        },
        {
          "id": "proizvodstvo",
          "title": "Цех: наряд-заказы и остатки без «бумаг»",
          "subtitle": "Производство · Заказ пришёл — а где материал, что уже сделано, кто свободен? Учёт в тетради или таблице, которая живёт у одного мастера."
        },
        {
          "id": "uslugi",
          "title": "Клиентский сервис без «сейчас перезвоню»",
          "subtitle": "Услуги · Заявки из звонков, почты и мессенджеров; ответы повторяются; никто не помнит, что обещал. Клиент ждёт — сервис теряет."
        },
        {
          "id": "stroitelstvo",
          "title": "Прораб: смета, сроки, подрядчики в одном окне",
          "subtitle": "Строительство · Смета в Excel, сроки в голове, подрядчики в телефонной книге. Один срыв — и пересчёт руками, а виноват всегда прораб."
        },
        {
          "id": "arhitektura",
          "title": "Архитектор: варианты и документация без ночей",
          "subtitle": "Архитектура · Клиенту нужны варианты, а каждый эскиз — часы работы. Документация съедает время, которое должно уходить на замысел."
        },
        {
          "id": "torgovlya",
          "title": "Магазин: цены, остатки и витрина без ручного труда",
          "subtitle": "Торговля · Товаров сотни, цены меняются, остатки разъезжаются. Обновлять витрину вручную — вечер уходит на таблицы."
        },
        {
          "id": "obrazovanie",
          "title": "Преподаватель: курс, задания, проверка",
          "subtitle": "Образование · Курс нужно собрать, задания проверить, обратную связь дать каждому. На группу — вечера ручной работы."
        },
        {
          "id": "nauka",
          "title": "Исследователь: обзор и гипотезы из источников",
          "subtitle": "Наука · Статей тысячи, времени нет, а выводы нужны сегодня. Читать всё руками — нереально, верить одному обзору — опасно."
        },
        {
          "id": "obraz-zhizni",
          "title": "Личный проект: от идеи до привычки",
          "subtitle": "Образ жизни · Цели есть, дисциплины нет: начал — бросил, начал — бросил. Причина не лень, а отсутствие системы, которая помнит и напоминает."
        },
        {
          "id": "finansy",
          "title": "Личные и малые финансы: учёт, план, отчёт",
          "subtitle": "Финансы · Деньги уходят, а куда — непонятно. Сводить банки и кассы руками — вечер раз в месяц, который вечно откладывается."
        },
        {
          "id": "restorany",
          "title": "Точка общепита: меню, закупки, смена",
          "subtitle": "Рестораны и общепит · Меню устарело, закупки на глаз, смена — в головах. Продукт портится, гость ждёт, владелец ночами сводит цифры."
        },
        {
          "id": "selskoe-hozyaystvo",
          "title": "Хозяйство: посевы, закупки, сезонный план",
          "subtitle": "Сельское хозяйство · Сезон один раз в год, ошибка в закупке — потерянный год. Журналы на бумаге, память одного агронома."
        },
        {
          "id": "marketing",
          "title": "Маркетолог: кампании, площадки, отчёт по фактам",
          "subtitle": "Маркетинг и реклама · Кампании в пяти кабинетах, отчёты собираются вручную, «эффективность» — из ощущений, а не из цифр."
        },
        {
          "id": "nedvizhimost",
          "title": "Агент: объекты, показы, сделка без потерь",
          "subtitle": "Недвижимость · Объекты в головах и чатах, показы накладываются, документы теряются. Один забытый звонок — сорванная сделка."
        },
        {
          "id": "transport",
          "title": "Доставка: маршруты, статусы, клиент в курсе",
          "subtitle": "Транспорт и доставка · Курьеры разъезжаются, клиенты звонят «где заказ?», маршруты строятся на глаз. Пик — хаос на телефоне."
        },
        {
          "id": "remont",
          "title": "Ремонтная служба: заявки, запчасти, выезды",
          "subtitle": "Ремонт и обслуживание · Заявки по телефону, запчасти кончаются в самый нужный момент, мастера ездят неоптимально."
        },
        {
          "id": "sport",
          "title": "Клуб: расписание, клиенты, загрузка зала",
          "subtitle": "Спорт и фитнес · Расписание в таблице, абонементы в голове, зал то пустует, то переполнен. Тренер — администратор, а не тренер."
        },
        {
          "id": "ii-otdel-prodazh",
          "title": "ИИ-отдел продаж: заявки из Telegram-чатов",
          "subtitle": "Продажи и лидогенерация · Клиенты пишут «нужен специалист» в профильных чатах, и найти это можно только листая ленту руками. Час-два в день на десять чатов, а запрос живёт недолго: написанный в 11:20 к 14:00 уже закрыт — человек договорился с тем, кто ответил первым."
        },
        {
          "id": "kompaniya-v-odnom-okne",
          "title": "Компания в одном окне: двенадцать процессов без ручной сборки",
          "subtitle": "Управление компанией · Компания растёт направлениями — розница, опт, сервис, поставки, — а управление держится на людях и таблицах. Деньги: дебиторка живёт без связки «сумма / срок / просрочка / ответственный». Тендеры: документация и номенклатура пересчитываются руками, рентабельность позиции не считается, контура «подал → выиграл → исполнил → закрыл» нет. Люди: показатели считаются, но без апелляции и без внешних причин. Данные: цены пяти-семи магазинов сводятся вручную, обращения из тендеров, соцсетей и офлайна лежат раздельно, а 1С и CRM, скорее всего, расходятся. Ничего из этого не видно в одном месте — поэтому каждое решение начинается со сбора данных, а не с решения."
        }
      ],
      "count": 22
    },
    {
      "id": "tavern",
      "title": "Таверна спроса",
      "items": [
        {
          "id": "proizvodstvo",
          "title": "Производство",
          "subtitle": "Наряд-заказы, учёт материалов и загрузка без бумаг: заказ пришёл — видно, где материал, что сделано и кто свободен."
        },
        {
          "id": "uslugi",
          "title": "Услуги",
          "subtitle": "Единый входящий поток из звонков, почты и мессенджеров: заявки не теряются, повторяющиеся ответы уходят в шаблоны."
        },
        {
          "id": "stroitelstvo",
          "title": "Строительство",
          "subtitle": "Смета, сроки и подрядчики в одном окне: смета не в Excel, сроки не в голове, срыв виден заранее."
        },
        {
          "id": "arhitektura",
          "title": "Архитектура",
          "subtitle": "Быстрые варианты для клиента и документация из них: эскиз перестаёт стоить ночь работы."
        },
        {
          "id": "medicina",
          "title": "Медицина",
          "subtitle": "Обзоры, выписки и черновики документов вместо недель чтения и оформления вручную."
        },
        {
          "id": "torgovlya",
          "title": "Торговля",
          "subtitle": "Витрина, цены и остатки без ручного труда: сотни товаров обновляются сами, расхождения видны сразу."
        },
        {
          "id": "obrazovanie",
          "title": "Образование",
          "subtitle": "Сборка курса, проверка заданий и обратная связь каждому — без ручной рутины преподавателя."
        },
        {
          "id": "logistika",
          "title": "Логистика и грузоперевозки",
          "subtitle": "Заявки, статусы и оповещения без звонков: диспетчер не переспрашивает, клиент видит свой груз."
        },
        {
          "id": "nauka",
          "title": "Наука",
          "subtitle": "Обзоры и гипотезы из источников: тысячи статей сворачиваются в выводы за сегодня, а не за месяц."
        },
        {
          "id": "obraz-zhizni",
          "title": "Образ жизни",
          "subtitle": "Ведение целей и привычек: напоминания по делу вместо цикла «начал — бросил»."
        },
        {
          "id": "finansy",
          "title": "Финансы",
          "subtitle": "Учёт, план и отчёт: банки и кассы сводятся сами, видно, куда уходят деньги."
        },
        {
          "id": "restorany",
          "title": "Рестораны и общепит",
          "subtitle": "Меню, закупки и смена под контролем: закупки не на глаз, продукт не портится."
        },
        {
          "id": "selskoe-hozyaystvo",
          "title": "Сельское хозяйство",
          "subtitle": "Сезонный план и учёт: ошибка в закупке видна до сезона, а не после потерянного года."
        },
        {
          "id": "it",
          "title": "IT-разработка",
          "subtitle": "Учёт и процессы без вендорной кабалы: без лицензий, интегратора и внедрения за год."
        },
        {
          "id": "marketing",
          "title": "Маркетинг и реклама",
          "subtitle": "Сводка кампаний и отчёт по фактам: пять кабинетов собираются в один отчёт без ручной сборки."
        },
        {
          "id": "nedvizhimost",
          "title": "Недвижимость",
          "subtitle": "Объекты, показы и сделка без потерь: показы не накладываются, документы не теряются."
        },
        {
          "id": "transport",
          "title": "Транспорт и доставка",
          "subtitle": "Маршруты, статусы и клиент в курсе: «где заказ?» закрывается статусом, а не звонком."
        },
        {
          "id": "remont",
          "title": "Ремонт и обслуживание",
          "subtitle": "Заявки, запчасти и выезды: запчасть не кончается в нужный момент, мастера расписаны."
        },
        {
          "id": "sport",
          "title": "Спорт и фитнес",
          "subtitle": "Расписание, клиенты и загрузка зала: зал не пустует и не переполнен, абонементы не в голове."
        },
        {
          "id": "razvlecheniya",
          "title": "Развлечения и контент",
          "subtitle": "Конвейер сценарий → ролик → пост: контент перестаёт есть дни."
        }
      ],
      "count": 20
    },
    {
      "id": "models",
      "title": "Модели",
      "items": [
        {
          "id": "mentalnye-modeli",
          "title": "Ментальные модели (мета)",
          "subtitle": "Картинки в голове, через которые видно мир: чем их больше, тем больше решений видно без долгих размышлений. Мета-модель — про то, что сами модели можно учить и пополнять."
        },
        {
          "id": "stimuly",
          "title": "Стимулы",
          "subtitle": "Люди и системы делают то, что им выгодно, даже когда говорят другое. Решение работает, когда у действующего есть причина делать правильно — а не когда его просят."
        },
        {
          "id": "alternativnye-izderzhki",
          "title": "Альтернативные издержки",
          "subtitle": "Цена выбора — то, от чего ты отказался. Деньги, время и внимание, потраченные на одно, не придут из другого. Считается не «сколько стоит», а «что я не сделал»."
        },
        {
          "id": "problema-indeyki",
          "title": "Проблема индейки",
          "subtitle": "То, что было всегда, не гарантирует то, что будет: индейка тысячу дней сыта, а на тысяча первый — к обеду. Прошлое — не договор о будущем."
        },
        {
          "id": "britva-okkama",
          "title": "Бритва Оккама",
          "subtitle": "Из двух объяснений выбирай то, что требует меньше допущений. Не потому что простое «правильнее», а потому что у него меньше мест, где можно ошибиться."
        },
        {
          "id": "izbegay-razoreniya",
          "title": "Избегай разорения",
          "subtitle": "Сначала не потеряй всё, потом думай о выигрыше. Один удар, который стирает тебя, сильнее любой череды успехов. Выживание — первая задача."
        },
        {
          "id": "igra-s-nenulevoy-summoy",
          "title": "Игра с ненулевой суммой",
          "subtitle": "Выигрыш одного не обязан быть проигрышем другого. Есть сделки, где оба становятся богаче: обмен знаниями, доверие, совместная работа."
        },
        {
          "id": "falsifitsiruemost",
          "title": "Фальсифицируемость",
          "subtitle": "Утверждение научно, если можно придумать проверку, которая его опровергнет. «Всё будет хорошо» — не проверяется; «контур собирается за неделю» — проверяется."
        },
        {
          "id": "principial-agent",
          "title": "Теория принципала–агента",
          "subtitle": "Принципал (владелец) передаёт работу агенту (исполнителю), но интересы у них не совпадают автоматически. Система должна делать так, чтобы агенту было выгодно служить принципалу."
        },
        {
          "id": "begi-v-goru",
          "title": "Беги в гору",
          "subtitle": "Делай то, что тяжело сейчас и легко потом: учиться, чинить долг, автоматизировать. В гору тяжело идти — но с горы потом легко катиться."
        },
        {
          "id": "estestvenny-otbor",
          "title": "Естественный отбор",
          "subtitle": "Выживает не самый сильный, а тот, кто лучше приспособлен к условиям и успевает размножаться. В деле — выживают практики, которые реально работают."
        },
        {
          "id": "prisposablivaemost",
          "title": "Приспособляемость",
          "subtitle": "Ценность не в том, чтобы быть правым при неизменных условиях, а в том, чтобы оставаться полезным, когда условия меняются. Жёсткий план умирает первым."
        },
        {
          "id": "slozhny-procent",
          "title": "Сложный процент",
          "subtitle": "Рост, который ложится на предыдущий рост: проценты на проценты. Маленькое и регулярное становится огромным — но только если успевает накопиться."
        },
        {
          "id": "kriticheskaya-massa",
          "title": "Критическая масса",
          "subtitle": "Есть порог, после которого процесс идёт сам: снежный ком, эпидемия, сеть. До порога — усилия, после — инерция. Всё решает не размер, а переход порога."
        },
        {
          "id": "inertsiya",
          "title": "Инерция",
          "subtitle": "Тело, движущееся по прямой, продолжает двигаться, пока его не остановят: привычки, процессы, технологии живут дольше своей пользы. Менять их — тратить энергию."
        },
        {
          "id": "effekt-kolei",
          "title": "Эффект колеи",
          "subtitle": "Чем глубже колея, тем легче катиться по ней и тем труднее выйти. Хорошая практика — колея; плохая — тоже колея. Главный вопрос: куда ты накатал."
        },
        {
          "id": "nepredvidennye-posledstviya",
          "title": "Непредвиденные последствия",
          "subtitle": "У действия есть эффекты, которых не ждали: побочные, отложенные, на других. Даже простая правка дёргает соседнее — просто мы не всегда это видим."
        },
        {
          "id": "nelineynost",
          "title": "Нелинейность",
          "subtitle": "Не всё растёт поровну: удвоение усилий может дать ноль или вчетверо. Зависимости, пороги, насыщение — мир редко бывает прямой линией."
        },
        {
          "id": "krug-kompetentsiy",
          "title": "Круг компетенций",
          "subtitle": "Знай, что ты знаешь, и знай, где твоя граница. Оптимально — внутри круга; у границы — осторожно; за кругом — не берись или берись с проверкой."
        },
        {
          "id": "vtorichnye-posledstviya",
          "title": "Вторичные последствия",
          "subtitle": "Смотри на два шага вперёд: у решения есть следствия от следствий. То, что кажется выигрышем на первом ходе, часто проигрыш на втором."
        },
        {
          "id": "strategiya-shtangi",
          "title": "Стратегия штанги",
          "subtitle": "Держи два конца: очень безопасное и очень рискованное, — а середину избегай. Потери ограничены, выигрыш не ограничен; середняк часто хуже обоих."
        },
        {
          "id": "svoya-shkura",
          "title": "Своя шкура на кону",
          "subtitle": "Тот, кто рискует своим, решает иначе, чем тот, кто рискует чужим. Ответственность за результат меняет качество решений сильнее любых регламентов."
        },
        {
          "id": "mashtabiruemost",
          "title": "Масштабируемость",
          "subtitle": "Сработает ли то же самое в десять раз больше? Ручное не масштабируется, процесс — да. Проверяется не размер, а способность расти без перестройки."
        },
        {
          "id": "hrupkost",
          "title": "Хрупкость",
          "subtitle": "Хрупкое ломается от удара, антихрупкое — крепнет от него. Важно не «как выглядит», а «что будет при ударе». Хрупкость часто прячется за гладким фасадом."
        },
        {
          "id": "optsionalnost",
          "title": "Опциональность",
          "subtitle": "Ценность — в праве выбора, а не в одном выбранном варианте. Дешёвая опция, которой можно не воспользоваться, часто дороже всего конкретного."
        }
      ],
      "count": 25
    },
    {
      "id": "manual",
      "title": "Связки",
      "items": [
        {
          "id": "prodayushchaya-konsultaciya",
          "title": "Продающая консультация по структуре",
          "subtitle": "Созвон перестаёт быть разговором «посмотрим», когда у него есть структура: контакт, запрос, путь, препятствия, подтверждение, история, цена, закрытие. Харнесс держит эту структуру и следит, чтобы ни один шаг не потерялся."
        },
        {
          "id": "job-s-zayavkami",
          "title": "Работа с заявками после созвона: четыре сценария",
          "subtitle": "Главное в продаже — не созвон, а то, что после него. Каждый клиент попадает в один из четырёх сегментов (готов платить / подумать / не тянет / не интересно), и у каждого — своя коммуникация. Держать четыре очереди в голове нельзя — их держит система."
        },
        {
          "id": "trenirovka-prodazh",
          "title": "Тренировка продаж на нейросети: клиент-бот",
          "subtitle": "Продажи — навык, который натаскивается повторением: клиент-бот отыгрывает возражения, ты ведёшь структуру, после — разбор слабых мест. Копейки на токены вместо потерянных лидов на живых созвонах."
        },
        {
          "id": "lid-magnit",
          "title": "Лид-магнит: видео → страница → бот → заявка",
          "subtitle": "Лид-магнит — бесплатная ценность, которая забирает контакт: видео с обложкой, своя страница, бот с серией сообщений, заявка на консультацию. Каждый элемент собирается по шагам, а харнесс держит все шаги и материалы вместе."
        },
        {
          "id": "priem-oplat",
          "title": "Оплата и рассрочка: банк принимает решение, не ты",
          "subtitle": "Продавать на высокий чек — значит дать клиенту способ платить. Банковская рассрочка через платёжную страницу: банк сразу переводит тебе всю сумму, клиент возвращает без процентов, ты не бегаешь за платежами."
        },
        {
          "id": "voprosy-agentu",
          "title": "Вопросы из взрослой позиции: как просить, чтобы получать",
          "subtitle": "Ответ полезен ровно настолько, насколько хорош вопрос. Взрослая позиция — обозначить проблему, дать варианты, показать свою логику и только потом спросить. Это правило работает и с людьми, и с агентами."
        },
        {
          "id": "blog-zayavki",
          "title": "Блог, который приносит заявки, а не лайки",
          "subtitle": "Блог — топливо для заявок: календарь активностей, регулярные посты, призывы, эфиры и тесты. Харнесс ведёт календарь, готовит контент по структуре и следит, чтобы ничего не выпало из ритма."
        },
        {
          "id": "zapusk",
          "title": "Запуск: три касания до решения",
          "subtitle": "Запуск — это серия касаний по расписанию: 3 видео или эфира, прогрев, напоминания, открытие продаж. Харнесс собирает план запуска в задачи и ведёт каждую активность по сценарию."
        }
      ],
      "count": 8
    },
    {
      "id": "tasks",
      "title": "Задачи",
      "items": [
        {
          "id": "task-0",
          "title": "Карточки инструментов: проверка на реальных прогонах",
          "subtitle": "Проверено 29 позиций из 84: у каждой — параметры, границы и измеренный результат прогона. Остальное честно названо тумблерами, op-семействами, устройствами и панельными группировками"
        },
        {
          "id": "task-1",
          "title": "Семь историй о делах на странице",
          "subtitle": "Общее для всех чувство, своё дело и что с этой болью делается — плюс «Путь и снаряжение» и блок отклика"
        },
        {
          "id": "task-2",
          "title": "Страница живёт из репозитория",
          "subtitle": "Эфир, каталог, задачи и история собираются генератором из каталога харнесса, а не правятся руками в разметке"
        },
        {
          "id": "task-future-0",
          "title": "Публичный README и установка в одну команду",
          "subtitle": "Документация и запуск продукта одной командой для будущих пользователей"
        },
        {
          "id": "task-future-1",
          "title": "Чистка и документация кода",
          "subtitle": "Приведение кодовой базы к виду, пригодному для открытия"
        },
        {
          "id": "task-future-2",
          "title": "Наборы расширений и шаблонов для типовых задач",
          "subtitle": "Готовые практики и шаблоны поверх харнесса"
        }
      ],
      "count": 6
    },
    {
      "id": "open",
      "title": "Открытый код",
      "items": [
        {
          "id": "open-0",
          "title": "Что уже работает",
          "subtitle": "Конвейер допуска и аудита, память с квитанциями, главы сессий, роутинг моделей, браузерные профили, мост «страница → агент», карты кода."
        },
        {
          "id": "open-1",
          "title": "Что впереди",
          "subtitle": "Чистка и документация, установка «в одну команду», публичный интерфейс расширений, наборы практик и шаблонов под типовые задачи."
        },
        {
          "id": "open-2",
          "title": "Кому это нужно",
          "subtitle": "Всем, кто делает сам: мастеру с проектом, главе небольшого дела, студии из двух человек, инвестору, который хочет видеть, а не верить."
        }
      ],
      "count": 3
    }
  ]
}
