# Parallel Streams

> Разбить утверждённый план на параллельные потоки работы, которые разные вкладки могут вести одновременно без конфликтов слияния и двойной работы. Выдаёт карту зависимостей (таблица плюс схема) и по одному самодостаточному заданию на поток, готовому к вставке в свежую вкладку. Вызывается на «раздели план на потоки», «раздели задачи на параллельные потоки», «что можно вести параллельно», «покажи карту потоков», «покажи схему разбивки» — и на английские «split the plan into streams», «parallelize this plan», «what can I run in parallel», «hand this plan to several agents», «show me the stream map».

- Skill: `timetodel/parallel-streams-2` (Agent Skill, multi-file: 20 files)
- Install (CLI): `npx skillmds@latest add timetodel/parallel-streams-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/timetodel/parallel-streams-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: timetodel (https://skillmd.com/u/timetodel)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/timetodel/parallel-streams-2

---


<!-- parallel-streams 1.16.0, русская версия — https://github.com/timetodel/parallel-streams
     Поставляется как скилл: этот каталог и есть всё целиком. Обновление — копированием
     более свежей копии поверх этой; что изменилось, перечислено в CHANGELOG.md репозитория.
     Правила проекта берутся из настройки `.parallel-streams.md` в корне репозитория.
     Канал согласования вкладок — механика за командами, которые печатает скилл, — лежит
     в подпапке `coordination/`. Он необязателен: настройка без раздела `## Coordination`
     оставляет скилл работать ровно так, как он работал до появления канала.
     См. `coordination/README.md`.
     ‼️ Заголовки разделов настройки скилл ищет ПО-АНГЛИЙСКИ (`## Isolation`, `## Tests`
     и так далее) — их не переводить ни здесь, ни в самой настройке. Переводится
     содержимое, а не адреса. -->

# Разбить план на параллельные потоки

Вход: путь к утверждённому плану (спецификация, план реализации, список задач, раздел дорожной карты).
Выход: карта зависимостей и по одному заданию на поток, которое свежая вкладка выполнит без всякого другого контекста.

**Только карта** — попросили «покажи карту», «как это разделится», «что можно вести параллельно»:
делать шаги 1–4 и 6. Заданий не писать.
**Полная разбивка** — попросили разделить план: делать шаги 0–6.
**Закрытие волны** — попросили «закрой волну», «что от неё осталось», «сведи хвосты», «волна
закончена?»: делать шаги 0, 1 и 7. Карту заново не строить, заданий не писать.

## Шаг 0. Загрузить настройку проекта

Искать настройку `.parallel-streams.md` в корне репозитория. В ней сказано, как ИМЕННО ЭТОТ проект
изолирует вкладки, какого размера бывает изменение, какой командой гоняются проверки и какой разбор
идёт перед слиянием. Настройка есть — каждое задание обязано ей следовать.

Настройки нет — работать по умолчанию и сказать об этом ОДИН раз, в итоговом абзаце: изоляция
отдельным рабочим деревом, один читаемый запрос на слияние на поток, проверки штатной командой
проекта, разбор изменений перед слиянием. Подробности и полный список полей —
`references/configuration.md`.

**Постоянный файл правил.** Раздел настройки `## Persistent rules` называет файл, который вкладки
этого проекта загружают в начале КАЖДОЙ сессии, — `CLAUDE.md`, `AGENTS.md` или что там читает
эта среда. Правила, которые обязаны действовать независимо от того, выдал ли задание этот скилл, —
как разговаривают с владельцем, во что превращается отчёт субагента, когда вкладка вообще пишет
текстом, — живут в том файле, а не только в настройке: вкладка, работающая по задаче, набранной
руками прямо в чате, не открывает ни настройку, ни этот скилл.

Проверить до того, как писать задания. Файл назван и существует — делать нечего. Назван и
отсутствует либо не назван вовсе — сказать об этом один раз в итоговом абзаце, одной строкой, и
предложить готовый блок из `references/persistent-rules.md`. В этот файл не писать без спроса —
и молчать о нём тоже нельзя: молчание здесь неотличимо от «в проекте всё закрыто».

