Плагин настроен и проверен (jev через Zen + прокси, enforce+deny), но признан не стоящим использования: хрупкая цепочка, нервные эскалации, запертая сессия. Запись в opencode.json отключена (закомментирована), выводы — в docs/research/.
5.9 KiB
Эксперимент: ИИ-ревьюер разрешений в OpenCode (autoapprove)
Дата: 2026-10-11 Статус: эксперимент закрыт, плагин снят. Документ сохранён как описание системы и причин отказа — если идея вернётся, начинать отсюда.
Итог одним абзацем
Плагин opencode-permission-reviewer (LLM-ревьюер каждого ask) настроен и
работоспособен, но признан не стоящим использования: хрупкая цепочка (ключ в
окружении сервиса → региональный 451 на endpoint jev → прокси), плюс ревьюер
нервно эскалует всё подряд в сессиях с «опасным» транскриптом. Боевой режим:
permission: autoaccept + deny-паттерны на секреты + snapshots/git как
обратимость. AFK для системного администрирования не достигнут: узкое место —
не разрешения, а компетентность модели-исполнителя (glm flash провалил простые
админские задачи: «делал странное с умным видом»).
Как была устроена система
Цепочка решений для каждого ask из opencode.json:
- Deny-паттерны (
permission.bash) — мгновенный отказ по строке команды, до моделей. Только секреты:*.env*,*.secrets*,~/.ssh/*и т.п. Паттерны слепы к содержимому скриптов — защита секретов, не рубеж. - Jev (
opencode/jev-1.13, System One) — типизированный ревьюер: команда, свидетельства из транскрипта, содержимое локальных скриптов (read-only enrichment). Отвечает allow / deny / escalate. - Второе мнение (
opencode-go/glm-5.3-flash) — трудные случаи, где jev неуверен. - Финал —
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