Три задачи в temp-репозитории: implementer'ы deepseek-flash, все ревью deepseek-v4-pro. Ревьюер Task 2 независимо нашёл T2.1 (медиана чётной длины противоречит спеке) и T2.2 (нет теста), fix-раунд 1 → 186575c, скоуп-ре-ревью APPROVED, финальное ревью ветки APPROVED. Режим 2 (фоновый контроллер, глубина 2) проверен отдельной пробой: вызов subagent из контроллера прошёл. Артефакты прогона — openspec/changes/dsh-sdd/trial/ (план, спека, брифы, отчёты, ledger), результаты — design.md. По урокам прогона skill sdd уточнён: DONE_WITH_CONCERNS при замеченном расхождении, число тестов в плане — ориентир, повтор при ошибке валидации provider/model. Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
227 lines
18 KiB
Markdown
227 lines
18 KiB
Markdown
# Design: DSH-native SDD
|
||
|
||
## Context
|
||
|
||
Claude-SDD (`~/.dsh/skills/subagent-driven-development/SKILL.md`) опирается на
|
||
синхронный `Task`: контроллер вызвал implementer'а и в том же ходе получил
|
||
отчёт. DSH так не умеет — и это не деталь, а другая форма исполнения.
|
||
|
||
Что измерено в DSH 0.2.1-rc.3 (`@deepseek-ai/dsh-tool-subagent`,
|
||
`dsh-subagent`, `dsh-tool-workflow`, `dsh-workflow-ptc`):
|
||
|
||
| Свойство | Значение в DSH | Следствие для SDD |
|
||
|---|---|---|
|
||
| `subagent` возвращает | `started subagent <id>` сразу, результат — уведомлением позже | нет синхронного ожидания; ход контроллера заканчивается |
|
||
| Продолжение ребёнка | `send_message` (провайдер `spawn` continuable) | раунды фикса идут в того же implementer'а |
|
||
| `subagent_fork` | наследует завершённые ходы родителя | для implementer'а не годится: нужен свежий контекст |
|
||
| `subagent.maxDepth` | по умолчанию **1** (настройка сервиса, volatile) | контроллер-сабагент не позовёт implementer'а, пока не поднято до 2 |
|
||
| Выбор модели у `subagent` | только при `modelSelectionSettings: true` на строке `tool-subagent`; иначе ребёнок наследует модель сессии | «укажи модель в dispatch» невыполнимо без правки профиля |
|
||
| `workflow` | синхронный, один вызов инструмента; `agent(prompt, {schema, provider, model, label, phase})` | годится для детерминированного fan-out с выбором модели без настроек |
|
||
| Кэпы `workflow` | `maxTotalAgents`, `maxConcurrentAgents`, `maxItemsPerCall` | backstop для веера; для 3 задач не упираемся |
|
||
| Наблюдение за детьми | `list_agents`, `interrupt_agent`, уведомления | «дождаться» = закончить ход и проснуться от уведомления |
|
||
| Модели в окружении | `deepseek-official/deepseek-flash`, `deepseek-official/deepseek-v4-pro` | три тира роли схлопываются в два |
|
||
|
||
Строка `subagent-model-selection-settings` есть в web/desktop-профиле и
|
||
отсутствует в headless. Поэтому флаг `modelSelectionSettings` нельзя ставить в
|
||
бандл: headless упадёт на загрузке с «requires … in the Host scope». Он живёт
|
||
в opt-in overlay профиля.
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals**
|
||
- Инструкция, по которой DSH-сессия исполняет план без вранья о возможностях
|
||
платформы: два режима контроллера, протокол отчётов, ревью задачи, fix-loop,
|
||
ledger с `## Findings`, финальное ревью.
|
||
- Проверяемый прогон: план из 3 задач в temp-репозитории, дефект найден
|
||
ревьюером и закрыт в fix-loop.
|
||
- Тесты, идущие без DSH runtime.
|
||
- Явная таблица отличий от Claude-SDD.
|
||
|
||
**Non-Goals**
|
||
- Паритет с `Task`: его не будет, и это фиксируется, а не имитируется.
|
||
- Переписывание `~/.dsh/skills/subagent-driven-development/` — skill
|
||
superpowers остаётся как есть; DSH-семантика живёт в отдельном skill.
|
||
- Правка `roles/dev.md` в общем слое: роль для DSH — слой `~/.dsh/roles`.
|
||
- Автоматическое включение выбора модели и глубины: это решение владельца.
|
||
|
||
## Решения владельца (brainstorming 24.10.2026)
|
||
|
||
- **Режим контроллера зависит от контекста, а не один на всех.**
|
||
Одна сложная задача — контроллер главная сессия. Несколько задач параллельно,
|
||
каждая по SDD, — контроллер фоновый сабагент на задачу.
|
||
|
||
## Design
|
||
|
||
### Режим 1 — главная сессия контроллер
|
||
|
||
Главная сессия читает план, ведёт ledger, диспатчит `subagent` (depth 1,
|
||
укладывается в дефолтный `maxDepth: 1`), получает уведомление, диспатчит
|
||
ревьюера, при находках — `send_message` implementer'у. Плюс: рулинги по
|
||
конфликтам плана принимает тот, у кого есть спека и контекст. Минус: контекст
|
||
главной сессии растёт, поэтому отчёты — файлами, а в контекст возвращается
|
||
только статус, коммиты и одна строка тестов.
|
||
|
||
### Режим 2 — фоновый контроллер
|
||
|
||
Один `subagent` на план, `maxDepth: 2`. Контроллер не блокируется: диспатч
|
||
implementer'а возвращает id, ход заканчивается, уведомление о завершении
|
||
начинает следующий ход. Пропущенное уведомление ловится `list_agents` перед
|
||
следующим диспатчем. Главная сессия в это время свободна для другой задачи.
|
||
|
||
### Протокол (общий для обоих режимов)
|
||
|
||
1. Setup: ledger `.superpowers/sdd/<plan>/progress.md`, первая строка —
|
||
путь плана; скан плана на конфликты (таблица в ledger, рулинги до Task 1).
|
||
2. Dispatch implementer'а: brief файлом, отчёт файлом, контракт — `DONE`,
|
||
`DONE_WITH_CONCERNS`, `NEEDS_CONTEXT`, `BLOCKED`.
|
||
3. Ревью задачи: пакет диффа файлом, вердикт по спеке и по качеству, находки
|
||
`T<n>.<k>`.
|
||
4. Fix-loop до 5 раундов: раунды 1–3 — тот же implementer через
|
||
`send_message`, 4–5 — свежий и на тир выше; затем адъюдикация.
|
||
5. Финальное ревью ветки: `C-n`/`I-n`/`M-n`, один fix-диспатч, одно
|
||
скоуп-ревью.
|
||
6. Ledger: `## Findings` с маркером и статусом; рулинги `R-n (design #n)`.
|
||
|
||
### Модели
|
||
|
||
Два маршрута вместо трёх тиров:
|
||
|
||
| Роль в SDD | Маршрут | Почему |
|
||
|---|---|---|
|
||
| implementer по готовому коду из плана | `deepseek-official/deepseek-flash` | транскрипция + тесты |
|
||
| implementer по прозе, интеграция | `deepseek-official/deepseek-v4-pro` | решение в нескольких файлах |
|
||
| ревью задачи, ре-ревью | `deepseek-official/deepseek-v4-pro` | вердикт важнее цены |
|
||
| финальное ревью ветки | `deepseek-official/deepseek-v4-pro` | самый широкий дифф |
|
||
|
||
Без overlay всё идёт на модели сессии (`deepseek-flash`); тиры становятся
|
||
недоступны, и инструкция это явно говорит, а не молча игнорирует.
|
||
|
||
### Где живёт
|
||
|
||
`dsh/skills/sdd/SKILL.md` — в репозитории обвязки, ставится
|
||
`dsh/install.sh --skills` в `~/.dsh/skills`. Claude Code его не получает:
|
||
DoD порта требует, чтобы CC-харнес не менялся.
|
||
|
||
## Альтернативы
|
||
|
||
- **Только workflow.** Детерминированный fan-out силён для независимых задач,
|
||
но решения по конфликтам плана, адъюдикация находок и «стоп, план врёт»
|
||
требуют суждения в моменте. Скрипт может ветвиться по структурному ответу
|
||
ревьюера, но не может решить, что находка неверна.
|
||
- **Только фоновый контроллер.** Дороже на одну задачу и требует поднятой
|
||
глубины; для одиночной задачи лишний уровень.
|
||
- **Гибрид.** `workflow` — для веера независимых задач внутри плана,
|
||
контроллер — для последовательной петли. Держим как расширение, в первой
|
||
версии не включаем: веер ещё не встречался в планах этого репозитория.
|
||
|
||
## Риски
|
||
|
||
- Уведомление о завершении ребёнка не пришло (обрыв, компакция) — контроллер
|
||
обязан сверяться с `list_agents` и git, а не с памятью.
|
||
- `maxDepth: 2` не поднят, а режим 2 выбран — диспатч упадёт
|
||
`subagent depth 2 exceeds maxDepth 1`; инструкция требует проверить до
|
||
старта и откатиться в режим 1 с записью рулинга.
|
||
- Ledger лежит в git-ignored scratch: `git clean -fdx` его уничтожает;
|
||
восстановление — по `git log`.
|
||
- Модели две: «haiku» из Claude-текста не существует, перенос формулировок
|
||
тиров без таблицы превратится в фикцию.
|
||
|
||
## Что должен доказать пробный прогон
|
||
|
||
| Пункт приёмки #41 | Чем доказывается |
|
||
|---|---|
|
||
| 3 задачи не теряются | ledger: три `Task N: complete`, три коммита |
|
||
| отчёты собираются | файлы отчётов implementer'ов + строки в ledger |
|
||
| ревьюер находит дефект | `T1.1` с `fixed <commit>` |
|
||
| fix-loop завершается | раунд в ledger, ре-ревью чистое |
|
||
| ledger содержит `## Findings` со статусами | сам файл |
|
||
| отличие от Claude-SDD указано | таблица выше + раздел в skill |
|
||
|
||
## Результаты пробного прогона 24.10.2026
|
||
|
||
Площадка — `/tmp/dsh-sdd-trial`: отдельный git-репозиторий, ветка `feat/trial`,
|
||
база `main`; модуль `src/stats.py` из трёх задач. Контроллер — главная сессия
|
||
(Режим 1), overlay профиля включён (`model selection` + `maxDepth: 2`),
|
||
`deepseek-flash` — implementer'ы, `deepseek-v4-pro` — все ревью. Артефакты
|
||
скопированы в `trial/`: `SPEC.md`, `plan.md`, брифы, отчёты implementer'ов и
|
||
ревьюеров, `ledger.md` (первая строка — путь плана, `## Findings`, `## Rulings`).
|
||
|
||
### Диспатчи
|
||
|
||
| Шаг | Агент | Маршрут | Результат |
|
||
|---|---|---|---|
|
||
| Task 1 implementer | `1c906f6f` | flash | `DONE`, `dc1670f`, 2 теста OK |
|
||
| Task 1 review | `68a1aeb4` | v4-pro | `APPROVED`, находок нет |
|
||
| Task 2 implementer | `1ec8f7fc` | flash | `DONE`, `836a730`, 4 теста OK, concern: план противоречит спеке на чётной длине |
|
||
| Task 2 review | `e50c74d2` | v4-pro | `CHANGES_REQUESTED`: `T2.1`, `T2.2` (проверено независимо от concerns) |
|
||
| Task 2 fix, раунд 1 | `1ec8f7fc` (send_message) | flash | `186575c`, 6 тестов OK |
|
||
| Task 2 re-review (скоуп) | `7912c16b` | v4-pro | `APPROVED`: `T2.1 fixed 186575c`, `T2.2 fixed 186575c` |
|
||
| Task 3 implementer | `6ca07edc` | flash | `DONE`, `7cb0383`, 7 тестов OK |
|
||
| Task 3 review | `f10e3165` | v4-pro | `APPROVED`, находок нет |
|
||
| Final branch review | `0fec8102` | v4-pro | `APPROVED`, находок нет |
|
||
|
||
### Приёмка #41
|
||
|
||
| Пункт приёмки | Чем доказан | Статус |
|
||
|---|---|---|
|
||
| 3 задачи не теряются | ledger `Task 1..3: complete`, 4 коммита `dc1670f`/`836a730`/`186575c`/`7cb0383` | выполнен |
|
||
| отчёты собираются | 9 файлов в `trial/reports/`, статус первой строкой у каждого | выполнен |
|
||
| ревьюер находит и проверяет дефект | `T2.1` найден независимо (`median([1,2]) == 2.0` вместо `1.5`), `T2.2` — отсутствие теста; оба `fixed 186575c`, ре-ревью APPROVED | выполнен |
|
||
| fix-loop завершается | раунд 1 из 5, ре-ревью чистое | выполнен |
|
||
| ledger содержит `## Findings` со статусами | `trial/ledger.md` | выполнен |
|
||
| итоговый прогон зелёный | `python3 -m unittest discover -s tests` → 7 тестов OK; `bash dsh/tests/run.sh` и `bash tests/run.sh` зелёные | выполнен |
|
||
| отличие от Claude-SDD указано | таблица в `dsh/skills/sdd/SKILL.md` | выполнен |
|
||
|
||
### Находки и наблюдения прогона
|
||
|
||
| Маркер | Что | Статус |
|
||
|---|---|---|
|
||
| `T2.1` | `median` на чётной длине возвращал верхний средний элемент вместо среднего двух | `fixed 186575c` |
|
||
| `T2.2` | не было теста на чётную длину | `fixed 186575c` |
|
||
| `O-1` | «Interfaces» плана обещают аннотации типов, «Exact code» их не содержит; SPEC аннотаций не требует | `rejected` (правка плана в прогоне не даёт результата) |
|
||
| `O-2`, `O-3` | первый вызов `subagent` с переданными `provider`/`model` вернул «child LLM provider and model must be supplied together»; немедленный повтор тем же вызовом проходит (2 раза за прогон) | `deferred` (наблюдение о стабильности валидации DSH; повтор в skill) |
|
||
| `O-4` | ожидаемое число тестов в плане (`5`) устарело после fix-раунда Task 2 (фактически 7) | `fixed` — в skill добавлено правило «число тестов в плане — ориентир» |
|
||
| `O-5` | тест `describe([1,2,3])` на симметричном входе не отличил бы перестановку `mean`/`median` | `deferred` (реализация верна, слабость плана) |
|
||
|
||
Отдельно: implementer Task 2 заметил расхождение плана со спекой, но поставил
|
||
`DONE`, а не `DONE_WITH_CONCERNS`; ревью дефект всё равно поймало, потому что
|
||
ревьюер проверял по `SPEC.md`, а не по отчёту. Правило уточнено в skill:
|
||
замеченное расхождение с брифом — это `DONE_WITH_CONCERNS`.
|
||
|
||
### Режим 2 (фоновый контроллер)
|
||
|
||
Отдельная площадка `/tmp/dsh-sdd-mode2`. Контроллер `afe886e5` (flash) вызвал
|
||
`subagent` (flash) и получил id; ход закончился, уведомление о завершении пришло
|
||
отдельным сообщением, после чего контроллер проверил отчёт, коммит `0601d6e` и
|
||
тесты независимо. Глубина 2 работает с overlay; синхронного ожидания нет.
|
||
|
||
### Отличия от дизайна, обнаруженные прогоном
|
||
|
||
- Число тестов в плане — ориентир: fix-раунд добавляет тесты, и расхождение
|
||
вверх не дефект (O-4).
|
||
- Ошибка валидации `provider`/`model` нестабильна; лечится повтором, а не
|
||
пересмотром маршрутов (O-2/O-3).
|
||
- Ревьюер, проверяющий по спеке, а не по отчёту implementer'а, ловит дефекты,
|
||
даже если implementer промолчал бы.
|
||
|
||
## Decisions made without discussion
|
||
|
||
- **24.10.2026 — overlay вместо флага в бандле.** Обоснование: headless-профиль
|
||
не содержит строку `subagent-model-selection-settings`, включённый флаг роняет
|
||
загрузку. Цена ошибки: владельцу нужно скопировать три записи в профиль
|
||
руками; забыл — работает на модели сессии.
|
||
- **24.10.2026 — карта тиров.** `flash` — транскрипция и механика, `v4-pro` —
|
||
интеграция и все ревью. Цена ошибки: дороже прогон или слабее ревью; правится
|
||
одной таблицей в skill.
|
||
- **24.10.2026 — skill ставится только в `~/.dsh`.** Обоснование: DoD порта
|
||
запрещает менять CC-харнес. Цена ошибки: в Claude-сессиях инструкции про
|
||
DSH-режимы нет — там работает исходный `subagent-driven-development`.
|
||
- **24.10.2026 — гибрид отложен.** `workflow` описан как расширение, не
|
||
реализуется в этом change. Цена ошибки: веер задач придётся ввести позже
|
||
отдельной правкой skill.
|
||
|
||
## Открытые вопросы
|
||
|
||
- Нужно ли после приёмки добавить в `~/.dsh/roles/dev.md` строку «в DSH
|
||
исполнение плана — skill `sdd`» (сейчас роль ссылается на superpowers-SDD).
|