Andrey Epifancev 3ad378c1dc chore(openspec): archive dsh-sdd (#41)
Change dsh-sdd перенесён в openspec/changes/archive/2026-10-24-dsh-sdd,
дельта dsh-sdd добавлена в openspec/specs/dsh-sdd/spec.md (7 требований).

Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
2026-10-24 17:57:35 +04:00

18 KiB
Raw Blame History

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).