**Канал согласования.** Если в настройке есть раздел `## Coordination`, у проекта есть способ,
которым работающие вкладки достают друг друга: контекст соседа не виден никому, а план, поправленный
после старта вкладки, до неё не доходит уже никогда. Команды оттуда копировать ДОСЛОВНО в блоки 4 и 9
каждого задания, заполненными под этот поток: объявить поток на старте, отправить находку живому
соседу, закрыть пришедшее, спросить, чей это кусок, прежде чем предлагать работу за пределами своих
задач, сдать поток последней командой — когда фиксировать больше нечего. Раздела нет — пропустить
целиком и про согласование не говорить ни слова: скилл несёт порядок, а не механику.

Объявление — единственное здесь, что не уговор, а отказ: при установленном канале фиксация работы
из потока, который не объявился, отклоняется, и отказ возвращает команду, которой это лечится.
Поэтому объявление в блоке 4 — не вежливость: поток, который его пропустил, остановится на первой
же фиксации.

Адрес потока в этом канале — `<волна>/<номер потока>`: волна из имени файла плана, номер из первой
колонки таблицы. Имена веток и папок внутри волны расходятся с объявленными, номер в плане — нет,
поэтому только он и продолжает работать.

Проект без волн и без файла плана тоже поддержан: канал выдаёт волну сам — по работе, идущей рядом,
а если рядом нет ничего, то по сегодняшней дате, — и присваивает следующий свободный номер потока.
Механика канала едет вместе со скиллом, в `coordination/`; как её ставят в проект —
`coordination/README.md`.

## Шаг 1. Прочитать план целиком

Открыть файл и прочитать его весь — каждый этап, каждый шаг. Не по памяти и не по конспекту.
Непрочитанная зависимость — это конфликт слияния, в который упрёшься позже.

**Если план лежит в папке, названной разделом `## Plans`, он тоже носитель правил.** Задание
вставляют один раз; план — документ, который вкладка открывает сама, и задача, заново нарезанная
из плана руками, несёт ровно то, что несёт план. Искать в нём раздел с правилами, действующими для
всех потоков. Раздела нет — сказать об этом в итоге и предложить его добавить, собрав из настройки.
Наблюдение 31.08.2026: план волны, написанный руками, такого раздела не имел; скилл и настройка были
свежие, и обе говорили, что отчёт субагента владельцу не пересылается, — а каждая вкладка той волны
печатала владельцу отчёты своих субагентов: пути, таблицы файлов, строчки настроек, и всё это
человеку, который код не читает. Никто ничего не нарушал: правила просто не было там, куда эти
вкладки смотрят.

**Плану нужен ещё и раздел `## Wave Loose Ends` — это адрес, на который канал уже отправляет.**
Несколько отказов канала называют его прямо: находка сданному потоку, находка потоку, у которого не
стало рабочей папки, ящик, оставшийся от сданного потока. Раздела нет — каждый такой совет ведёт в
никуда, и вкладке, идущей по нему, некуда деть то, что у неё в руках. Нет — сказать об этом один раз
в итоге и предложить добавить; хватит пустого раздела с одной строкой о том, что в него кладут.

## Шаг 2. Найти зависимости между потоками

Зависимость между потоками — не то же самое, что порядок шагов внутри плана. Считать зависимостью:

- **Общая поверхность правки** — два потока меняют один файл или один модуль. Один ждёт.
- **Произведённый предмет** — один поток пользуется тем, что заводит другой: таблица, миграция,
  адрес обращения, ключ настройки, сгенерированный клиент, новый пакет.
- **Единственный владелец версии** — оба поднимают одно и то же версионируемое: версию схемы,
  версию протокола, файл замка зависимостей, публичный интерфейс. Параллельно — никогда: слить
  в один поток или выстроить в очередь явно.

**Не** считать зависимостью: два потока трогают один пакет, но разные, непересекающиеся файлы. Это
риск конфликта, а не зависимость — упомянуть в задании, но не выстраивать из-за этого работу в очередь.

