# ADR-035: Commit tool staging truth + git restore --staged allow

## Статус
Accepted (2026-07-26)

## Контекст
Агент ругался что `commit` tool коммитит лишние файлы. Расследование показало: `commit.ts` НЕ делает `git add` — коммитит только уже staged файлы (`git diff --cached --name-only` → `git commit -m`). Подтверждено: ADR-015, handoff pr-38, тесты test_commit_tool.py, код commit.ts L42-56.

Root cause попадания лишних файлов в коммит — НЕ tool:
1. Агент сделал `git add -A` / `git add .` (allow) и забыл проверить staged set.
2. `memory_save` tool (плагин @mathew-cf/opencode-memory) stage'ит ВСЁ через `git add -A` под капотом — задокументированный gotcha (memory `technical/memory-save-git-add-all-gotcha.md`, инцидент PR#30 с SSH-ключами).
3. Агент не запустил `git status` перед `commit`.

Self-correction был заблокирован: `git reset *` = deny, `git restore --staged` = catch-all `ask` (требовал user approval). Агент не мог unstage лишнее без пользователя.

Дополнительно: handoff pr-73 L28/L32 содержал ЛОЖЬ — утверждал что `commit` tool делает `git add -A` под капотом. Автор перепутал с `memory_save` tool. Ложь активно вредила: будущие агенты могли верить, что staging вне их контроля, и не проверять `git status`. Memory `technical/commit-tool-staging-truth.md` зафиксировала этот баг.

## Решение
1. Исправить handoff pr-73 L28/L32 — заменить ложь про `git add -A` под капотом `commit` tool на корректное описание (tool коммитит только staged, staging ответственность агента).

2. Усилить skills: добавить явный `git status` шаг перед `commit` в 5 SKILL.md (add-skill, release, repo-init, run-pipeline ×3 Template A/B/D, configure-opencode ×2). Формулировка: «`commit` tool НЕ делает `git add` — коммитит только уже staged. Используй `git add <конкретные-пути>`, НЕ `git add -A`. Если лишнее stage'нулось — `git restore --staged <file>`.»

3. Расширить allow-list в opencode.json:
   - `"git restore --staged *": "allow"` (L180)
   - `"git -C * restore --staged *": "allow"` (L189)
   - Даёт агенту self-correction путь для unstage лишнего без user approval.

4. `git reset *` остаётся deny (L245) — `restore --staged` безопаснее (не трогает working tree, только индекс). `reset` может перемотать коммиты — поэтому deny.

5. `commit` tool API НЕ меняется (параметр `paths` не добавляется) — это отдельное решение через ADR + тесты, если проблема повторится.

## Альтернативы
1. Добавить параметр `paths?: string[]` в `commit` tool — отклонено (меняет tool API, требует тестов + обновления всех skills, отдельный PR. Backward-compatible, но не решает случай когда агент уже stage'нул лишнее через raw `git add -A`).

2. Запретить `git add -A` / `git add .` в permissions — отклонено (opencode glob-паттерны плохо различают `git add -A` от `git add src/foo.ts` — оба матчат `git add *`. Ненадёжно).

3. Добавить `git reset HEAD <file>` в allow — отклонено (`git reset *` deny защищает от перемотки коммитов, `restore --staged` безопаснее — только индекс, не трогает working tree и коммиты).

4. Оставить как есть (верить агенту на слово) — отклонено (агент уже ругался, проблема реальная, ложь в handoff pr-73 активно вредила).

5. Не править handoff pr-73 (исторический документ) — отклонено (handoff pr-73 содержит активную ложь про `commit` tool, которая сбивает будущих агентов. Исторические docs сохраняют оригинальное написание, но ложь про поведение tool — это documentation drift, не историческая конвенция).