---
pr: 193
title: fix(agents): add safe read-only commands to reviewer bash allow-list
---

## Что сделано
- Расширён bash allow-list в `.opencode/agents/reviewer.md` безопасными read-only командами:
  - `date` и `date *` — временные метки (лог показал 313 срабатываний catch-all, среди них `date +%Y-%m-%d`)
  - `sed -n *` — печать диапазона строк без авто-вывода (`-n` подавляет, `p` печатает)
  - `sort` и `sort *` — сортировка в stdout
  - `sort * -o *: deny` — defense-in-depth: `sort -o out.txt` пишет файл через процесс, обход `edit: deny` (аналог ADR-005 про echo). Поставлен ПОСЛЕ `sort *: allow` (findLast → deny побеждает для `-o` варианта, allow для остальных).
- Паттерн `git ls-files*` оставлен без изменений (уже присутствует в allow-list, строка 66). Проверка glob-matching в opencode: `git ls-files*` без пробела матчит `git ls-files` (без аргументов) и `git ls-files<anything>` включая `git ls-files .opencode/skills/` — паттерн корректен. Срабатывание catch-all в логе — вероятно артефакт устаревшей версии или другой причины; паттерн формально верен и не требует правки.
- Создан ADR-085 (`docs/decisions/085-pr-193-reviewer-bash-allowlist.md`) с обоснованием и risk-assessment для `sed -n ... w` и `date --set`.
- Guard-скрипт `check-permissions.py` запущен — новые правила не флагуются как опасные (exit 0).
- Global mirror `~/.config/opencode/agents/reviewer.md` синхронизирован через skill `configure-opencode` (edit in workspace → commit → push → pull на хосте; НЕ прямой правкой, согласно ADR-078).

## Почему
Анализ `opencode.log` (202 740 строк) выявил 313 срабатываний catch-all `"*": deny` в `reviewer.md`. Среди заблокированных — безопасные read-only inspection-команды, которые не создают write-bypass, но мешают ревьюеру продуктивно работать (печать диапазона строк, сортировка, временные метки). Catch-all by design (ADR-005 убрал `echo *` чтобы закрыть bypass), но он блокирует и безопасные команды. Расширение allow-list восстанавливает продуктивность ревьюера без ослабления read-only контракта.

## Pending
- После merge: `git pull` на хосте + рестарт opencode (MCP/agents грузятся при старте) — правки в `reviewer.md` не видны до рестарта.
- Для Docker-сетапа: `git pull` + `docker compose restart opencode`.

## Watch out
- `sed -n *` с командой `w` (`sed -n '1p; w out.txt'`) пишет файл внутренними средствами sed — нельзя закрыть через glob. Риск принят как низкий (редкая конструкция, альтернативы `cat`/`head`/`tail` неудобны для больших файлов). См. ADR-085 Risk Assessment.
- `date --set="..."` меняет системное время. В контейнере обычно нет root, на хосте нужен sudo (не в allow-list). Риск принят. См. ADR-085.
- `sort * -o *: deny` должен стоять ПОСЛЕ `sort *: allow` (findLast). При перестановке правил deny перестанет работать.
- НЕ добавлены write-bypass команды: `echo *` (ADR-005), `cp`, `awk` (может `>`), `xxd` (может `-r`), `sed` без `-n` (может `w`/`i`/`c`).
- `edit: deny` и catch-all `"*": deny` сохранены — read-only контракт ревьюера не нарушен.
- Спека issue #191 содержала опечатку: номер ADR указан как `084` (max+1), но `084` уже занят (`084-pr-192-add-boosty-chat-id-env.md`). Использован `085` (фактический max+1 согласно ADR-079). Зафиксировано, продолжено без отклонений.