Все три вопроса выше спрашивают, что поток **меняет**. Задать ещё один: чем каждый поток
**пользуется, пока проверяет себя**? Одна местная база, которую мигрирует набор проверок, контейнер
под фиксированным именем, замок сборки, общий кэш — два потока, запустившие проверки одновременно,
делят всё это, и ломается оно совсем не как зависимость: красные проверки в потоке, который ничего
похожего не менял, либо зелёные, купленные миграцией соседа. Это не «ждёт»: ответ — развести, а это
строка в задании и строка под картой; ни колонкой, ни очередью это не записывается. Что бывает
общим и куда какая строка идёт — `references/dependency-analysis.md`.

Полный список, включая ловушки, которые выглядят независимыми и таковыми не являются:
`references/dependency-analysis.md`.

## Шаг 3. Сгруппировать в потоки

- Максимум параллельности, который не нарушает шаг 2.
- Один поток = одна ветка = одно изолированное рабочее место = одна вкладка.
- Размер: один читаемый запрос на слияние или короткая цепочка небольших внутри одной ветки.
- Никогда не резать физически неделимое: миграция и её единственный потребитель едут вместе.

## Шаг 4. Собрать карту: сперва таблица, потом схема

Обе, всегда, в этом порядке.

### 4.1 Таблица — ровно шесть колонок

| Поток | Название | Ждёт | Держит | Усиленный режим | Разбор |
|---|---|---|---|---|---|
| 1 | Ввести признак возможности | ничего | 4, 5, 6 | шаги 3–4 — сплошная инвентаризация мест вызова | глубокий |
| 2 | Честный отказ, когда служба лежит | ничего | 5 | не нужен | обычный |
| 9 | Сторожа и приёмка | 5, 6, 7, 8 | — | весь поток — полная инвентаризация | глубокий + безопасность |

- **Ждёт / Держит** симметричны: B ждёт A ⇔ A держит B. Сверять сравнением обеих колонок, а не на глаз.
- **Усиленный режим** — *отрезок*, который занимает более глубокий и дорогой режим: где начинается,
  где кончается и ради чего — «шаги 3–4», «весь поток», — либо «не нужен». Пустой ячейки не бывает.
  Именно отрезок, а не точка: режим включают руками и держат руками, поэтому начало без конца
  оставляет дорогой режим работать на всей рутине, которая идёт следом.
- **Разбор** — проверка из настройки, глубиной по тому, что поток трогает, и никогда — по ощущению
  «работа была простая»:

  | Что трогает поток | Глубина |
  |---|---|
  | Деньги, права доступа, ключи, персональные данные, всё, до чего дотягиваются снаружи | самая глубокая проверка из настройки плюс разбор безопасности |
  | Расползающаяся правка — сквозная замена, миграция, переименование — или новый договор, которым будут пользоваться соседние потоки | глубокий |
  | Одна область по образцу, который уже есть в репозитории | облегчённая проверка из настройки |
  | Изменение, которое не может изменить поведение: текст, переводы строк, комментарии, номер версии, файл, перемещённый без правок | «не нужен», с причиной в той же ячейке |

  «Не нужен» — утверждение об изменении, а не о плане: задание с таким ответом обязано нести и строку,
  возвращающую проверку, если работа всё-таки затронет код. Настройка может запрещать «не нужен»
  вовсе — тогда проверку несёт каждый поток. Обе колонки принимают «не нужен» как ответ; ни одна
  не принимает пустоту. Правила глубины и запасные формулировки — `references/brief-template.md`.
- Не повторять транзитивные зависимости: если 9 ждёт 5–8, а те уже ждут 1–4, перечислить только
  5, 6, 7, 8 и одной строкой под таблицей сказать, почему этого достаточно.
- Всё, что потоки делят **на проверке**, идёт одной строкой под таблицей — что развести и чем, — а
  не колонкой и не в «Ждёт». Разводить нечего — не писать ничего. Колонка тут почти в каждой строке
  ответила бы «нет», а запись в «Ждёт» выстроила бы в очередь часы работы ради того, что чинится
  строкой.

### 4.2 Схема — одна связная картинка, порождённая, а не набранная руками

Скормить сборщику только что написанную таблицу и вставить его вывод дословно:

```
python scripts/render_map.py map.md --format table --check
```

