Brainstorm (экономия 5%) с Дмитрием: лечим два класса инцидентов параллельных сессий — (A) субагенты теряются между worktree (Sprint 6 паттерн); (B) нормативка/MEMORY дрейфует (Tooling v2.11 collision 17.05.2026). Решение из 4 артефактов, 0 новых плагинов/MCP: 1. Pravila §15 (новое hard-rule): §15.1 субагенты+git (Sonnet/Opus only), §15.2 нормативка+pre-flight sync (фиксированный список 8 файлов). 2. docs/sessions/CURRENT.md — заявочный лог активных сессий + claim/check/release. 3. .claude/hooks/subagent-prompt-prefix.mjs — PreToolUse-хук, инжектит cwd/branch/HEAD заголовок в каждый Task-prompt. 4. Verify-протокол в скиле subagent-driven-development — pre/post-subagent чеклист + обязательный GIT REPORT блок от субагента. Acceptance в §8 spec'а. Spec — черновик → ревью заказчика → writing-plans. +cspell-words: коммитит / инвокейшн / парсимый (валидные транслитерации). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
23 KiB
Параллельные сессии: координация — дизайн
Дата: 2026-05-18
Автор: Claude (Opus 4.7, brainstorming с Дмитрием, экономия 5%)
Статус: черновик → ревью заказчика → writing-plans
Связано: Pravila §12 / §14 (hard rules), memory feedback_subagent_git_reliability.md, Sprint 6 инцидент.
0. Контекст и проблема
При параллельной работе нескольких Claude-сессий на одном репозитории — что является ежедневной нормой проекта (на 18.05.2026 в git worktree list 16 активных worktrees) — наблюдаются два класса инцидентов:
Класс A — субагенты теряются между worktree.
Запущенный из контроллера субагент (особенно Haiku) путает рабочую директорию или ветку: коммитит в чужую ветку, делает orphan-коммит, не возвращает git-state в отчёте. Прецедент — Sprint 6: Haiku-субагенты угнали ветку параллельной сессии, инцидент устранён через git reflog + reset. Корневая причина — контроллер не верифицирует HEAD/branch после Task-инвокации.
Класс B — нормативка/MEMORY дрейфует.
Параллельные сессии правят один и тот же набор файлов (Pravila / CLAUDE.md / Tooling / PSR_v1 / MEMORY.md / Открытые_вопросы_*.md) и претендуют на один version-номер. Прецедент — 17.05.2026: ADR-006 D4 и C10 одновременно претендовали на Tooling v2.11, C10 пришлось переномеровать в v2.12 (видно в шапке CLAUDE.md). За неделю 18.05.2026 разделы A11/A3/A4/A6/C9/C10/discovery-interview — все 7 — трогали один набор из 4 нормативных файлов.
Обе проблемы — следствие одного: параллельность без явного контракта на scope.
1. Архитектура
Решение из 4 артефактов, без новых плагинов / MCP-серверов:
- Pravila §15 (новое hard-rule) — два пункта: §15.1 (субагенты + git), §15.2 (нормативка + pre-flight sync). Hard-rule = §9 «Отступления» не применяется (как §12 и §14).
docs/sessions/CURRENT.md— заявочный лог активных параллельных сессий..claude/hooks/subagent-prompt-prefix.mjs— PreToolUse-хук, инжектящий в каждыйTask-prompt заголовок git-safety.- Verify-протокол в скиле
superpowers:subagent-driven-development— pre-spawn + post-subagent чеклист контроллера.
Зависимости: артефакт 1 (Pravila §15) — корень всех правил; артефакты 2–4 ссылаются на §15.1 / §15.2 как enforcement floor.
2. Pravila §15 — текст обоих пунктов
§15.1 Субагенты + git
Git-коммит-задачи субагенту (любой
Task-инвокейшн, чей prompt содержитgit commit,git push,git stage,git checkout,git switch,git merge,git rebase, либо где явно ожидается коммит в результате) — только модель Sonnet или Opus, никогда Haiku. Контроллер, делегирующий git-операцию Haiku-субагенту — нарушение §15.1, фиксируется в feedback того же уровня, что §12.Исключение — read-only git-операции (
git log,git status,git diff,git rev-parse,git branch --show-current,git worktree list) — разрешены любой модели.
§15.2 Нормативные правки + pre-flight sync
Любая правка файлов из списка «нормативка» (см. ниже) выполняется только на актуальной базе
origin/main. Pre-flight обязателен:git fetch origin && git log HEAD..origin/main --oneline— если есть untracked commits на origin/main, ребейз/merge до начала правки, не после.Параллельная нормативная правка на устаревшей базе — нарушение §15.2. Признак нарушения: коммит правит файл, чья последняя версия на
origin/mainновее, чем версия в parent коммите правки.Список «нормативка» — 8 позиций:
docs/Pravila_raboty_Claude_v1_1.mdCLAUDE.mddocs/Tooling_v8_3.mddocs/Plugin_stack_rules_v1.mdmemory/MEMORY.md(и всеmemory/*.md)docs/Открытые_вопросы_v8_3.mddocs/adr/*.md(glob — collision на ADR-NNN номере = тот же класс, что version-bump нормативки)db/schema.sql(параллельные миграции из разных сессий = реальный риск; запись вdb/CHANGELOG_schema.mdсама не защищает от version-base дрейфа)Расширение списка — отдельная правка §15.2, не «по ощущениям».
§15.3 Cross-refs в других файлах
- CLAUDE.md §1 priority chain — упомянуть §15 рядом с §12 и §14 как hard-rules (footer-абзац после цепочки).
- PSR_v1 — не правится (§15 не про координацию плагинов, а про координацию сессий).
- Tooling — не правится.
3. docs/sessions/CURRENT.md — заявочный лог
3.1 Формат
Один markdown-файл, append-only, парсимый. Запись на каждую активную параллельную сессию:
## session: 2026-05-18-discovery-interview
- branch: worktree-discovery-interview
- worktree: c:/моя/проекты/портал crm/Документация-discovery
- started: 2026-05-18T14:30+03:00
- scope-files:
- docs/Tooling_v8_3.md §4.30
- docs/Pravila_raboty_Claude_v1_1.md §13.2
- docs/Plugin_stack_rules_v1.md R10.1
- CLAUDE.md §3.3 #55
- docs/adr/009-*.md (new)
- version-claims:
- Tooling: 2.12 → 2.13
- Pravila: 1.25 → 1.26
- PSR_v1: 3.11 → 3.12
- CLAUDE.md: 2.12 → 2.13
- status: in-progress
- closes: docs/superpowers/plans/2026-05-18-discovery-interview-integration.md
3.2 Жизненный цикл записи
- claim — на старте сессии (до первой нормативной правки) контроллер добавляет запись + атомарный коммит
sessions: claim <topic>. Отдельный коммит от plan-документа. - check — pre-flight перед своей правкой:
Read docs/sessions/CURRENT.md+ scan записей соstatus: in-progress. Конфликт = пересечениеscope-filesИЛИversion-claimsс активной соседней сессией. - release — на закрытии (push на main) контроллер меняет
status: closed-<commit-sha>. Append-only-вариант (closed-записи остаются). Closed-записи переезжают вdocs/sessions/archive/YYYY-MM.mdчерез ≥30 дней после закрытия (ручная архивация раз в месяц, не cron).
3.3 Конфликт-резолюция
- Файловое пересечение (две сессии правят один и тот же файл, не обязательно одну секцию) — soft-warn, продолжать можно, но pre-flight fetch перед каждым коммитом обязателен (§15.2).
- Section-пересечение (одна и та же секция §X.Y) — hard-stop, координация с заказчиком до начала правки.
- Version-claim collision (две сессии заявили один номер) — hard-stop, кто claim'нул раньше (по timestamp в CURRENT.md) — тот его и берёт; вторая сессия сдвигается на +1.
3.4 Что НЕ включаем (YAGNI)
- TTL / auto-expire записей — добавим, если файл реально засорится.
- Machine-readable JSON-формат — markdown достаточен, парсится
grep/sed. - Интеграция с GitHub Issues — отдельная тема, не блокер.
- Pre-commit hook на проверку CURRENT.md — добавим только если будут зафиксированы инциденты игнорирования.
3.5 Pre-flight snippet (для plan-документов и скила)
# Перед нормативной правкой:
git fetch origin && git log HEAD..origin/main --oneline
grep -A 20 'status: in-progress' docs/sessions/CURRENT.md
4. Хук .claude/hooks/subagent-prompt-prefix.mjs
4.1 Тип и matcher
Тип хука — PreToolUse, matcher Task. Перехватывает tool_input.prompt, дописывает в начало обязательный заголовок git-safety, возвращает модифицированный prompt через стандартный JSON-output API хук-системы Claude Code:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "git-safety header injected (Pravila §15.1)",
"updatedInput": { "prompt": "<header>\n\n<original prompt>" }
}
}
Точный формат API подтвердить против реально работающих tools/ruflo-queen-hook.mjs / tools/ruflo-recall-hook.mjs на этапе имплементации.
4.2 Тело заголовка
=== SUBAGENT GIT-SAFETY HEADER (Pravila §15.1, auto-injected) ===
Working directory (cwd): <absolute path>
Branch (git branch --show-current): <branch-name>
Parent commit (git rev-parse HEAD): <sha>
Worktree root (git rev-parse --show-toplevel): <path>
ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:
1. Все git-операции выполняй ТОЛЬКО внутри cwd выше. Если pwd ≠ cwd — STOP, верни ошибку.
2. ЗАПРЕЩЕНО: `git checkout <branch>`, `git switch <branch>`, `git checkout -b`, `git branch -m`, `git worktree add/remove`, `git push --force`, `git reset --hard`.
3. После КАЖДОГО `git commit` — выполни `git rev-parse HEAD` и `git branch --show-current`, выпиши результат в ответ. Это обязательная часть отчёта.
4. Если обнаружил, что находишься не в той ветке/worktree — STOP, не правь ничего, верни ошибку с raw output `git status` и `git branch --show-current`.
5. Если задача не требует git-операций (только Edit/Read/Grep) — этот блок информационный, follow rule 1.
=== END SUBAGENT GIT-SAFETY HEADER ===
<здесь — оригинальный prompt контроллера>
4.3 Резолюция переменных
Хук резолвит 4 значения сам в момент инжекта — не из контроллера. Резолв через стандартный Node child-process API c fixed-string git-командами (без подстановки user-input в shell — все аргументы статичны: git rev-parse HEAD, git rev-parse --show-toplevel, git branch --show-current, pwd/process.cwd()). Контроллер мог быть запущен в одной директории, но Task инвокируется по факту в ней же — хук берёт process.cwd() рантайма.
4.4 Какие модели затрагиваются
Заголовок инжектится для всех Task-инвокаций (универсально). §15.1 (Sonnet-only для git) — не в хук, а в Pravila + чеклист скила (Секция 5). Хук не знает, является ли задача git-задачей: анализ prompt'а — ненадёжный signal, пусть это решает контроллер.
4.5 Edge-cases
- Task без git (только read/edit) — заголовок присутствует, безвреден (rule 5 нейтрализует).
- Контроллер уже включил похожий заголовок — двойная защита, не проблема.
- Хук упал (например,
gitне в PATH) — возвращает{"continue": true}без модификации prompt'а + логирует stderr. Не блокирующий: лучше Task без заголовка, чем сломанный Task. - Несколько worktree в разных терминалах — каждый запуск Claude Code имеет свой cwd, хук резолвит локально.
4.6 Объём и latency
~60 строк JS, паттерн один-в-один с tools/ruflo-queen-hook.mjs / tools/ruflo-recall-hook.mjs. Latency ~5–10 мс на Task (3 локальных git-вызова).
5. Verify-протокол в скиле subagent-driven-development
5.1 Где живёт
Добавочный чеклист-блок в скиле superpowers:subagent-driven-development:
- если скил вендорится в
.claude/skills/— патчится напрямую; - если только marketplace-скил без локальной копии — добавляем
references/git-safety-checklist.mdрядом + одну строку «обязательный verify-блок после каждого субагента» в проектную обёртку. Фактический способ решается при имплементации (см. §7 ограничения).
5.2 Pre-spawn чеклист (до Task-инвокации)
- Резолвить и записать: cwd, branch, parent SHA, worktree root — те же 4 значения, что инжектит хук. Контроллер хранит их у себя для post-check.
- Если задача git-коммит → выбрать model
sonnetилиopus. Никогдаhaiku(§15.1). - Если задача правит нормативку из списка §15.2 → pre-flight
git fetch && git log HEAD..origin/main --oneline. Не пусто → ребейз до инвокации, не после.
5.3 Post-subagent чеклист (сразу после возврата)
git rev-parse HEAD— сравнить с pre-spawn parent SHA. Ожидание: либо равно (субагент не коммитил), либо отличается ровно одним коммитом на pre-spawn HEAD.git branch --show-current— сравнить с pre-spawn branch. Не равно → STOP, разбор инцидента (Sprint 6 паттерн).git log -1 --format='%s%n%P'— проверить subject (соответствует задаче?) + parent (родитель = pre-spawn HEAD?).- Если субагент коммитил несколько коммитов — не запрещено, но требует ручной проверки subject'ов.
5.4 Red-flag-список (любой = hard-stop разбор)
- branch ≠ ожидаемая;
- parent коммита ≠ pre-spawn HEAD (= висячий коммит / попадание на чужую ветку);
- HEAD двинулся, но субагент в отчёте об этом не упомянул;
- в diff'е есть файлы вне scope задачи.
5.5 Формат отчёта субагента
Субагент обязан выписать в конце ответа блок:
=== GIT REPORT ===
cwd: <pwd>
branch: <git branch --show-current>
HEAD: <git rev-parse HEAD>
HEAD^: <git rev-parse HEAD^>
status: <git status --short>
=== END GIT REPORT ===
Отсутствие блока = контроллер считает результат недостоверным и запускает 5.3-чеклист сам через Bash.
5.6 Соотношение с code-review
Двухстадийное review сохраняется (Pravila §4.5 / R10 PSR_v1): сильная модель делает code-review артефакта субагента. Git-safety-чеклист не заменяет code-review, он стоит до него (нет смысла ревьюить diff, если он не в той ветке).
6. Тесты, migration, контракт записи
6.1 Тесты самих защит
| Защита | Тест | Ожидание |
|---|---|---|
| Хук (inject) | echo '{"tool_input":{"prompt":"X"}}' | node .claude/hooks/subagent-prompt-prefix.mjs |
updatedInput.prompt начинается с === SUBAGENT GIT-SAFETY HEADER ===; cwd/branch/HEAD — реальные |
| Хук — failure-mode | временно сломать (mv .git → .git.bak) → запустить хук |
{"continue":true}, без модификации; Task не должен крашиться |
| Verify-протокол (5.3) | Task субагенту с prompt "do nothing, run git status, return" |
в ответе субагента — блок === GIT REPORT ===; контроллер сверяет HEAD до/после — должны быть равны |
| §15.1 enforcement | Ручной dry-run: попытаться делегировать git commit Haiku-субагенту |
согласно чеклисту контроллер отказывается и перенаправляет Sonnet'у |
| §15.2 pre-flight | Симулировать diverged state: git fetch + сделать divergence → попытаться правнуть Pravila |
pre-flight snippet ловит, требует rebase |
| CURRENT.md claim collision | Две параллельные сессии: добавить запись с тем же version-claim | вторая сессия должна вручную увидеть конфликт через grep version-claims |
Никакой автоматизации сверх этого (no pre-commit hook, no CI check) — YAGNI. Если CURRENT.md начнёт игнорироваться — добавим pre-commit grep отдельной правкой.
6.2 Migration существующих параллельных worktrees
На момент 18.05.2026 — 16 активных worktree (git worktree list). Шаги:
- После merge §15 + хука + CURRENT.md на
main— каждая активная worktree-сессия делаетgit fetch+ ребейз на свежийmain(получает §15 + хук). - Каждая активная сессия дописывает свою запись в CURRENT.md одним коммитом (
sessions: backfill claim <topic>) — не блокирует работу, retro-claim. - Существующие version-collision'ы (A11 / C9 / A4 / discovery — последние 2 недели) не пересматриваем; §15 действует с момента введения, не ретроактивно.
6.3 Что НЕ делаем сейчас (явный YAGNI)
- Реестр зарезервированных версий — пропущен;
- pre-commit hook на CURRENT.md — пропущен;
- машинно-читаемый JSON-формат CURRENT.md — пропущен;
- запрет параллельных сессий — нет, параллельность — норма проекта;
- изменения PSR_v1 / Tooling — не требуются, §15 — внутри Pravila;
- subagent-без-git (вариант C из брейншторма) — отложен до повторного инцидента после A+B.
7. Ограничения / что не верифицировано в дизайне
- Не верифицировал через grep, что в Pravila нет пересекающихся правил под номером §15 — проверено в формате headings
## 13. ... / ## 14. ..., §15 свободен. Подтверждено на этапе brainstorming. - Не верифицировал API хук-системы Claude Code на актуальной версии CLI — формат
updatedInputв PreToolUse для Task tool требует подтверждения против реально работающихtools/ruflo-queen-hook.mjs/tools/ruflo-recall-hook.mjsперед написанием хука. Задача имплементации, не дизайна. - Не верифицировал, что
subagent-driven-developmentскил вендорится в.claude/skills/. Может быть только маркетплейс-скил без локальной копии — фактический способ патчинга решится при имплементации (Секция 5.1). - Не верифицировал Windows-специфику резолва
git-команд через Node child-process в хуке — на Windows работало дляruflo-queen-hook.mjs, должно работать и здесь.
8. Acceptance criteria (для writing-plans)
Дизайн считается реализованным, когда:
- Pravila §15 (15.1 + 15.2) добавлен, версия Pravila bumped, CHANGELOG entry есть.
docs/sessions/CURRENT.mdсоздан, формат описан в README рядом, в нём есть retro-claim запись для всех активных worktrees на момент имплементации (Migration §6.2; на дату дизайна — 16 штук)..claude/hooks/subagent-prompt-prefix.mjsнаписан, зарегистрирован в.claude/settings.json, прошёл тесты 6.1 (рукопись + failure-mode + e2e Task).- Скил
subagent-driven-developmentпатчен (5.1) — verify-протокол доступен контроллеру. - CLAUDE.md §1 cross-ref на §15 добавлен.
- Pre-commit gitleaks + Pest/Vitest GREEN; gitleaks-full-history + lychee — перед push.
- Регрессия Pest --parallel / Vitest — 0 регрессий vs baseline.