Files
portal/docs/superpowers/plans/2026-05-18-parallel-sessions-coordination.md
T
Дмитрий 8dbdd5aac0 docs(superpowers): parallel sessions coordination — implementation plan
8 atomic tasks per spec 2026-05-18-parallel-sessions-coordination-design.md:
1. Pravila §15 hard-rule (15.1 субагенты+git, 15.2 нормативка+pre-flight, 15.3 cross-refs) + v1.26→v1.27.
2. docs/sessions/ — README + CURRENT.md с retro-claim для 16 worktrees.
3. tools/subagent-prompt-prefix.test.mjs — TDD red-фаза (5 тестов).
4. tools/subagent-prompt-prefix.mjs — TDD green (PreToolUse Task auto-inject).
5. CLAUDE.md cross-ref через /claude-md-management:claude-md-improver (§5 п.10).
6. .claude/settings.json — регистрация хука matcher:'Task'.
7. .claude/skills/subagent-driven-development/ — wrapper-skill + git-safety-checklist.
8. Final regression + push (manual /push gate).

Все шаги с exact paths, exact commands, expected outputs.
TDD red→green разнесён по двум task'ам (3 → 4) с RED-коммитом между.

Branch: feat/parallel-sessions-coordination (от origin/main b40f2c8).
Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 09:51:29 +03:00

48 KiB
Raw Blame History

Parallel Sessions Coordination — Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Лечим два класса параллельных-сессий инцидентов (субагенты теряются между worktree / нормативка дрейфует) — добавляем Pravila §15 hard-rule, заявочный лог docs/sessions/CURRENT.md, PreToolUse-хук tools/subagent-prompt-prefix.mjs, references-wrapper к скилу subagent-driven-development.

Architecture: 4 артефакта, 0 новых плагинов / MCP. Pravila §15 — корневое правило. CURRENT.md — координация scope/version-claims. Хук — авто-инжект git-safety заголовка в каждый Task-prompt. Wrapper-скил — verify-чеклист контроллера.