Тогда схема берётся из той же таблицы, которую видит читатель. Короткая запись тоже работает
(`4: 1, 2` значит «поток 4 ждёт потоки 1 и 2»), но сверять её с таблицей потом некому: таблица,
говорящая одно, и схема, нарисованная с другого, пройдут обе — каждую проверяют отдельно.

`--check` здесь делает две работы. Проверяет рисунок — схема, которая выглядит хорошо и врёт на
один символ, падает громко. И разбирает саму таблицу: шесть колонок в закреплённом порядке, «Ждёт»
и «Держит» согласны друг с другом в обе стороны, нет пустых клеток там, где место ответу, нет
транзитивных связей, нет ссылок на потоки, которых в таблице нет. Ничего из этого списку
самопроверки больше не задают.

Колонка — это момент старта: всё, что стоит в самой левой, можно открывать прямо сейчас. Правила
чтения, формат входа и что делать, когда Python недоступен, — `references/diagram-rules.md`.

Нарисованная руками схема уезжает на символ, и замечает это всегда только читатель. Руками не рисовать.

### 4.3 Состояние, когда план частично сделан

Если часть работы уже влита, карта без такой пометки вводит в заблуждение. Посмотреть историю слияний
(`git log --oneline origin/main`) и добавить одну строку под схемой: какие потоки влиты, какие идут,
какие не начинались. Проверка приблизительная — так и сказать; догадку за факт не выдавать.

Какие потоки идут ПРЯМО СЕЙЧАС — та половина, на которой догадка и ошибается: рабочее дерево,
брошенное закрытой вкладкой, выглядит в точности как живое. Если настройка объявляет канал
согласования — спросить у него: он отвечает по собственным заявкам вкладок, а не по именам папок.

## Шаг 5. Написать по одному заданию на поток

Каждое задание самодостаточно: владелец вставляет его в свежую вкладку, у которой нет ничего из
этого разговора. Каждое задание печатается прямо в ответе, под заголовком, говорящим, когда его
открывать, — точная форма ниже, в разделе «Формат вывода». Порядок блоков закреплён, ничего не
пропускается и не переставляется:

1. **Заголовок** — действие, а не предмет («Завести очередь повторов», а не «Очередь повторов»).
2. **Контекст** — 3–5 строк: что и зачем, со ссылкой на раздел плана.
3. **Зависимости** — что должно быть влито раньше, либо «ничего, начинай сейчас».
4. **Как работать** — сперва завести изолированное рабочее место, затем объявить поток на канале
   согласования, если он есть в настройке (объявление и есть то, что делает вкладку достижимой,
   и задним числом оно бесполезно — ставить его до любой правки); чтение и разведку отдавать
   субагентам, а не вести в своём контексте, и так же отдавать выполнение каждой задачи, с отдельным
   субагентом, который сверяет готовую задачу с заданием — сделано ли то, о чём просили, а не охота
   за ошибками в логике, это работа проверки перед слиянием, — один раз на задачу, а не на каждый
   круг правок, либо один раз на весь поток, когда поток это две-три мелкие однородные задачи; на
   каждую задачу берётся свежий субагент, а не разбуженный прежний; модели — по уровням из настройки.
   Ветку, коммиты, запрос на слияние и само слияние вкладка ведёт сама и спрашивает только про
   решения из блока 8. Когда канал есть, этот же блок несёт: как находка доходит до живого соседа,
   что пришедшие записи надо закрывать и — прежде чем предлагать любую работу за пределами своих
   задач — как спросить, чей это кусок. Тот, кто утверждает работу, не может знать, что задачу
   планировали другому потоку; он скажет «да». Этот же блок решает, что доходит до владельца:
   отчёт субагента — сырьё для вкладки, а не текст на пересылку; от субагентов требуют максимума
   точности, и ничего из этого не попадает в чат — ни целиком, ни выжимкой, ни пересказом
   с сохранением имён из кода. Одного намерения вкладки для этого мало: последний ответ субагента
   владелец видит сам, отдельным сообщением, раньше вкладки, — поэтому задание субагенту называет
   два адреса, подробный отчёт в файл и несколько строк простыми словами в ответ.
   Владелец слышит собственные слова вкладки, и всего три раза: строка
   на задачу о том, за что взялись, самодостаточный вопрос на каждой развилке и итог в конце.
   Просьба про усиленный режим — включить перед отрезком и выключить в его конце — это вопрос на
   развилке, а не лишний статус: обе останавливают работу, пока не ответят.
