# Эксперимент: ИИ-ревьюер разрешений в OpenCode (autoapprove) **Дата:** 2026-10-11 **Статус:** эксперимент закрыт, плагин снят. Документ сохранён как описание системы и причин отказа — если идея вернётся, начинать отсюда. ## Итог одним абзацем Плагин `opencode-permission-reviewer` (LLM-ревьюер каждого `ask`) настроен и работоспособен, но признан не стоящим использования: хрупкая цепочка (ключ в окружении сервиса → региональный 451 на endpoint jev → прокси), плюс ревьюер нервно эскалует всё подряд в сессиях с «опасным» транскриптом. Боевой режим: `permission: autoaccept` + deny-паттерны на секреты + snapshots/git как обратимость. AFK для системного администрирования не достигнут: узкое место — не разрешения, а компетентность модели-исполнителя (glm flash провалил простые админские задачи: «делал странное с умным видом»). ## Как была устроена система Цепочка решений для каждого `ask` из `opencode.json`: 1. **Deny-паттерны** (`permission.bash`) — мгновенный отказ по строке команды, до моделей. Только секреты: `*.env*`, `*.secrets*`, `~/.ssh/*` и т.п. Паттерны слепы к содержимому скриптов — защита секретов, не рубеж. 2. **Jev** (`opencode/jev-1.13`, System One) — типизированный ревьюер: команда, свидетельства из транскрипта, содержимое локальных скриптов (read-only enrichment). Отвечает allow / deny / escalate. 3. **Второе мнение** (`opencode-go/glm-5.3-flash`) — трудные случаи, где jev неуверен. 4. **Финал** — `escalationMode`: `manual` (спросить человека; при `permission=autoaccept` на него отвечает auto) или `deny` (отказ с причиной). `enforcementMode`: `observe` (только аудит, дефолт) или `enforce`. ## Инфраструктурные грабли (главная ценность эксперимента) - Jev ходит на отдельный endpoint Zen `/zen/v1/systemone`. Zen закрывает его по региону (HTTP 451) — нужен прокси в окружении сервиса (`HTTPS_PROXY` в `~/.env.secrets`). Чат-модели Zen (`/zen/v1/chat/completions`) доступны без прокси; блокирован только systemone. Jev нет в общем каталоге моделей — это намеренно (не чат-модель), на плагин не влияет. - `OPENCODE_API_KEY` должен быть в окружении **процесса сервиса**. Сервис наследует окружение шелла, из которого запущен; после правки `~/.env.secrets` нужны `source` + рестарт из свежего шелла. Рестарт из старого шелла ключ не подхватывает. - Ревьюер зовётся из серверного процесса: рестарт сервиса из сессии агента рвёт саму сессию. - Emergency brake: команды, пахнущие выносом креденшелов (`curl -H "Authorization: ... $KEY"`), режутся детерминированно. - Конфиг плагина читается с O_NOFOLLOW: симлинк молча игнорируется, деплой только копией (см. `.stow-local-ignore`). ## Известные свойства поведения - Сессия, полная опасных команд в транскрипте, выглядит для ревьюера подозрительно: jev эскалует всё подряд, и с `escalationMode: deny` такая сессия становится неработоспособной — fail-closed по замыслу. - В этой сессии это проявилось полностью: заперт даже `git status`, отменить отказы изнутри сессии нельзя (явное разрешение в чате не помогло). - Пороги тонкой настройки (не крутились): `systemOneConfidenceThreshold` (дефолт 0.4), `systemOneReasoningThreshold` (дефолт 0.38), `confidenceThreshold` (чат-ревьюер, 0.7). - Установлено про авто-подтверждение без плагина: ручное approve при серии запросов вырождается в слепое «да» — честный auto + обратимость лучше декоративного ручного. ## Ссылки - Плагин и все опции: https://github.com/warc0s/opencode-permission-reviewer (README: https://npm.io/package/opencode-permission-reviewer) - Модель разрешений OpenCode V2: https://opencode.ai/v2/docs/permissions - Jev: https://jevmodel.org/ (прямой API TypeSafe с ключом `TYPESAFE_API_KEY` — запасной маршрут мимо Zen) - Аудит решений (на машине): `~/.local/share/opencode/permission-reviewer-audit.jsonl` - Снятый конфиг сохранён закомментированным в `opencode/.config/opencode/opencode.json`