Tech Stack: Markdown (нормативка + лог), Node 22 ESM (tools/*.mjs с node --test), git, lefthook (pre-commit), Bash (на Windows через Git Bash).

Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md

Branch: feat/parallel-sessions-coordination (создана от origin/main b40f2c8, верифицирована pre-flight — git log HEAD..origin/main пуст).


File Structure

Создаются:

  • docs/sessions/README.md — описание формата CURRENT.md, лайфциклов, конфликт-резолюции.
  • docs/sessions/CURRENT.md — заявочный лог + retro-claim для активных worktrees на момент имплементации.
  • tools/subagent-prompt-prefix.mjs — PreToolUse-хук на Task, инжектит cwd/branch/HEAD заголовок.
  • tools/subagent-prompt-prefix.test.mjsnode --test test-suite.
  • .claude/skills/subagent-driven-development/SKILL.md — wrapper-скил с проектным verify-протоколом (references-обёртка над marketplace-скилом).
  • .claude/skills/subagent-driven-development/references/git-safety-checklist.md — pre/post-subagent чеклист, формат GIT REPORT.

Модифицируются:

  • docs/Pravila_raboty_Claude_v1_1.md — добавить §15 (15.1 + 15.2 + 15.3), bump header v1.26 → v1.27, add §10 changelog entry.
  • CLAUDE.md — §1 priority chain footer-абзац (cross-ref на §15), §0 row Pravila version v1.26 → v1.27. Через /claude-md-management:claude-md-improver.
  • .claude/settings.json — добавить PreToolUse block matcher: "Task".
  • cspell-words.txt — добавить транслитерации появляющиеся в хуке/wrapper-скиле (по факту падений).

Task 1: Pravila §15 hard-rule

Files:

  • Modify: docs/Pravila_raboty_Claude_v1_1.md (add §15 after §14, bump header version, add §10 changelog entry)

  • Step 1.1: Verify §15 still free

Run:

grep -nE '^## 1[5-9]\.|^## 2[0-9]\.' docs/Pravila_raboty_Claude_v1_1.md

Expected: empty (no §15 collision). If non-empty — STOP, разбор.

  • Step 1.2: Find insertion point after §14

Run:

grep -nE '^## (14|15|11)\.' docs/Pravila_raboty_Claude_v1_1.md

Expected: line for ## 14. Ruflo Queen routing — hard rule (триггер queen/королева) (was line 820 at design time; verify актуально). Find end-of-§14 boundary (next ^## heading или EOF).

  • Step 1.3: Add §15 content

Insert after the closing line of §14 (before next ## heading or EOF). Exact text:

## 15. Параллельные сессии — hard rule (субагенты + git, нормативка + pre-flight sync)

Действует с 18.05.2026. **Hard rule**: §9 «Отступления» к §15 не применяется (как §12 и §14).

### 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`) — разрешены любой модели.

Прецедент-источник: Sprint 6 (17.05.2026) — Haiku-субагенты угнали ветку параллельной сессии, устранено через `git reflog` + `reset`. Корневая причина — отсутствие верификации HEAD/branch после Task-инвокации. Verify-протокол — `.claude/skills/subagent-driven-development/references/git-safety-checklist.md`.

### 15.2 Нормативные правки + pre-flight sync

Любая правка файлов из списка «нормативка» (см. ниже) выполняется **только** на актуальной базе `origin/main`. Pre-flight обязателен:

```bash
git fetch origin && git log HEAD..origin/main --oneline

Если есть untracked commits на origin/main, ребейз/merge до начала правки, не после.

Параллельная нормативная правка на устаревшей базе — нарушение §15.2. Признак нарушения: коммит правит файл, чья последняя версия на origin/main новее, чем версия в parent коммите правки.

Список «нормативка» — 8 позиций:

  1. docs/Pravila_raboty_Claude_v1_1.md
  2. CLAUDE.md
  3. docs/Tooling_v8_3.md
  4. docs/Plugin_stack_rules_v1.md
  5. memory/MEMORY.md (и все memory/*.md)
  6. docs/Открытые_вопросы_v8_3.md
  7. docs/adr/*.md (glob — collision на ADR-NNN номере = тот же класс, что version-bump нормативки)
  8. db/schema.sql (параллельные миграции из разных сессий = реальный риск; запись в db/CHANGELOG_schema.md сама не защищает от version-base дрейфа)

Расширение списка — отдельная правка §15.2, не «по ощущениям».

Дополнительно: при параллельных активных сессиях контроллер обязан добавить запись в docs/sessions/CURRENT.md до первой нормативной правки (claim) — формат и жизненный цикл записи описаны в docs/sessions/README.md. Конфликт-резолюция (file overlap / section overlap / version-claim collision) — там же.

15.3 Cross-refs в других файлах

  • CLAUDE.md §1 priority chain — §15 рядом с §12 и §14 как hard-rule (см. footer-абзац после цепочки).
  • PSR_v1 — не правится: §15 не про координацию плагинов, а про координацию сессий.
  • Tooling — не правится.

- [ ] **Step 1.4: Bump Pravila header v1.26 → v1.27**

Find first occurrence of `v1.26` in the file header (~lines 110) and replace one instance with `v1.27`. Update date if needed — `от 18.05.2026` stays.

Run check после правки:
```bash
head -10 docs/Pravila_raboty_Claude_v1_1.md

Expected: header содержит v1.27 от 18.05.2026.

  • Step 1.5: Add §10 changelog entry

Find ## 10. История версий (was line 561). Add at the top of the version list (newest first per existing pattern; verify pattern in §10 head — if oldest-first, append at bottom; the entry text is the same):

**v1.27 от 18.05.2026** — Параллельные сессии: координация. +§15 hard-rule (15.1 субагенты+git Sonnet/Opus only, 15.2 нормативка+pre-flight sync, 15.3 cross-refs). §15 третье hard-rule после §12 и §14; список «нормативка» — 8 позиций. Лечит два класса инцидентов параллельных-сессий: (A) субагенты теряются между worktree (Sprint 6 прецедент), (B) нормативка/MEMORY дрейфует (Tooling v2.11 collision 17.05.2026). Спек — `docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md`, план — `docs/superpowers/plans/2026-05-18-parallel-sessions-coordination.md`.
  • Step 1.6: Verify Pravila correctness

Run:

grep -cE '^## 15\.' docs/Pravila_raboty_Claude_v1_1.md
grep -cE '^### 15\.[123]' docs/Pravila_raboty_Claude_v1_1.md
grep -c 'v1.27' docs/Pravila_raboty_Claude_v1_1.md

Expected: 1, 3, ≥2 (header + §10 entry).

  • Step 1.7: Commit
git add docs/Pravila_raboty_Claude_v1_1.md
git commit -m "feat(pravila): §15 hard-rule — параллельные сессии (субагенты+git, нормативка+pre-flight sync)

Bump Pravila v1.26 → v1.27 + §10 changelog entry. §15 третье hard-rule
после §12 (Superpowers) и §14 (Ruflo Queen). §15 лечит два класса
инцидентов параллельных Claude-сессий — субагенты путают ветки/worktree
(Sprint 6) и нормативка/MEMORY дрейфует (Tooling v2.11 collision 17.05.2026).

Cross-refs to CLAUDE.md §1 — отдельная правка через
/claude-md-management:claude-md-improver (Task 5 плана).

Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md
Plan: docs/superpowers/plans/2026-05-18-parallel-sessions-coordination.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"

Pre-commit chain должен пройти: gitleaks 0, markdownlint 0, cspell 0 (если новые транслитерации появятся — добавить в cspell-words.txt отдельным fixup-commit'ом до основного коммита).


Task 2: docs/sessions/ — каталог + README + CURRENT.md retro-claim

Files:

  • Create: docs/sessions/README.md

  • Create: docs/sessions/CURRENT.md

  • Step 2.1: Resolve active worktrees

Run:

git worktree list --porcelain

Expected: список worktree (на 18.05.2026 — 16 штук). Сохранить вывод для retro-claim записей.

  • Step 2.2: Create docs/sessions/README.md

Полное содержимое (никаких placeholder'ов):

# docs/sessions/ — координация параллельных Claude-сессий

**Источник правила:** Pravila §15.2 (раздел про CURRENT.md в конце текста §15.2).

## Назначение

`docs/sessions/CURRENT.md` — заявочный лог активных параллельных Claude-сессий проекта. Решает класс инцидентов «нормативка/MEMORY дрейфует» (см. spec — `docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md`).

## Когда писать в CURRENT.md

Перед **первой** нормативной правкой в сессии (правки файлов из списка §15.2 — Pravila, CLAUDE.md, Tooling, PSR_v1, MEMORY.md, Открытые_вопросы, docs/adr/*, db/schema.sql). Запись добавляется отдельным атомарным коммитом `sessions: claim <topic>` — до plan-документа и до первой содержательной правки.

## Формат записи

```markdown
## session: YYYY-MM-DD-<topic-kebab>
- branch: <git branch --show-current>
- worktree: <git rev-parse --show-toplevel>
- started: <ISO 8601 with timezone>
- scope-files:
  - <relative path> [§/раздел/строка]
  - ...
- version-claims:
  - <file-or-topic>: <from> → <to>
  - ...
- status: in-progress | closed-<commit-sha>
- closes: <relative path к plan-документу>

scope-files — какие нормативные файлы и в каких секциях правит сессия. version-claims — какие новые версии (Tooling 2.X, Pravila 1.Y и т.п.) или номера (ADR-NNN) сессия резервирует.

Жизненный цикл

  • claim — добавить запись со status: in-progress + атомарный коммит sessions: claim <topic>.
  • check — pre-flight перед нормативной правкой: Read docs/sessions/CURRENT.md + проверить пересечение scope-files / version-claims с активными записями.
  • release — на закрытии (после push на main) изменить status: closed-<commit-sha> (запись остаётся в CURRENT.md — append-only-вариант).

Closed-записи переезжают в docs/sessions/archive/YYYY-MM.md через ≥30 дней после закрытия (ручная архивация раз в месяц, не cron).

Конфликт-резолюция

Тип пересечения Реакция
Файловое пересечение (одинаковый файл, разные секции) soft-warn — продолжать можно, но pre-flight fetch перед каждым коммитом обязателен (§15.2).
Section-пересечение (одна и та же секция §X.Y) hard-stop — координация с заказчиком до начала правки.
Version-claim collision (две сессии заявили один номер) hard-stop — кто claim'нул раньше (по started-timestamp), тот его и берёт. Вторая сессия сдвигается на +1.

Pre-flight snippet (для plan-документов и скила subagent-driven-development)

# Перед нормативной правкой:
git fetch origin && git log HEAD..origin/main --oneline
grep -A 20 'status: in-progress' docs/sessions/CURRENT.md

Что мы НЕ делаем (явный YAGNI)

  • Pre-commit hook на CURRENT.md — добавим только если будут зафиксированы инциденты игнорирования.
  • TTL / auto-expire записей — добавим, если файл реально засорится.
  • Machine-readable JSON-формат — markdown достаточен, парсится grep/sed.
  • Интеграция с GitHub Issues — отдельная тема, не блокер.

- [ ] **Step 2.3: Create docs/sessions/CURRENT.md с retro-claim**

Структура с заголовком + текущей сессией parallel-sessions-coordination + retro-claim записями для каждой активной worktree из Step 2.1.

Для текущей сессии (заполнить gотовыми значениями):

```markdown
# CURRENT.md — активные Claude-сессии

> Формат и жизненный цикл записей: [docs/sessions/README.md](README.md).
> Pravila §15.2 — описание правила в нормативке.

## session: 2026-05-18-parallel-sessions-coordination
- branch: feat/parallel-sessions-coordination
- worktree: c:/моя/проекты/портал crm/Документация
- started: 2026-05-18T09:30+03:00
- scope-files:
  - docs/Pravila_raboty_Claude_v1_1.md §15 (new)
  - CLAUDE.md §1 (cross-ref), §0 (Pravila version row)
  - tools/subagent-prompt-prefix.mjs (new)
  - .claude/settings.json (PreToolUse Task block)
  - .claude/skills/subagent-driven-development/ (new wrapper-skill)
  - docs/sessions/README.md, CURRENT.md (new — этот файл)
- version-claims:
  - Pravila: 1.26 → 1.27
- status: in-progress
- closes: docs/superpowers/plans/2026-05-18-parallel-sessions-coordination.md

---

## Retro-claim'ы активных worktrees (snapshot 2026-05-18)

Per Pravila §15.2 — backfill для существующих параллельных сессий. Эти записи retroactive, scope/version-claims заполнены best-effort из последних коммитов worktree-веток. Активные сессии при возобновлении работы обновляют свой блок.

Дальше — по одной записи на каждую worktree из Step 2.1 (кроме основной Документация, которая = текущая сессия). Для каждой записи:

  • branch: имя ветки из git worktree list
  • worktree: путь
  • started: 2026-05-18T00:00+03:00 (best-effort backfill, не точный)
  • scope-files: best-effort из последнего коммита ветки (git log -1 --name-only <branch>). Если scope непонятен — - <unknown — backfill>
  • version-claims: - <none verified — backfill> если непонятно
  • status: in-progress (backfilled) если HEAD ветки не на origin/main, иначе closed-<sha> (backfilled)

Например (шаблон для одной retro-записи; повторить для каждой worktree):

## session: 2026-05-XX-<topic-from-branch-name>
- branch: <worktree-branch-name>
- worktree: <worktree path>
- started: 2026-05-18T00:00+03:00 (backfill)
- scope-files:
  - <best-effort from git log -1 --name-only>
- version-claims:
  - <none verified — backfill>
- status: in-progress (backfilled) | closed-<sha> (backfilled)
- closes: <unknown — backfill>
  • Step 2.4: Verify created files

Run:

ls -la docs/sessions/
wc -l docs/sessions/README.md docs/sessions/CURRENT.md
grep -c '^## session:' docs/sessions/CURRENT.md

Expected: оба файла существуют; CURRENT.md содержит ≥1 запись (текущая) + retro-claim для каждой worktree из Step 2.1.

  • Step 2.5: Commit
git add docs/sessions/
git commit -m "feat(sessions): CURRENT.md + README — заявочный лог параллельных Claude-сессий

Создаём docs/sessions/ — координация per Pravila §15.2 (claim/check/release
жизненный цикл, конфликт-резолюция). CURRENT.md содержит текущую сессию
parallel-sessions-coordination + retro-claim записи для существующих
активных worktrees (16 штук на 2026-05-18).

Backfill scope/version-claims заполнен best-effort; активные сессии
обновят свой блок при возобновлении работы.

Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"

Task 3: Hook tests (TDD — failing first)

Files:

  • Create: tools/subagent-prompt-prefix.test.mjs

  • Step 3.1: Write the failing test file

Полное содержимое (node --test runner, паттерн один-в-один с tools/ruflo-recall-hook.test.mjs):

#!/usr/bin/env node
/**
 * Tests for tools/subagent-prompt-prefix.mjs — PreToolUse Task git-safety header inject.
 *
 * Per Pravila §15.1 — hook injects cwd/branch/HEAD/worktree-root into каждый Task-prompt.
 * FAIL-OPEN: any error → return {continue: true} без модификации.
 *
 * Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md §4
 */
import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';

const __dirname = dirname(fileURLToPath(import.meta.url));
const HOOK_PATH = join(__dirname, 'subagent-prompt-prefix.mjs');

function runHook(stdinJson) {
  return spawnSync('node', [HOOK_PATH], {
    input: JSON.stringify(stdinJson),
    encoding: 'utf8',
    timeout: 5000,
  });
}

test('hook injects SUBAGENT GIT-SAFETY HEADER into Task prompt', () => {
  const result = runHook({
    tool_name: 'Task',
    tool_input: { prompt: 'do something' },
  });
  assert.equal(result.status, 0, `stderr: ${result.stderr}`);
  const out = JSON.parse(result.stdout);
  assert.ok(out.hookSpecificOutput, 'has hookSpecificOutput');
  assert.equal(out.hookSpecificOutput.hookEventName, 'PreToolUse');
  assert.equal(out.hookSpecificOutput.permissionDecision, 'allow');
  const newPrompt = out.hookSpecificOutput.updatedInput.prompt;
  assert.match(newPrompt, /=== SUBAGENT GIT-SAFETY HEADER/);
  assert.match(newPrompt, /=== END SUBAGENT GIT-SAFETY HEADER ===/);
  assert.match(newPrompt, /do something/, 'preserves original prompt');
});

test('hook injects real cwd, branch, HEAD values', () => {
  const result = runHook({
    tool_name: 'Task',
    tool_input: { prompt: 'noop' },
  });
  assert.equal(result.status, 0);
  const out = JSON.parse(result.stdout);
  const newPrompt = out.hookSpecificOutput.updatedInput.prompt;
  // cwd — absolute path
  assert.match(newPrompt, /Working directory \(cwd\): [A-Za-z]:[\\/]|Working directory \(cwd\): \//);
  // branch — non-empty
  assert.match(newPrompt, /Branch \(git branch --show-current\): \S+/);
  // HEAD — 40-char SHA
  assert.match(newPrompt, /Parent commit \(git rev-parse HEAD\): [0-9a-f]{40}/);
});

test('hook passes through non-Task tools without modification', () => {
  const result = runHook({
    tool_name: 'Edit',
    tool_input: { file_path: '/foo', old_string: 'a', new_string: 'b' },
  });
  assert.equal(result.status, 0);
  const out = JSON.parse(result.stdout);
  // Non-Task → either {continue: true} OR no updatedInput
  if (out.hookSpecificOutput) {
    assert.equal(out.hookSpecificOutput.updatedInput, undefined);
  } else {
    assert.equal(out.continue, true);
  }
});

test('hook fail-open on malformed stdin', () => {
  const result = spawnSync('node', [HOOK_PATH], {
    input: 'not-json',
    encoding: 'utf8',
    timeout: 5000,
  });
  assert.equal(result.status, 0, `should not crash; stderr: ${result.stderr}`);
  // Either {continue: true} or empty output — both acceptable fail-open
});

test('hook fail-open when git not available', () => {
  const result = spawnSync('node', [HOOK_PATH], {
    input: JSON.stringify({ tool_name: 'Task', tool_input: { prompt: 'x' } }),
    encoding: 'utf8',
    timeout: 5000,
    env: { ...process.env, PATH: '' }, // strip PATH → git not found
  });
  assert.equal(result.status, 0, `should not crash when git missing; stderr: ${result.stderr}`);
});
  • Step 3.2: Verify tests FAIL (hook doesn't exist yet)

Run:

node --test tools/subagent-prompt-prefix.test.mjs

Expected: ALL tests FAIL — Cannot find module '.../subagent-prompt-prefix.mjs' or similar ENOENT. Это ожидаемое — TDD red-phase.

  • Step 3.3: Commit (TDD: failing test первым)
git add tools/subagent-prompt-prefix.test.mjs
git commit -m "test(hooks): subagent-prompt-prefix — failing tests (TDD red)

5 тестов для Task git-safety inject хука:
- inject SUBAGENT GIT-SAFETY HEADER в Task-prompt
- inject real cwd/branch/HEAD/worktree-root
- passes through non-Task tools
- fail-open on malformed stdin
- fail-open when git unavailable

Tests FAIL — hook implementation в следующем коммите (TDD green-phase).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"

Task 4: Hook implementation (TDD green)

Files:

  • Create: tools/subagent-prompt-prefix.mjs

  • Step 4.1: Write hook implementation

Полное содержимое (паттерн из tools/ruflo-recall-hook.mjsexecFile, FAIL-OPEN, ESM):

#!/usr/bin/env node
/**
 * PreToolUse hook — git-safety header inject for Task tool.
 *
 * For каждый Task-инвокейшн контроллера: дописывает в начало tool_input.prompt
 * заголовок с cwd / branch / parent SHA / worktree-root + правилами поведения
 * (rule 1–5). Это компенсирует класс инцидентов «субагент путает ветку/worktree»
 * (Sprint 6, Pravila §15.1).
 *
 * FAIL-OPEN: любая ошибка / тайм-аут / git-не-в-PATH → {continue: true} без
 * модификации; хук НИКОГДА не блокирует Task.
 *
 * Non-Task tools — pass-through без модификации.
 *
 * Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md §4
 * Rule: docs/Pravila_raboty_Claude_v1_1.md §15.1
 */
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';

const execFileP = promisify(execFile);
const GIT_TIMEOUT_MS = 1500;

/** Read all stdin into a string. */
async function readStdin() {
  let buf = '';
  for await (const chunk of process.stdin) buf += chunk;
  return buf;
}

/** Parse hook input JSON; return null on any parse error. */
function parseHookInput(raw) {
  try { return JSON.parse(raw); } catch { return null; }
}

/** Run a single fixed-args git command; return trimmed stdout, or null on any error. */
async function gitCmd(args) {
  try {
    const { stdout } = await execFileP('git', args, { timeout: GIT_TIMEOUT_MS, encoding: 'utf8' });
    return stdout.trim();
  } catch {
    return null;
  }
}

/** Build the safety header block. Returns null if any of the 4 git values can't be resolved. */
async function buildHeader() {
  const cwd = process.cwd();
  const [branch, head, top] = await Promise.all([
    gitCmd(['branch', '--show-current']),
    gitCmd(['rev-parse', 'HEAD']),
    gitCmd(['rev-parse', '--show-toplevel']),
  ]);
  if (!branch || !head || !top) return null;
  return [
    '=== SUBAGENT GIT-SAFETY HEADER (Pravila §15.1, auto-injected) ===',
    `Working directory (cwd): ${cwd}`,
    `Branch (git branch --show-current): ${branch}`,
    `Parent commit (git rev-parse HEAD): ${head}`,
    `Worktree root (git rev-parse --show-toplevel): ${top}`,
    '',
    'ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:',
    '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 ===',
    '',
  ].join('\n');
}

/** Emit fail-open response and exit 0. */
function failOpen() {
  process.stdout.write(JSON.stringify({ continue: true }));
  process.exit(0);
}

async function main() {
  const raw = await readStdin();
  const input = parseHookInput(raw);
  if (!input) return failOpen();

  // Non-Task — pass-through
  if (input.tool_name !== 'Task') return failOpen();

  const originalPrompt = input.tool_input?.prompt;
  if (typeof originalPrompt !== 'string') return failOpen();

  const header = await buildHeader();
  if (!header) {
    // git unavailable / not in worktree — fail-open per spec §4.5 edge-case 3
    process.stderr.write('[subagent-prompt-prefix] git resolution failed — passing through\n');
    return failOpen();
  }

  const newPrompt = header + originalPrompt;
  process.stdout.write(JSON.stringify({
    hookSpecificOutput: {
      hookEventName: 'PreToolUse',
      permissionDecision: 'allow',
      permissionDecisionReason: 'git-safety header injected (Pravila §15.1)',
      updatedInput: { prompt: newPrompt },
    },
  }));
}

main().catch(() => failOpen());
  • Step 4.2: Run tests — verify GREEN

Run:

node --test tools/subagent-prompt-prefix.test.mjs

Expected: ALL 5 tests PASS (# pass 5 / # fail 0).

Если какой-то тест падает — STOP, фикс реализации (НЕ теста), повторить.

  • Step 4.3: Smoke test inject вручную

Run:

echo '{"tool_name":"Task","tool_input":{"prompt":"hello"}}' | node tools/subagent-prompt-prefix.mjs | python -m json.tool

Expected: JSON с hookSpecificOutput.updatedInput.prompt, начинающимся === SUBAGENT GIT-SAFETY HEADER, с реальными cwd/branch/HEAD значениями.

  • Step 4.4: Commit
git add tools/subagent-prompt-prefix.mjs
git commit -m "feat(hooks): subagent-prompt-prefix — PreToolUse git-safety inject (TDD green)

Per Pravila §15.1 — инжектит cwd/branch/HEAD/worktree-root + правила
поведения в каждый Task-prompt. FAIL-OPEN на любой ошибке (git
не в PATH, malformed stdin, non-Task tools).

Все 5 тестов из subagent-prompt-prefix.test.mjs PASS.
Регистрация в .claude/settings.json — Task 6 плана.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"

Task 5: CLAUDE.md cross-ref через claude-md-management

Files:

  • Modify: CLAUDE.md (через плагин, не прямой Edit)

  • Step 5.1: Запустить /claude-md-management:claude-md-improver

Через слэш-команду в Claude Code. Передать конкретные правки:

Обнови CLAUDE.md под добавление Pravila §15:

  1. §0 cross-ref row Pravilav1.26v1.27. Сводный комментарий в скобках после версии: «(v1.27 от 18.05.2026 — §15 hard-rule: параллельные сессии (15.1 субагенты+git, 15.2 нормативка+pre-flight sync, 15.3 cross-refs); третье hard-rule после §12 и §14)».

  2. §1 priority chain — добавить footer-абзац после блок-схемы цепочки (после слов «...alongside CLAUDE.md как корневая карта Claude Code.»). Текст footer-абзаца:

Hard-rules вне §9 «Отступления» (Pravila): §12 (Superpowers — инвокация skill ПЕРВОЙ), §14 (Ruflo Queen routing — триггер queen/королева), §15 (параллельные сессии — 15.1 субагенты+git Sonnet/Opus only, 15.2 нормативка+pre-flight sync с 8-позиционным списком, 15.3 cross-refs). Эти три параграфа Pravila — explicit override-floor под §9; transitive hard-rule через §13 — координация Plugin_stack_rules_v1.

  1. §9 «История версий» — добавить запись v2.14 (или next-free version) с описанием изменений согласно §6 шаблону предыдущих записей.

Плагин сам бамп'нет шапку CLAUDE.md (v2.13 → v2.14) и сделает commit per §5 п.10.

  • Step 5.2: Verify after plugin run

Run:

git log -1 --stat
grep -c 'v1.27' CLAUDE.md
grep -c '§15' CLAUDE.md

Expected: latest коммит трогает только CLAUDE.md; v1.27 встречается ≥1 раз; §15 встречается ≥2 раз (§0 + §1 footer).


Task 6: Register hook в .claude/settings.json

Files:

  • Modify: .claude/settings.json — добавить новый PreToolUse block с matcher: "Task"

  • Step 6.1: Найти существующий PreToolUse секцию

Run:

grep -n '"PreToolUse"' .claude/settings.json

Expected: одна строка (например "PreToolUse": [).

  • Step 6.2: Добавить новый matcher block

Внутри массива PreToolUse добавить новый объект-block (НЕ внутри существующего matcher: "Edit|Write" block, отдельный объект массива):

      {
        "matcher": "Task",
        "hooks": [
          {
            "type": "command",
            "command": "node \"C:/моя/проекты/портал crm/Документация/tools/subagent-prompt-prefix.mjs\""
          }
        ]
      }

Точный путь — абсолютный (паттерн из существующих ruflo-хуков в этом же файле). Запятая после предыдущего объекта массива обязательна — Edit|Write объект должен оканчиваться },.

  • Step 6.3: Validate JSON

Run:

node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8')); console.log('OK')"

Expected: OK. Если ошибка — STOP, ловить trailing comma / unbalanced brace.

  • Step 6.4: Smoke test end-to-end

Перезапустить Claude Code (хук перечитывается на старте сессии). В новой сессии запустить тривиальный Task — субагент должен в ответе содержать === SUBAGENT GIT-SAFETY HEADER === в начале промпта (можно проверить, попросив субагента выписать первые 10 строк своего промпта).

Если перезапуск Claude Code невозможен в текущем рабочем потоке — отметить шаг как «verified at next session start» в коммит-сообщении.

  • Step 6.5: Commit
git add .claude/settings.json
git commit -m "chore(hooks): register subagent-prompt-prefix PreToolUse Task hook

Регистрирует tools/subagent-prompt-prefix.mjs как PreToolUse-хук
matcher:'Task'. JSON валиден (node -e JSON.parse). End-to-end smoke
verified at next session start (хук перечитывается на старте сессии).

Per Pravila §15.1 (третье hard-rule).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"

Task 7: Wrapper-скил subagent-driven-development

Files:

  • Create: .claude/skills/subagent-driven-development/SKILL.md

  • Create: .claude/skills/subagent-driven-development/references/git-safety-checklist.md

  • Step 7.1: Create SKILL.md (wrapper)

Полное содержимое:

---
name: subagent-driven-development
description: Project-local wrapper для superpowers:subagent-driven-development — добавляет обязательный git-safety verify-протокол per Pravila §15.1. Использовать вместо marketplace-варианта при работе с git-коммит-задачами в субагентах.
---

# Subagent-Driven Development (project wrapper)

Этот скил — проектная обёртка над marketplace-скилом `superpowers:subagent-driven-development`. Дополняет его обязательным git-safety verify-протоколом per Pravila §15.1.

## Когда использовать

Когда нужно делегировать задачу субагенту через Task tool — особенно git-коммит-задачи (Sprint 6 прецедент: Haiku-субагенты угнали ветку параллельной сессии).

## Что делать

1. **Откройте marketplace-скил** `superpowers:subagent-driven-development` для общего workflow (fresh subagent per task + two-stage review).
2. **Перед каждой Task-инвокацией** прочитайте и выполните pre-spawn-чеклист — [references/git-safety-checklist.md](references/git-safety-checklist.md) §A.
3. **После каждой Task-инвокации** прочитайте и выполните post-subagent-чеклист — там же §B.
4. **Hard-rule §15.1** — git-коммит-задача = модель Sonnet/Opus, никогда Haiku. Read-only git-операции (`log`, `status`, `diff`, `rev-parse`, `branch --show-current`, `worktree list`) разрешены любой модели.

Хук `tools/subagent-prompt-prefix.mjs` (зарегистрирован в `.claude/settings.json`) автоматически инжектит git-safety заголовок в каждый Task-prompt — это **первая** линия защиты. Чеклист из этого скила — **вторая** линия (защита со стороны контроллера).

## Cross-refs

- Pravila §15.1 — hard-rule субагенты + git.
- Spec: `docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md` §5.
- Memory: `memory/feedback_subagent_git_reliability.md`.
  • Step 7.2: Create references/git-safety-checklist.md

Полное содержимое:

# Git-safety Checklist для контроллера субагентов

Per Pravila §15.1 — выполнять каждый раз при делегировании задачи через Task tool.

## §A. Pre-spawn чеклист (до Task-инвокации)

1. **Резолвите 4 значения** (запишите у себя для post-check):
   ```bash
   git branch --show-current        # → ожидаемая ветка
   git rev-parse HEAD               # → pre-spawn parent SHA
   git rev-parse --show-toplevel    # → worktree root
   pwd                              # → cwd
  1. Выберите модель субагенту:

    • Задача требует git commit/push/stage/checkout/switch/merge/rebase? → Sonnet или Opus, никогда Haiku (§15.1).
    • Только read-только git log/status/diff/rev-parse ИЛИ только Edit/Read/Grep? → любая модель.
  2. Если задача правит нормативку из списка §15.2 (Pravila / CLAUDE.md / Tooling / PSR_v1 / MEMORY.md / Открытые_вопросы / docs/adr/* / db/schema.sql):

    git fetch origin && git log HEAD..origin/main --oneline
    

    Не пусто → ребейз/merge до инвокации, не после. Pre-flight также проверить docs/sessions/CURRENT.md на конфликт scope-files / version-claims.

§B. Post-subagent чеклист (сразу после возврата субагента)

  1. git rev-parse HEAD — сравнить с pre-spawn parent SHA.
    • Равно → субагент не коммитил (OK для Edit-задач без commit).
    • Отличается ровно одним коммитом, чей parent = pre-spawn HEAD → OK для commit-задач.
    • Иначе → STOP, разбор инцидента.
  2. git branch --show-current — сравнить с pre-spawn branch.
    • Не равно → STOP, разбор инцидента (Sprint 6 паттерн).
  3. git log -1 --format='%s%n%P' — проверить subject + parent последнего коммита.
    • Subject соответствует задаче?
    • Parent = pre-spawn HEAD?
  4. Если несколько коммитов — ручная проверка subject'ов каждого.

§C. Red-flag-список — любой = hard-stop разбор

  • branch ≠ ожидаемая;
  • parent коммита ≠ pre-spawn HEAD (висячий коммит / попадание на чужую ветку);
  • HEAD двинулся, но субагент в отчёте об этом не упомянул;
  • в diff'е есть файлы вне scope задачи.

§D. Обязательный формат отчёта субагента

Субагент в конце ответа выписывает блок:

=== 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 ===

Отсутствие блока = контроллер считает результат недостоверным и запускает §B-чеклист сам через Bash.

§E. Соотношение с code-review

Двухстадийное review (Pravila §4.5 / PSR_v1 R10) сохраняется. Git-safety-чеклист не заменяет code-review — он стоит до него (нет смысла ревьюить diff, если он не в той ветке).


- [ ] **Step 7.3: Verify скил**

Run:
```bash
ls -la .claude/skills/subagent-driven-development/
ls -la .claude/skills/subagent-driven-development/references/

Expected: SKILL.md + references/git-safety-checklist.md существуют.

  • Step 7.4: Commit
git add .claude/skills/subagent-driven-development/
git commit -m "feat(skills): subagent-driven-development project wrapper + git-safety-checklist

Project-local обёртка над marketplace-скилом superpowers:subagent-driven-development.
Добавляет обязательный pre/post-subagent git-safety verify-протокол
per Pravila §15.1 (Sprint 6 прецедент-источник: Haiku-субагенты
угнали ветку параллельной сессии).

Состав:
- SKILL.md — точка входа, ссылка на marketplace + §A/§B/§C из checklist.
- references/git-safety-checklist.md — pre-spawn / post-subagent / red-flags / GIT REPORT format / code-review boundary.

Хук tools/subagent-prompt-prefix.mjs — первая линия защиты (auto-inject),
этот checklist — вторая линия (контроллер verify).

Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md §5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"

Task 8: Final regression + push

Files: none (verification + push only)

  • Step 8.1: Update CURRENT.md status — release

Прочитать docs/sessions/CURRENT.md, изменить запись текущей сессии:

  • status: in-progressstatus: closed-<последний commit SHA из git log -1>

Это append-only правка в смысле жизненного цикла — запись остаётся, только меняется статус.

  • Step 8.2: Commit status change
git add docs/sessions/CURRENT.md
git commit -m "chore(sessions): release parallel-sessions-coordination session

status: in-progress → closed-<sha>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
  • Step 8.3: Verify everything is staged correctly

Run:

git status
git log --oneline origin/main..HEAD

Expected: working tree clean (кроме dirty файлов вне нашего scope: .gitignore, app/dev-indices.json, _demo_* — не трогаем); git log показывает 8 atomic commits (по одному на task'у, + spec-commit 235b1d4 из brainstorming).

  • Step 8.4: Pre-push full regression

Run параллельно (в одном tool-сообщении):

./bin/gitleaks.exe detect --source . --redact -v

Expected: 0 leaks (full history scan).

./bin/lychee.exe --no-progress 'docs/**/*.md' '*.md'

Expected: 0 broken links.

(Pest --parallel / Vitest — пропускаем: scope не трогает PHP/JS-код приложения, только tools/+docs/+.claude/. Если settings.json правка влияет на запуск сессии — это не testable в этом репо.)

  • Step 8.5: Push to origin (только после явного «делай push» от заказчика)
git push origin feat/parallel-sessions-coordination:feat/parallel-sessions-coordination

Затем — либо PR через GitHub MCP, либо прямой FF-merge на main по решению заказчика. PR-вариант предпочтителен из-за объёма (8 atomic commits + новая нормативка §15).

  • Step 8.6: Update memory MEMORY.md

Через /claude-md-management:revise-claude-md (capture session-learnings) ИЛИ ручной Edit memory/MEMORY.md + создание memory/project_parallel_sessions.md. Важные факты:

  • Pravila §15 — третье hard-rule (после §12, §14).
  • docs/sessions/CURRENT.md — claim/check/release координация.
  • Хук tools/subagent-prompt-prefix.mjs — PreToolUse Task auto-inject.
  • Wrapper-скил .claude/skills/subagent-driven-development/.
  • Прецедент Sprint 6 → исторический корень §15.1.

Self-Review

1. Spec coverage — каждая секция spec'а покрыта:

  • spec §0 Контекст — упомянут в Goal плана.
  • spec §1 Архитектура — 4 артефакта → tasks 1, 2, 3+4+6, 7.
  • spec §2 Pravila §15 — Task 1 целиком (15.1/15.2/15.3 + список 8).
  • spec §3 CURRENT.md — Task 2 (формат + lifecycle + retro-claim).
  • spec §4 Хук — Tasks 3 (TDD red) + 4 (green) + 6 (register).
  • spec §5 Verify-протокол — Task 7 (wrapper-skill + references).
  • spec §6 Тесты+migration — Tasks 3+4 (хук-тесты), Task 2 (retro-claim migration), Task 8 (final regression).
  • spec §7 Ограничения — учтены в pre-flight (§15 свободен verified) и в Task 7 (references-wrapper вместо vendor-патча — confirmed .claude/skills/subagent-driven-development/ отсутствует).
  • spec §8 Acceptance — все 7 пунктов адресованы tasks.

2. Placeholder scan — все шаги содержат конкретный код / точную команду / ожидаемый вывод. Никаких «TBD / implement later / add validation».

3. Type consistency — формат хука (JSON output структура) consistent между Task 3 (тесты) и Task 4 (имплементация): hookSpecificOutput.updatedInput.prompt, hookEventName: 'PreToolUse', permissionDecision: 'allow'. GIT REPORT формат (cwd / branch / HEAD / HEAD^ / status) consistent между Task 4 (header instructs subagent) и Task 7 (checklist §D).

4. Гарантии TDD — Task 3 явно требует RED-фазу (тесты падают), Task 4 — GREEN. Атомарные коммиты RED-then-GREEN сохраняют TDD-историю.


Risks / Out-of-scope

  • Smoke-test перезапуска сессии (Task 6 Step 6.4) — может не сработать в текущем рабочем потоке (если плановщик хочет провести все таски в одной сессии). Mitigation: «verified at next session start» отметка в commit'е.
  • Retro-claim accuracy (Task 2 Step 2.3) — scope-files для existing worktrees заполнены best-effort из git log -1 --name-only. Точность ограничена; активные сессии при возобновлении обновят свой блок. Spec §6.2 явно фиксирует «§15 действует с момента введения, не ретроактивно».
  • CLAUDE.md правки через плагин (Task 5) — /claude-md-management:claude-md-improver может предложить другие версии bump'а или другую формулировку footer-абзаца — это нормально, плагин — owner CLAUDE.md (§5 п.10).
  • Out-of-scope (явный YAGNI из spec §6.3): реестр зарезервированных версий, pre-commit hook на CURRENT.md, JSON-формат CURRENT.md, запрет параллельных сессий, изменения PSR_v1/Tooling, subagent-без-git (вариант C).