5. **Что делать** — конкретные шаги из плана, относящиеся к этому потоку.
6. **Усиленный режим** — обязательно. Либо «не нужен» и почему, либо две просьбы: **включить** —
   с поводом и отрезком, который режим покрывает, и в конце этого отрезка **остановиться и попросить
   выключить**, потому что сам по себе режим не выключается.
7. **Разбор** — обязательная строка: какая проверка идёт перед слиянием, либо «не нужен» с причиной
   и условием, при котором проверка возвращается.
8. **Решить со мной до реализации** — настоящие развилки *из этого плана* для этого потока, плюс
   любые формулировки, которые увидит человек, простым языком, решение прежде кода; и постоянное
   приглашение возразить против самого задания до начала работы — бесплатно даже тогда, когда
   возражение отменяет распоряжение, — вместе с требованием в каждом отчёте отделять проверенное
   от предполагаемого.
9. **Готово, когда** — проверки пройдены, разбор сделан, запрос на слияние влит; а там, где в
   настройке есть канал согласования, — поток сдан: сдача и есть то, что заставляет спросить
   «всё ли пришедшее учтено», а больше об этом не спрашивает ничто. Сдача идёт САМОЙ ПОСЛЕДНЕЙ,
   когда фиксировать в этой папке больше нечего: после неё сторож не пропускает ни коммит, ни
   отправку, ни заведение запроса на слияние.

Шаблон и правила блоков 4 и 6–8: `references/brief-template.md`.

## Шаг 6. Самопроверка до того, как что-то показывать

Карта:

Механическую половину закрывает сборщик: прогнанный по самой таблице, он отвечает за шесть колонок
и их порядок, за согласие двух колонок зависимостей в обе стороны, за пустые клетки, транзитивные
связи, ссылки на несуществующие потоки и за сам рисунок. Остаётся то, что требует суждения:

- [ ] `render_map.py --format table --check` прогнан по этой самой таблице и прошёл?
- [ ] глубина разбора у каждого выведена из того, что поток трогает, а не из того, насколько сложной казалась работа?
- [ ] «не нужен» в клетке несёт причину, а не одно слово?
- [ ] всё, что потоки делят *на проверке*, названо под таблицей вместе с тем, чем это развести, —
      либо разводить действительно нечего?
- [ ] если план частично сделан, состояние отмечено под схемой?

Каждое задание:

Каждый пункт — один вопрос. Что именно должно быть в ответе, сказано в шаге 5 и в шаблоне;
повторить это здесь значило бы дать одному требованию две формулировки, а две формулировки
расходятся.

- [ ] строка про делегирование есть целиком — и разведка, и выполнение, уровни моделей, один
      проверяющий на готовую задачу, каждый раз свежий?
- [ ] строка про отчётность есть целиком — включая два адреса, которые называет задание субагенту?
- [ ] строка про усиленный режим явная — «не нужен» с причиной либо отрезок с обеими остановками?
- [ ] строка про разбор явная — проверка либо «не нужен» с причиной и то, что её возвращает?
- [ ] развилки конкретные, взятые из плана, а не общие советы?
- [ ] в блоке 8 есть приглашение возразить до начала — бесплатное даже тогда, когда оно отменяет
      распоряжение, — и требование отделять проверенное от предполагаемого в отчётах?
- [ ] заголовок называет действие?
- [ ] читатель без всякого другого контекста сможет это выполнить?
- [ ] если в настройке есть канал согласования — объявление на старте (до любой правки) в блоке 4,
      сдача в блоке 9 и подставленный адрес именно этого потока, а не заглушка?

Доставка:

- [ ] постоянный файл правил из настройки проверен — существует, либо его отсутствие названо один
      раз в итоге, с предложением готового блока?
- [ ] план в папке из раздела `## Plans` несёт раздел с правилами для всех потоков — либо его
      отсутствие названо один раз, с предложением его добавить?
- [ ] план несёт раздел `## Wave Loose Ends` — адрес, на который ссылаются отказы самого канала, —
      либо его отсутствие названо один раз, с предложением его добавить?
