fix(docs): commit tool staging truth + allow git restore --staged (#80)
Co-authored-by: opencode-agent <agent@opencode.local>
This commit is contained in:
parent
d641f7a65b
commit
4b377f3e4d
9 changed files with 134 additions and 6 deletions
|
|
@ -177,6 +177,7 @@
|
|||
"git diff*": "allow",
|
||||
"git log*": "allow",
|
||||
"git pull*": "allow",
|
||||
"git restore --staged *": "allow",
|
||||
"git -C * add *": "allow",
|
||||
"git -C * commit *": "allow",
|
||||
"git -C * push *": "allow",
|
||||
|
|
@ -185,6 +186,7 @@
|
|||
"git -C * status*": "allow",
|
||||
"git -C * diff*": "allow",
|
||||
"git -C * log*": "allow",
|
||||
"git -C * restore --staged *": "allow",
|
||||
"git -C * reset *": "deny",
|
||||
"git -C * clean *": "deny",
|
||||
"git -C * branch -D *": "ask",
|
||||
|
|
|
|||
|
|
@ -69,8 +69,14 @@ Implementing agent (subagent, которому делегировано созд
|
|||
```bash
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
git add .opencode/skills/<skill-name>/SKILL.md
|
||||
git status # проверь staged set — только SKILL.md, без лишнего
|
||||
```
|
||||
|
||||
> `commit` tool НЕ делает `git add` — коммитит только уже staged файлы. Если
|
||||
> в индексе лишнее (например `memory_save` stage'нул всё через `git add -A`)
|
||||
> — не коммить: сначала `git restore --staged <file>` или не stage'и его
|
||||
> изначально. Используй `git add <конкретные-пути>`, НЕ `git add -A`.
|
||||
|
||||
Затем через `commit` tool (НЕ raw `git commit` — заблокирован deny):
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ description: Use when adding, changing, or removing MCP servers, providers, perm
|
|||
## 2. Применение изменений
|
||||
|
||||
- `commit` + `push` в репо `slaid098/opencode-config` (через `commit` tool).
|
||||
- Перед каждым `commit` — `git status` для проверки staged set. `commit` tool
|
||||
НЕ делает `git add` — коммитит только уже staged файлы. Используй
|
||||
`git add <конкретные-пути>`, НЕ `git add -A` (иначе лишние файлы уйдут в
|
||||
коммит). Если в индексе лишнее (например `memory_save` stage'нул всё через
|
||||
`git add -A`) — сначала `git restore --staged <file>`, потом коммить.
|
||||
- В клонах: `git pull` + рестарт opencode (MCP-серверы, skills, agents грузятся при старте — см. `add-skill/SKILL.md`). До рестарта правки не видны.
|
||||
- Для Docker-сетапа: `git pull` на хосте + `docker compose restart opencode` (или эквивалент) — MCP/skills/agents грузятся при старте контейнера.
|
||||
|
||||
|
|
@ -106,7 +111,7 @@ description: Use when adding, changing, or removing MCP servers, providers, perm
|
|||
## 8. Commit message
|
||||
|
||||
- Формат: `feat(config): ...` / `chore(config): ...` / `fix(config): ...` (conventional commits, English, ≤72 chars).
|
||||
- Перед commit — использовать `commit` tool (валидация формата встроена), проверить `git log --oneline -20`, match existing style.
|
||||
- Перед commit — `git status` для проверки staged set (`commit` tool НЕ делает `git add` — коммитит только уже staged файлы; НЕ `git add -A`, иначе лишние файлы уйдут в коммит). Затем использовать `commit` tool (валидация формата встроена), проверить `git log --oneline -20`, match existing style.
|
||||
- Примеры: `feat(config): add integrations MCP server`, `fix(config): correct timeout for integrations discover tool`.
|
||||
|
||||
## 9. Не дублировать блоки между репо
|
||||
|
|
|
|||
|
|
@ -41,8 +41,14 @@ description: Выполняет релиз после мерджа PR — обн
|
|||
|
||||
```bash
|
||||
git add CHANGELOG.md
|
||||
git status # проверь staged set — только CHANGELOG.md, без лишнего
|
||||
```
|
||||
|
||||
> `commit` tool НЕ делает `git add` — коммитит только уже staged файлы. Если
|
||||
> в индексе лишнее (например `memory_save` stage'нул всё через `git add -A`)
|
||||
> — не коммить: сначала `git restore --staged <file>` или не stage'и его
|
||||
> изначально. Используй `git add <конкретные-пути>`, НЕ `git add -A`.
|
||||
|
||||
Затем через `commit` tool (НЕ raw `git commit` — заблокирован deny):
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -38,8 +38,14 @@ description: Sequential checklist: create GitHub remote → configure settings/b
|
|||
git init
|
||||
echo "# <repo-name>" > README.md
|
||||
git add README.md
|
||||
git status # проверь staged set — только README.md, без лишнего
|
||||
```
|
||||
|
||||
> `commit` tool НЕ делает `git add` — коммитит только уже staged файлы. Если
|
||||
> в индексе лишнее (например `memory_save` stage'нул всё через `git add -A`)
|
||||
> — не коммить: сначала `git restore --staged <file>` или не stage'и его
|
||||
> изначально. Используй `git add <конкретные-пути>`, НЕ `git add -A`.
|
||||
|
||||
Затем через `commit` tool (НЕ raw `git commit` — заблокирован deny):
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ description: Автономный исполнитель PR-пайплайна.
|
|||
4. Коммиты через `commit({ message: "type(scope): description" })` tool (НЕ
|
||||
raw `git commit` — заблокирован deny). Формат: ≤72 chars, English, no
|
||||
period, no body unless necessary. Минимум 3-4 логических коммита.
|
||||
Перед КАЖДЫМ `commit` — `git status` для проверки staged set. `commit`
|
||||
tool НЕ делает `git add` — коммитит только уже staged файлы. Используй
|
||||
`git add <конкретные-пути>`, НЕ `git add -A` (иначе лишние файлы уйдут в
|
||||
коммит). Если в индексе лишнее (например `memory_save` stage'нул всё
|
||||
через `git add -A`) — не коммить: сначала `git restore --staged <file>`.
|
||||
5. Push ветку (`git push -u origin HEAD`), затем создай PR через tool:
|
||||
`create-pr({ title: "type(scope): description", body: "## Что сделано\n...\n\n## Почему\n...\n\nCloses #N", issue_number: N })`.
|
||||
6. После получения PR номера — исправь placeholder `<PR-NUMBER>` в handoff
|
||||
|
|
@ -72,8 +77,11 @@ Review PR#M в текущем репо (pre-merge, режим docs).
|
|||
Решение, Альтернативы).
|
||||
6. Если криво — почини (edit: allow).
|
||||
7. `git add docs/project-map/ docs/handoff/ docs/decisions/` (add — НЕ
|
||||
заблокирован), затем `commit({ message: "docs: update project map + handoff + ADR" })`
|
||||
tool, и `git push`.
|
||||
заблокирован). Перед `commit` — `git status` для проверки staged set
|
||||
(`commit` tool НЕ делает `git add` — коммитит только staged; НЕ
|
||||
`git add -A`, иначе лишние файлы уйдут в коммит). Затем
|
||||
`commit({ message: "docs: update project map + handoff + ADR" })` tool,
|
||||
и `git push`.
|
||||
8. **ВСЕГДА** оставь PR comment (даже если structural changes нет) — это
|
||||
детерминированный marker для `check_docs` в pipeline-status.py. Без comment
|
||||
pipeline блокируется на DOCS phase. Используй tool `post-docs-review` (НЕ
|
||||
|
|
@ -116,7 +124,10 @@ Log: `gh run view <run-id> --log-failed` output:
|
|||
1. `gh pr checkout M`.
|
||||
2. Проанализируй log, найди причину.
|
||||
3. Исправь (минимальные изменения, whitespace/formatting/logic fix).
|
||||
4. Коммит через `commit({ message: "fix(ci): <description>" })` tool (НЕ raw
|
||||
4. Перед коммитом — `git status` для проверки staged set (`commit` tool НЕ
|
||||
делает `git add` — коммитит только staged; используй
|
||||
`git add <конкретные-пути>`, НЕ `git add -A`). Коммит через
|
||||
`commit({ message: "fix(ci): <description>" })` tool (НЕ raw
|
||||
`git commit`), push.
|
||||
5. Не трогай логику unrelated файлов.
|
||||
```
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# 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, не историческая конвенция).
|
||||
|
|
@ -25,8 +25,8 @@ Debian 13 trixie НЕ использует snap (в отличие от Ubuntu n
|
|||
- memory update `technical/opencode-log-subagent-stumbles-analysis.md` (noble-slim не существует → trixie-slim) — на фазе MEMORY через memory-syncer subagent, если pipeline дойдёт
|
||||
|
||||
## Watch out
|
||||
- **`commit` tool делает `git add -A` под капотом** — staged-группировка НЕ сохраняется. Если в индексе есть лишние файлы (например `package-lock.json`), они уйдут в коммит вместе с целевыми. Урок: проверять `git status` перед `commit` и `git reset` лишнее заранее. Но `git reset *` заблокирован deny в `opencode.json:311-314` — нельзя перемотать неудачный коммит через raw bash. Workaround: новый `commit --amend` тоже не доступен (tool не принимает `--amend`), только новый коммит поверх.
|
||||
- **`commit` tool НЕ делает `git add`** — коммитит только уже staged файлы (`git diff --cached --name-only` → `git commit -m`). Staging ответственность агента: `git add <files>` явно перед `commit`. Если в индексе случайно оказались лишние файлы (например `package-lock.json` через `git add -A`), они уйдут в коммит. Урок: проверять `git status` перед `commit`. Для unstage лишнего: `git restore --staged <file>` (added to allow-list в PR#80, ADR-035) — `git reset *` заблокирован deny (`opencode.json:311-314`). См. ADR-035, memory `technical/commit-tool-staging-truth.md`.
|
||||
- **Урок PR#71: проверять существование Docker тега через Docker Hub API перед коммитом.** `curl -s "https://hub.docker.com/v2/repositories/library/node/tags/noble-slim/" | jq .` — `name: null` = тег не существует. `trixie-slim` возвращает `name: "trixie-slim"`. Также `curl -s "https://hub.docker.com/v2/repositories/library/node/tags?page_size=100&name=trixie"` — список реальных trixie тегов.
|
||||
- **scaffold-handoff.sh создаёт и ADR, и handoff** — для этого PR ADR уже существовал (030-pr-71-...), но паттерн поиска `*-pr-<PR>-<slug>.md` использует PR=73 → не нашёл 030-pr-71 → создал пустой файл `031-pr-73-*.md`. Лишний файл `031-pr-73` удалён вручную (`rm`, не `git rm` — файл ещё не в индексе). Если scaffold запускается после переименования ADR с другим PR-номером — нужно либо переименовать ADR ДО scaffold под целевой PR, либо удалять дубликат после.
|
||||
- **pipeline-status.py ищет handoff по PR-номеру, НЕ issue-номеру** — конвенция репо: `pr-<PR>-<slug>.md`. PR#71 handoff назван по исходному PR#71 (который этот PR исправляет), поэтому pipeline-status для PR#73 не находил его → нужен отдельный `pr-73-*.md`. См. memory `technical/video_uniq-pr51-channel-profile-discoveries.md` §2.
|
||||
- **`.opencode/package-lock.json` untracked** — не относится к этому PR (зафиксировано в pr-69 handoff), не коммитить. `git status` показывает его как untracked — нужно игнорировать при `commit` (tool сделает `git add -A`, если файл не в `.gitignore` → уйдёт в коммит).
|
||||
- **`.opencode/package-lock.json` untracked** — не относится к этому PR (зафиксировано в pr-69 handoff), не коммитить. `git status` показывает его как untracked — нужно игнорировать при `commit` (агент должен `git add` только целевые файлы, НЕ `git add -A`; `commit` tool коммитит только staged, не делая `git add` сам — см. Watch out выше).
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
pr: 80
|
||||
title: fix(docs): commit tool staging truth + allow git restore --staged
|
||||
---
|
||||
|
||||
## Что сделано
|
||||
3 направления правок, 7 файлов изменено (+50/-6 строк примерно).
|
||||
|
||||
1. Исправлена ложь в handoff pr-73 (L28, L32) про `commit` tool.
|
||||
- `docs/handoff/pr-73-base-image-trixie-slim.md` L28: было «`commit` tool делает `git add -A` под капотом» — ЛОЖЬ. Стало: «`commit` tool НЕ делает `git add` — коммитит только уже staged файлы (`git diff --cached --name-only` → `git commit -m`). Staging ответственность агента: `git add <files>` явно перед `commit`.»
|
||||
- L32: аналогично — было «tool сделает `git add -A`, если файл не в .gitignore → уйдёт в коммит», стало «агент должен `git add` только целевые файлы, НЕ `git add -A`; `commit` tool коммитит только staged, не делая `git add` сам».
|
||||
- Причина лжи: автор handoff pr-73 перепутал `commit` tool с `memory_save` tool (плагин @mathew-cf/opencode-memory), который ДЕЙСТВИТЕЛЬНО делает `git add -A` под капотом (задокументированный gotcha, memory `technical/memory-save-git-add-all-gotcha.md`, инцидент PR#30 с SSH-ключами). См. ADR-035, memory `technical/commit-tool-staging-truth.md`.
|
||||
|
||||
2. Усилены skills: добавлен явный `git status` шаг перед `commit` в 5 SKILL.md.
|
||||
- `.opencode/skills/add-skill/SKILL.md` — `git status` в bash-блок + blockquote с правилом
|
||||
- `.opencode/skills/release/SKILL.md` — `git status` в bash-блок + blockquote с правилом
|
||||
- `.opencode/skills/repo-init/SKILL.md` — `git status` в bash-блок + blockquote с правилом
|
||||
- `.opencode/skills/run-pipeline/SKILL.md` — 3 вставки: Template A (общее правило перед КАЖДЫМ commit: `git status` + `git add <конкретные-пути>` НЕ `git add -A`), Template B (`git status` между add/commit), Template D (`git status` перед commit)
|
||||
- `.opencode/skills/configure-opencode/SKILL.md` — 2 вставки: секция 2 (prose bullet) + секция 8 (усиление существующей строки)
|
||||
- Формулировки единообразны: «`commit` tool НЕ делает `git add` — коммитит только уже staged файлы. Используй `git add <конкретные-пути>`, НЕ `git add -A`. Если лишнее stage'нулось — `git restore --staged <file>` (теперь в allow-list).»
|
||||
|
||||
3. Расширен allow-list в opencode.json для self-correction staging.
|
||||
- `.opencode/opencode.json` — добавлены 2 правила в allow:
|
||||
- `"git restore --staged *": "allow"` (L180)
|
||||
- `"git -C * restore --staged *": "allow"` (L189)
|
||||
- Даёт агенту возможность unstage случайно добавленные файлы без user approval. Раньше `git restore --staged` был в catch-all `ask` (требовал подтверждения пользователя), а `git reset *` — deny (не давал unstage вообще). См. ADR-035.
|
||||
- Проверено: `git restore --staged *` не матчится ни одним deny-rule (`git reset *` L245, `git clean *` L246 — другие команды, не matчат restore).
|
||||
|
||||
## Почему
|
||||
Агент ругался что `commit` tool коммитит лишние файлы. Root cause НЕ в tool — `commit.ts` коммитит только уже staged файлы (`git diff --cached --name-only` → `git commit -m`), НЕ делая `git add` (подтверждено ADR-015, handoff pr-38, тестами test_commit_tool.py, кодом commit.ts L42-56).
|
||||
|
||||
Причины попадания лишних файлов в коммит:
|
||||
1. Агент сделал `git add -A` / `git add .` (allow) и забыл/не заметил, что staged лишнее.
|
||||
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` для проверки staged set.
|
||||
|
||||
Self-correction был заблокирован: `git reset *` = deny (L245), `git restore --staged` = catch-all `ask` (требовал user approval). Если случайно stage'нул лишнее — агент не мог unstage без пользователя.
|
||||
|
||||
Handoff pr-73 L28/L32 содержал ложь про `git add -A` под капотом `commit` tool — активно вредил: будущие агенты могли верить, что staging вне их контроля, и не проверять `git status`.
|
||||
|
||||
Решение: (1) исправить ложь в handoff pr-73, (2) усилить skills явным `git status` шагом перед `commit`, (3) добавить `git restore --staged` в allow-list для self-correction. См. ADR-035.
|
||||
|
||||
## Pending
|
||||
—
|
||||
|
||||
## Watch out
|
||||
- `memory_save` tool (MCP plugin @mathew-cf/opencode-memory) ДЕЙСТВИТЕЛЬНО делает `git add -A` под капотом — это НЕ исправлено (плагин сторонний, так задумано). Это отдельный gotcha (memory `technical/memory-save-git-add-all-gotcha.md`). Новый `git restore --staged` allow-rule даёт агенту путь self-correction после `memory_save`.
|
||||
- `git reset *` остаётся deny (L245) — `restore --staged` безопаснее (не трогает working tree, только индекс). `reset` может перемотать коммиты — поэтому остаётся deny.
|
||||
- Handoff pr-73 исправлен, но историческая ложь осталась в memory `technical/commit-tool-staging-truth.md` (создан в предыдущей сессии) — там зафиксировано что handoff pr-73 L28/L32 WRONG. Memory обновлять не нужно (она уже корректна).
|
||||
- `commit` tool не имеет параметра `paths` (только `message`) — агент должен `git add <files>` явно перед `commit`. Добавление параметра `paths` в tool API — отдельное решение (через ADR + тесты), не в этом PR.
|
||||
- Check-permissions.py guard script прогон обязателелен в CI (permissions-check.yml) — проверяет что новые allow-паттерны не опасны. В этом PR `git restore --staged *` — безопасный (только индекс, не working tree, не коммиты).
|
||||
Loading…
Add table
Reference in a new issue