- [ ] карта и задания напечатаны прямо в этом ответе, копируются без открытия файлов?
- [ ] каждое задание под заголовком, называющим момент запуска?

Любое «нет» — починить до показа. Черновик не показывать никогда.

Закрытие волны — только в этом режиме:

- [ ] состояние потоков спрошено у канала, а не угадано по именам папок и веток?
- [ ] каждый остаток — отдельным пунктом с готовым текстом запуска НОВОЙ вкладки?
- [ ] то, что выяснить не удалось, названо неизвестным, а не опущено?

## Шаг 7. Закрыть волну: свести всё, что осталось

Волна заканчивается так же, как начиналась, — руками, и закрывающего вопроса не задаёт никто. Карта
строится один раз, в начале, а вся механика набора работает, только пока вкладки ЖИВЫ.

То, что остаётся после, невидимо по устройству. Задача, которую поток бросил, не даёт ни конфликта
слияния, ни красных тестов, ни двойной работы: её просто нет, и потеря всплывает волну спустя, если
всплывает вообще. Находка, адресованная потоку, который успели сдать, остаётся на доске — получать
её некому. Ящик, не разобранный при сдаче, уходит вместе с потоком.

Спрашивать канал — не угадывать и не читать состояние по именам папок:

- `pwsh scripts/wave-board.ps1 -Mode Streams -Wave <волна>` — кто какой поток вёл, какие сданы, у
  каких адресов две ведущие записи или ни одной;
- `pwsh scripts/wave-board.ps1 -Mode Show` — что осталось открытым на доске и что застряло, потому
  что адресат закрыт.

Затем сверить задачи плана с историей слияний, как в шаге 4.3, и прямо сказать, где сверка
приблизительна.

Три вида остатка, каждый — отдельным пунктом:

- задача, которую никто не доделал и никто не ведёт сейчас, — в том числе оставленная сданным
  потоком незакрытой;
- находка на доске, адресат которой закрыт: она не придёт уже никогда;
- поток, сданный с непустым ящиком: то, что в нём лежало, не ушло никуда.

Каждый пункт кладётся в раздел плана `## Wave Loose Ends`, и каждый несёт готовый текст запуска
НОВОЙ вкладки. Строкой в чьей-то задаче тут не обойтись: потока, которому она принадлежала, больше
нет, а правка плана до живых вкладок и так не доходит. Раздела нет — завести его или сказать об этом
и предложить.

Тот же список напечатать в ответе и закончить единственной строкой, ради которой всё: волна
закончена — или у неё есть открытые концы, и вот кому их подбирать.

## Формат вывода

Карта и задания печатаются в самом ответе. Они и есть ответ, а не документ, написанный рядом:
владелец копирует каждое задание прямо из окна перед собой в новую вкладку, не открывая сперва файл.

1. Итоговый абзац: сколько потоков, почему разбивка такая, нашлась ли настройка и — только если
   чего-то не хватает — что постоянного файла правил или раздела правил в плане нет.
2. Таблица.
3. Схема, плюс строка состояния, если план частично сделан.
4. По блоку на поток, в порядке номеров, каждый под заголовком вида «Поток N — начинать сейчас»,
   когда его ничто не держит, или «Поток N — после слияния потока M», когда держит, с перечислением
   всех, кого он ждёт («Поток 8 — после слияния потоков 5, 6, 7»). Заголовок несёт момент запуска,
   поэтому по одним заголовкам видно, какие вкладки открывать сегодня; название работы — это
   собственный заголовок задания, первая строка внутри блока. Каждое задание в огороженном блоке,
   чтобы одним движением копировалось целиком. Пропускается, когда просили только карту.
5. Одна закрывающая строка: какие потоки можно открывать прямо сейчас.

Закрытие волны печатает совсем другое: состояние каждого потока так, как его называет канал, остатки
по видам, куда каждый записан, и одну закрывающую строку — волна закончена либо у неё есть открытые
концы и вот кому их подбирать. Ни карты, ни заданий.

Попросили ещё и файл — написать файл и всё равно напечатать всё здесь.

Порядок запуска прозой не пересказывать: его уже несут таблица, схема и заголовки.

